(diff-auto-refine-mode): Remove lighter, since it's
[emacs.git] / src / image.c
blob5c8748eefba11ed8afed0b7b20d445041d0ec206
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 #ifdef HAVE_NS
135 #include "nsterm.h"
136 #include <sys/types.h>
137 #include <sys/stat.h>
139 #undef COLOR_TABLE_SUPPORT
141 typedef struct ns_bitmap_record Bitmap_Record;
143 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
144 #define NO_PIXMAP 0
146 #define RGB_PIXEL_COLOR unsigned long
147 #define ZPixmap 0
149 #define PIX_MASK_RETAIN 0
150 #define PIX_MASK_DRAW 1
152 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
153 #define x_defined_color(f, name, color_def, alloc) \
154 ns_defined_color (f, name, color_def, alloc, 0)
155 #define FRAME_X_SCREEN(f) 0
156 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
157 #endif /* HAVE_NS */
160 /* Search path for bitmap files. */
162 Lisp_Object Vx_bitmap_file_path;
165 static void x_disable_image P_ ((struct frame *, struct image *));
166 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
167 Lisp_Object));
169 static void init_color_table P_ ((void));
170 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
171 #ifdef COLOR_TABLE_SUPPORT
172 static void free_color_table P_ ((void));
173 static unsigned long *colors_in_color_table P_ ((int *n));
174 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
175 #endif
177 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
178 id, which is just an int that this section returns. Bitmaps are
179 reference counted so they can be shared among frames.
181 Bitmap indices are guaranteed to be > 0, so a negative number can
182 be used to indicate no bitmap.
184 If you use x_create_bitmap_from_data, then you must keep track of
185 the bitmaps yourself. That is, creating a bitmap from the same
186 data more than once will not be caught. */
188 #ifdef MAC_OS
190 static XImagePtr
191 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
192 Display *display; /* not used */
193 Pixmap pixmap;
194 int x, y; /* not used */
195 unsigned int width, height; /* not used */
196 unsigned long plane_mask; /* not used */
197 int format; /* not used */
199 #if !USE_MAC_IMAGE_IO
200 #if GLYPH_DEBUG
201 xassert (x == 0 && y == 0);
203 Rect ri, rp;
204 SetRect (&ri, 0, 0, width, height);
205 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
207 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
208 #endif
210 LockPixels (GetGWorldPixMap (pixmap));
211 #endif
213 return pixmap;
216 static void
217 XPutPixel (ximage, x, y, pixel)
218 XImagePtr ximage;
219 int x, y;
220 unsigned long pixel;
222 #if USE_MAC_IMAGE_IO
223 if (ximage->bits_per_pixel == 32)
224 ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
225 else
226 ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
227 #else
228 PixMapHandle pixmap = GetGWorldPixMap (ximage);
229 short depth = GetPixDepth (pixmap);
231 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
232 if (depth == 32)
234 char *base_addr = GetPixBaseAddr (pixmap);
235 short row_bytes = GetPixRowBytes (pixmap);
237 ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
239 else
240 #endif
241 if (depth == 1)
243 char *base_addr = GetPixBaseAddr (pixmap);
244 short row_bytes = GetPixRowBytes (pixmap);
246 if (pixel == PIX_MASK_DRAW)
247 base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
248 else
249 base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
251 else
253 CGrafPtr old_port;
254 GDHandle old_gdh;
255 RGBColor color;
257 GetGWorld (&old_port, &old_gdh);
258 SetGWorld (ximage, NULL);
260 color.red = RED16_FROM_ULONG (pixel);
261 color.green = GREEN16_FROM_ULONG (pixel);
262 color.blue = BLUE16_FROM_ULONG (pixel);
264 SetCPixel (x, y, &color);
266 SetGWorld (old_port, old_gdh);
268 #endif
271 static unsigned long
272 XGetPixel (ximage, x, y)
273 XImagePtr ximage;
274 int x, y;
276 #if USE_MAC_IMAGE_IO
277 if (ximage->bits_per_pixel == 32)
278 return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
279 else
280 return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
281 #else
282 PixMapHandle pixmap = GetGWorldPixMap (ximage);
283 short depth = GetPixDepth (pixmap);
285 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
286 if (depth == 32)
288 char *base_addr = GetPixBaseAddr (pixmap);
289 short row_bytes = GetPixRowBytes (pixmap);
291 return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
293 else
294 #endif
295 if (depth == 1)
297 char *base_addr = GetPixBaseAddr (pixmap);
298 short row_bytes = GetPixRowBytes (pixmap);
300 if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
301 return PIX_MASK_DRAW;
302 else
303 return PIX_MASK_RETAIN;
305 else
307 CGrafPtr old_port;
308 GDHandle old_gdh;
309 RGBColor color;
311 GetGWorld (&old_port, &old_gdh);
312 SetGWorld (ximage, NULL);
314 GetCPixel (x, y, &color);
316 SetGWorld (old_port, old_gdh);
317 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
319 #endif
322 static void
323 XDestroyImage (ximg)
324 XImagePtr ximg;
326 #if !USE_MAC_IMAGE_IO
327 UnlockPixels (GetGWorldPixMap (ximg));
328 #endif
331 #if USE_CG_DRAWING
332 #if USE_MAC_IMAGE_IO
333 void
334 mac_data_provider_release_data (info, data, size)
335 void *info;
336 const void *data;
337 size_t size;
339 xfree ((void *)data);
341 #endif
343 static CGImageRef
344 mac_create_cg_image_from_image (f, img)
345 struct frame *f;
346 struct image *img;
348 #if USE_MAC_IMAGE_IO
349 XImagePtr ximg = img->pixmap;
350 CGDataProviderRef provider;
351 CGImageRef result;
353 if (img->mask)
355 int x, y;
356 unsigned long color, alpha;
358 for (y = 0; y < ximg->height; y++)
359 for (x = 0; x < ximg->width; x++)
361 color = XGetPixel (ximg, x, y);
362 alpha = XGetPixel (img->mask, x, y);
363 XPutPixel (ximg, x, y,
364 ARGB_TO_ULONG (alpha,
365 RED_FROM_ULONG (color)
366 * alpha / PIX_MASK_DRAW,
367 GREEN_FROM_ULONG (color)
368 * alpha / PIX_MASK_DRAW,
369 BLUE_FROM_ULONG (color)
370 * alpha / PIX_MASK_DRAW));
372 xfree (img->mask->data);
373 img->mask->data = NULL;
375 BLOCK_INPUT;
376 provider = CGDataProviderCreateWithData (NULL, ximg->data,
377 ximg->bytes_per_line * ximg->height,
378 mac_data_provider_release_data);
379 ximg->data = NULL;
380 result = CGImageCreate (ximg->width, ximg->height, 8, 32,
381 ximg->bytes_per_line, mac_cg_color_space_rgb,
382 (img->mask ? kCGImageAlphaPremultipliedFirst
383 : kCGImageAlphaNoneSkipFirst)
384 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
385 | kCGBitmapByteOrder32Host
386 #endif
387 , provider, NULL, 0, kCGRenderingIntentDefault);
388 CGDataProviderRelease (provider);
389 UNBLOCK_INPUT;
391 return result;
392 #else
393 Pixmap mask;
394 CGImageRef result = NULL;
396 BLOCK_INPUT;
397 if (img->mask)
398 mask = img->mask;
399 else
401 mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
402 img->width, img->height, 1);
403 if (mask)
405 CGrafPtr old_port;
406 GDHandle old_gdh;
407 Rect r;
409 GetGWorld (&old_port, &old_gdh);
410 SetGWorld (mask, NULL);
411 BackColor (blackColor); /* Don't mask. */
412 SetRect (&r, 0, 0, img->width, img->height);
413 EraseRect (&r);
414 SetGWorld (old_port, old_gdh);
417 if (mask)
419 CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
420 GetGWorldPixMap (mask), &result);
421 if (mask != img->mask)
422 XFreePixmap (FRAME_X_DISPLAY (f), mask);
424 UNBLOCK_INPUT;
426 return result;
427 #endif
429 #endif /* USE_CG_DRAWING */
430 #endif /* MAC_OS */
432 #ifdef HAVE_NS
433 XImagePtr
434 XGetImage (Display *display, Pixmap pixmap, int x, int y,
435 unsigned int width, unsigned int height,
436 unsigned long plane_mask, int format)
438 /* TODO: not sure what this function is supposed to do.. */
439 ns_retain_object(pixmap);
440 return pixmap;
443 /* use with imgs created by ns_image_for_XPM */
444 unsigned long
445 XGetPixel (XImagePtr ximage, int x, int y)
447 return ns_get_pixel(ximage, x, y);
450 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
451 pixel is assumed to be in form RGB */
452 void
453 XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
455 ns_put_pixel(ximage, x, y, pixel);
457 #endif /* HAVE_NS */
460 /* Functions to access the contents of a bitmap, given an id. */
463 x_bitmap_height (f, id)
464 FRAME_PTR f;
465 int id;
467 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
471 x_bitmap_width (f, id)
472 FRAME_PTR f;
473 int id;
475 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
478 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
480 x_bitmap_pixmap (f, id)
481 FRAME_PTR f;
482 int id;
484 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
486 #endif
488 #ifdef HAVE_X_WINDOWS
490 x_bitmap_mask (f, id)
491 FRAME_PTR f;
492 int id;
494 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
496 #endif
498 /* Allocate a new bitmap record. Returns index of new record. */
500 static int
501 x_allocate_bitmap_record (f)
502 FRAME_PTR f;
504 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
505 int i;
507 if (dpyinfo->bitmaps == NULL)
509 dpyinfo->bitmaps_size = 10;
510 dpyinfo->bitmaps
511 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
512 dpyinfo->bitmaps_last = 1;
513 return 1;
516 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
517 return ++dpyinfo->bitmaps_last;
519 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
520 if (dpyinfo->bitmaps[i].refcount == 0)
521 return i + 1;
523 dpyinfo->bitmaps_size *= 2;
524 dpyinfo->bitmaps
525 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
526 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
527 return ++dpyinfo->bitmaps_last;
530 /* Add one reference to the reference count of the bitmap with id ID. */
532 void
533 x_reference_bitmap (f, id)
534 FRAME_PTR f;
535 int id;
537 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
540 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
543 x_create_bitmap_from_data (f, bits, width, height)
544 struct frame *f;
545 char *bits;
546 unsigned int width, height;
548 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
549 int id;
551 #ifdef HAVE_X_WINDOWS
552 Pixmap bitmap;
553 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
554 bits, width, height);
555 if (! bitmap)
556 return -1;
557 #endif /* HAVE_X_WINDOWS */
559 #ifdef HAVE_NTGUI
560 Pixmap bitmap;
561 bitmap = CreateBitmap (width, height,
562 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
563 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
564 bits);
565 if (! bitmap)
566 return -1;
567 #endif /* HAVE_NTGUI */
569 #ifdef MAC_OS
570 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
571 if (width % 16 != 0)
572 return -1;
573 #endif
575 #ifdef HAVE_NS
576 void *bitmap = ns_image_from_XBM(bits, width, height);
577 if (!bitmap)
578 return -1;
579 #endif
581 id = x_allocate_bitmap_record (f);
582 #ifdef MAC_OS
583 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
584 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
585 #endif /* MAC_OS */
587 #ifdef HAVE_NS
588 dpyinfo->bitmaps[id - 1].img = bitmap;
589 dpyinfo->bitmaps[id - 1].depth = 1;
590 #endif
592 dpyinfo->bitmaps[id - 1].file = NULL;
593 dpyinfo->bitmaps[id - 1].height = height;
594 dpyinfo->bitmaps[id - 1].width = width;
595 dpyinfo->bitmaps[id - 1].refcount = 1;
597 #ifdef HAVE_X_WINDOWS
598 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
599 dpyinfo->bitmaps[id - 1].have_mask = 0;
600 dpyinfo->bitmaps[id - 1].depth = 1;
601 #endif /* HAVE_X_WINDOWS */
603 #ifdef HAVE_NTGUI
604 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
605 dpyinfo->bitmaps[id - 1].hinst = NULL;
606 dpyinfo->bitmaps[id - 1].depth = 1;
607 #endif /* HAVE_NTGUI */
609 return id;
612 /* Create bitmap from file FILE for frame F. */
615 x_create_bitmap_from_file (f, file)
616 struct frame *f;
617 Lisp_Object file;
619 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
621 #ifdef MAC_OS
622 return -1; /* MAC_TODO : bitmap support */
623 #endif /* MAC_OS */
625 #ifdef HAVE_NTGUI
626 return -1; /* W32_TODO : bitmap support */
627 #endif /* HAVE_NTGUI */
629 #ifdef HAVE_NS
630 int id;
631 void *bitmap = ns_image_from_file(file);
633 if (!bitmap)
634 return -1;
637 id = x_allocate_bitmap_record (f);
638 dpyinfo->bitmaps[id - 1].img = bitmap;
639 dpyinfo->bitmaps[id - 1].refcount = 1;
640 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
641 dpyinfo->bitmaps[id - 1].depth = 1;
642 dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap);
643 dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap);
644 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
645 return id;
646 #endif
648 #ifdef HAVE_X_WINDOWS
649 unsigned int width, height;
650 Pixmap bitmap;
651 int xhot, yhot, result, id;
652 Lisp_Object found;
653 int fd;
654 char *filename;
656 /* Look for an existing bitmap with the same name. */
657 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
659 if (dpyinfo->bitmaps[id].refcount
660 && dpyinfo->bitmaps[id].file
661 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
663 ++dpyinfo->bitmaps[id].refcount;
664 return id + 1;
668 /* Search bitmap-file-path for the file, if appropriate. */
669 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
670 if (fd < 0)
671 return -1;
672 emacs_close (fd);
674 filename = (char *) SDATA (found);
676 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
677 filename, &width, &height, &bitmap, &xhot, &yhot);
678 if (result != BitmapSuccess)
679 return -1;
681 id = x_allocate_bitmap_record (f);
682 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
683 dpyinfo->bitmaps[id - 1].have_mask = 0;
684 dpyinfo->bitmaps[id - 1].refcount = 1;
685 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
686 dpyinfo->bitmaps[id - 1].depth = 1;
687 dpyinfo->bitmaps[id - 1].height = height;
688 dpyinfo->bitmaps[id - 1].width = width;
689 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
691 return id;
692 #endif /* HAVE_X_WINDOWS */
695 /* Free bitmap B. */
697 static void
698 free_bitmap_record (dpyinfo, bm)
699 Display_Info *dpyinfo;
700 Bitmap_Record *bm;
702 #ifdef HAVE_X_WINDOWS
703 XFreePixmap (dpyinfo->display, bm->pixmap);
704 if (bm->have_mask)
705 XFreePixmap (dpyinfo->display, bm->mask);
706 #endif /* HAVE_X_WINDOWS */
708 #ifdef HAVE_NTGUI
709 DeleteObject (bm->pixmap);
710 #endif /* HAVE_NTGUI */
712 #ifdef MAC_OS
713 xfree (bm->bitmap_data); /* Added ++kfs */
714 bm->bitmap_data = NULL;
715 #endif /* MAC_OS */
717 #ifdef HAVE_NS
718 ns_release_object(bm->img);
719 #endif
721 if (bm->file)
723 xfree (bm->file);
724 bm->file = NULL;
728 /* Remove reference to bitmap with id number ID. */
730 void
731 x_destroy_bitmap (f, id)
732 FRAME_PTR f;
733 int id;
735 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
737 if (id > 0)
739 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
741 if (--bm->refcount == 0)
743 BLOCK_INPUT;
744 free_bitmap_record (dpyinfo, bm);
745 UNBLOCK_INPUT;
750 /* Free all the bitmaps for the display specified by DPYINFO. */
752 void
753 x_destroy_all_bitmaps (dpyinfo)
754 Display_Info *dpyinfo;
756 int i;
757 Bitmap_Record *bm = dpyinfo->bitmaps;
759 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
760 if (bm->refcount > 0)
761 free_bitmap_record (dpyinfo, bm);
763 dpyinfo->bitmaps_last = 0;
767 #ifdef HAVE_X_WINDOWS
769 /* Useful functions defined in the section
770 `Image type independent image structures' below. */
772 static unsigned long four_corners_best P_ ((XImagePtr ximg,
773 int *corners,
774 unsigned long width,
775 unsigned long height));
777 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
778 int depth, XImagePtr *ximg,
779 Pixmap *pixmap));
781 static void x_destroy_x_image P_ ((XImagePtr ximg));
784 /* Create a mask of a bitmap. Note is this not a perfect mask.
785 It's nicer with some borders in this context */
788 x_create_bitmap_mask (f, id)
789 struct frame *f;
790 int id;
792 Pixmap pixmap, mask;
793 XImagePtr ximg, mask_img;
794 unsigned long width, height;
795 int result;
796 unsigned long bg;
797 unsigned long x, y, xp, xm, yp, ym;
798 GC gc;
800 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
802 if (!(id > 0))
803 return -1;
805 pixmap = x_bitmap_pixmap (f, id);
806 width = x_bitmap_width (f, id);
807 height = x_bitmap_height (f, id);
809 BLOCK_INPUT;
810 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
811 ~0, ZPixmap);
813 if (!ximg)
815 UNBLOCK_INPUT;
816 return -1;
819 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
821 UNBLOCK_INPUT;
822 if (!result)
824 XDestroyImage (ximg);
825 return -1;
828 bg = four_corners_best (ximg, NULL, width, height);
830 for (y = 0; y < ximg->height; ++y)
832 for (x = 0; x < ximg->width; ++x)
834 xp = x != ximg->width - 1 ? x + 1 : 0;
835 xm = x != 0 ? x - 1 : ximg->width - 1;
836 yp = y != ximg->height - 1 ? y + 1 : 0;
837 ym = y != 0 ? y - 1 : ximg->height - 1;
838 if (XGetPixel (ximg, x, y) == bg
839 && XGetPixel (ximg, x, yp) == bg
840 && XGetPixel (ximg, x, ym) == bg
841 && XGetPixel (ximg, xp, y) == bg
842 && XGetPixel (ximg, xp, yp) == bg
843 && XGetPixel (ximg, xp, ym) == bg
844 && XGetPixel (ximg, xm, y) == bg
845 && XGetPixel (ximg, xm, yp) == bg
846 && XGetPixel (ximg, xm, ym) == bg)
847 XPutPixel (mask_img, x, y, 0);
848 else
849 XPutPixel (mask_img, x, y, 1);
853 xassert (interrupt_input_blocked);
854 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
855 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
856 width, height);
857 XFreeGC (FRAME_X_DISPLAY (f), gc);
859 dpyinfo->bitmaps[id - 1].have_mask = 1;
860 dpyinfo->bitmaps[id - 1].mask = mask;
862 XDestroyImage (ximg);
863 x_destroy_x_image (mask_img);
865 return 0;
868 #endif /* HAVE_X_WINDOWS */
871 /***********************************************************************
872 Image types
873 ***********************************************************************/
875 /* Value is the number of elements of vector VECTOR. */
877 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
879 /* List of supported image types. Use define_image_type to add new
880 types. Use lookup_image_type to find a type for a given symbol. */
882 static struct image_type *image_types;
884 /* A list of symbols, one for each supported image type. */
886 Lisp_Object Vimage_types;
888 /* An alist of image types and libraries that implement the type. */
890 Lisp_Object Vimage_library_alist;
892 /* Cache for delayed-loading image types. */
894 static Lisp_Object Vimage_type_cache;
896 /* The symbol `xbm' which is used as the type symbol for XBM images. */
898 Lisp_Object Qxbm;
900 /* Keywords. */
902 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
903 extern Lisp_Object QCdata, QCtype;
904 extern Lisp_Object Qcenter;
905 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
906 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
907 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
909 /* Other symbols. */
911 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
913 /* Time in seconds after which images should be removed from the cache
914 if not displayed. */
916 Lisp_Object Vimage_cache_eviction_delay;
918 /* Function prototypes. */
920 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
921 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
922 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
923 static void x_laplace P_ ((struct frame *, struct image *));
924 static void x_emboss P_ ((struct frame *, struct image *));
925 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
926 Lisp_Object));
928 #define CACHE_IMAGE_TYPE(type, status) \
929 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
931 #define ADD_IMAGE_TYPE(type) \
932 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
934 /* Define a new image type from TYPE. This adds a copy of TYPE to
935 image_types and caches the loading status of TYPE. */
937 static Lisp_Object
938 define_image_type (type, loaded)
939 struct image_type *type;
940 int loaded;
942 Lisp_Object success;
944 if (!loaded)
945 success = Qnil;
946 else
948 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
949 The initialized data segment is read-only. */
950 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
951 bcopy (type, p, sizeof *p);
952 p->next = image_types;
953 image_types = p;
954 success = Qt;
957 CACHE_IMAGE_TYPE (*type->type, success);
958 return success;
962 /* Look up image type SYMBOL, and return a pointer to its image_type
963 structure. Value is null if SYMBOL is not a known image type. */
965 static INLINE struct image_type *
966 lookup_image_type (symbol)
967 Lisp_Object symbol;
969 struct image_type *type;
971 /* We must initialize the image-type if it hasn't been already. */
972 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
973 return 0; /* unimplemented */
975 for (type = image_types; type; type = type->next)
976 if (EQ (symbol, *type->type))
977 break;
979 return type;
983 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
984 valid image specification is a list whose car is the symbol
985 `image', and whose rest is a property list. The property list must
986 contain a value for key `:type'. That value must be the name of a
987 supported image type. The rest of the property list depends on the
988 image type. */
991 valid_image_p (object)
992 Lisp_Object object;
994 int valid_p = 0;
996 if (IMAGEP (object))
998 Lisp_Object tem;
1000 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
1001 if (EQ (XCAR (tem), QCtype))
1003 tem = XCDR (tem);
1004 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
1006 struct image_type *type;
1007 type = lookup_image_type (XCAR (tem));
1008 if (type)
1009 valid_p = type->valid_p (object);
1012 break;
1016 return valid_p;
1020 /* Log error message with format string FORMAT and argument ARG.
1021 Signaling an error, e.g. when an image cannot be loaded, is not a
1022 good idea because this would interrupt redisplay, and the error
1023 message display would lead to another redisplay. This function
1024 therefore simply displays a message. */
1026 static void
1027 image_error (format, arg1, arg2)
1028 char *format;
1029 Lisp_Object arg1, arg2;
1031 add_to_log (format, arg1, arg2);
1036 /***********************************************************************
1037 Image specifications
1038 ***********************************************************************/
1040 enum image_value_type
1042 IMAGE_DONT_CHECK_VALUE_TYPE,
1043 IMAGE_STRING_VALUE,
1044 IMAGE_STRING_OR_NIL_VALUE,
1045 IMAGE_SYMBOL_VALUE,
1046 IMAGE_POSITIVE_INTEGER_VALUE,
1047 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
1048 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
1049 IMAGE_ASCENT_VALUE,
1050 IMAGE_INTEGER_VALUE,
1051 IMAGE_FUNCTION_VALUE,
1052 IMAGE_NUMBER_VALUE,
1053 IMAGE_BOOL_VALUE
1056 /* Structure used when parsing image specifications. */
1058 struct image_keyword
1060 /* Name of keyword. */
1061 char *name;
1063 /* The type of value allowed. */
1064 enum image_value_type type;
1066 /* Non-zero means key must be present. */
1067 int mandatory_p;
1069 /* Used to recognize duplicate keywords in a property list. */
1070 int count;
1072 /* The value that was found. */
1073 Lisp_Object value;
1077 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
1078 int, Lisp_Object));
1079 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
1082 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1083 has the format (image KEYWORD VALUE ...). One of the keyword/
1084 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1085 image_keywords structures of size NKEYWORDS describing other
1086 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1088 static int
1089 parse_image_spec (spec, keywords, nkeywords, type)
1090 Lisp_Object spec;
1091 struct image_keyword *keywords;
1092 int nkeywords;
1093 Lisp_Object type;
1095 int i;
1096 Lisp_Object plist;
1098 if (!IMAGEP (spec))
1099 return 0;
1101 plist = XCDR (spec);
1102 while (CONSP (plist))
1104 Lisp_Object key, value;
1106 /* First element of a pair must be a symbol. */
1107 key = XCAR (plist);
1108 plist = XCDR (plist);
1109 if (!SYMBOLP (key))
1110 return 0;
1112 /* There must follow a value. */
1113 if (!CONSP (plist))
1114 return 0;
1115 value = XCAR (plist);
1116 plist = XCDR (plist);
1118 /* Find key in KEYWORDS. Error if not found. */
1119 for (i = 0; i < nkeywords; ++i)
1120 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
1121 break;
1123 if (i == nkeywords)
1124 continue;
1126 /* Record that we recognized the keyword. If a keywords
1127 was found more than once, it's an error. */
1128 keywords[i].value = value;
1129 ++keywords[i].count;
1131 if (keywords[i].count > 1)
1132 return 0;
1134 /* Check type of value against allowed type. */
1135 switch (keywords[i].type)
1137 case IMAGE_STRING_VALUE:
1138 if (!STRINGP (value))
1139 return 0;
1140 break;
1142 case IMAGE_STRING_OR_NIL_VALUE:
1143 if (!STRINGP (value) && !NILP (value))
1144 return 0;
1145 break;
1147 case IMAGE_SYMBOL_VALUE:
1148 if (!SYMBOLP (value))
1149 return 0;
1150 break;
1152 case IMAGE_POSITIVE_INTEGER_VALUE:
1153 if (!INTEGERP (value) || XINT (value) <= 0)
1154 return 0;
1155 break;
1157 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
1158 if (INTEGERP (value) && XINT (value) >= 0)
1159 break;
1160 if (CONSP (value)
1161 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
1162 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
1163 break;
1164 return 0;
1166 case IMAGE_ASCENT_VALUE:
1167 if (SYMBOLP (value) && EQ (value, Qcenter))
1168 break;
1169 else if (INTEGERP (value)
1170 && XINT (value) >= 0
1171 && XINT (value) <= 100)
1172 break;
1173 return 0;
1175 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
1176 if (!INTEGERP (value) || XINT (value) < 0)
1177 return 0;
1178 break;
1180 case IMAGE_DONT_CHECK_VALUE_TYPE:
1181 break;
1183 case IMAGE_FUNCTION_VALUE:
1184 value = indirect_function (value);
1185 if (SUBRP (value)
1186 || COMPILEDP (value)
1187 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
1188 break;
1189 return 0;
1191 case IMAGE_NUMBER_VALUE:
1192 if (!INTEGERP (value) && !FLOATP (value))
1193 return 0;
1194 break;
1196 case IMAGE_INTEGER_VALUE:
1197 if (!INTEGERP (value))
1198 return 0;
1199 break;
1201 case IMAGE_BOOL_VALUE:
1202 if (!NILP (value) && !EQ (value, Qt))
1203 return 0;
1204 break;
1206 default:
1207 abort ();
1208 break;
1211 if (EQ (key, QCtype) && !EQ (type, value))
1212 return 0;
1215 /* Check that all mandatory fields are present. */
1216 for (i = 0; i < nkeywords; ++i)
1217 if (keywords[i].mandatory_p && keywords[i].count == 0)
1218 return 0;
1220 return NILP (plist);
1224 /* Return the value of KEY in image specification SPEC. Value is nil
1225 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1226 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1228 static Lisp_Object
1229 image_spec_value (spec, key, found)
1230 Lisp_Object spec, key;
1231 int *found;
1233 Lisp_Object tail;
1235 xassert (valid_image_p (spec));
1237 for (tail = XCDR (spec);
1238 CONSP (tail) && CONSP (XCDR (tail));
1239 tail = XCDR (XCDR (tail)))
1241 if (EQ (XCAR (tail), key))
1243 if (found)
1244 *found = 1;
1245 return XCAR (XCDR (tail));
1249 if (found)
1250 *found = 0;
1251 return Qnil;
1255 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
1256 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1257 PIXELS non-nil means return the size in pixels, otherwise return the
1258 size in canonical character units.
1259 FRAME is the frame on which the image will be displayed. FRAME nil
1260 or omitted means use the selected frame. */)
1261 (spec, pixels, frame)
1262 Lisp_Object spec, pixels, frame;
1264 Lisp_Object size;
1266 size = Qnil;
1267 if (valid_image_p (spec))
1269 struct frame *f = check_x_frame (frame);
1270 int id = lookup_image (f, spec);
1271 struct image *img = IMAGE_FROM_ID (f, id);
1272 int width = img->width + 2 * img->hmargin;
1273 int height = img->height + 2 * img->vmargin;
1275 if (NILP (pixels))
1276 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
1277 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
1278 else
1279 size = Fcons (make_number (width), make_number (height));
1281 else
1282 error ("Invalid image specification");
1284 return size;
1288 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
1289 doc: /* Return t if image SPEC has a mask bitmap.
1290 FRAME is the frame on which the image will be displayed. FRAME nil
1291 or omitted means use the selected frame. */)
1292 (spec, frame)
1293 Lisp_Object spec, frame;
1295 Lisp_Object mask;
1297 mask = Qnil;
1298 if (valid_image_p (spec))
1300 struct frame *f = check_x_frame (frame);
1301 int id = lookup_image (f, spec);
1302 struct image *img = IMAGE_FROM_ID (f, id);
1303 if (img->mask)
1304 mask = Qt;
1306 else
1307 error ("Invalid image specification");
1309 return mask;
1312 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1313 doc: /* Return extension data for image SPEC.
1314 FRAME is the frame on which the image will be displayed. FRAME nil
1315 or omitted means use the selected frame. */)
1316 (spec, frame)
1317 Lisp_Object spec, frame;
1319 Lisp_Object ext;
1321 ext = Qnil;
1322 if (valid_image_p (spec))
1324 struct frame *f = check_x_frame (frame);
1325 int id = lookup_image (f, spec);
1326 struct image *img = IMAGE_FROM_ID (f, id);
1327 ext = img->data.lisp_val;
1330 return ext;
1334 /***********************************************************************
1335 Image type independent image structures
1336 ***********************************************************************/
1338 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1339 static void free_image P_ ((struct frame *f, struct image *img));
1340 static int check_image_size P_ ((struct frame *f, int width, int height));
1342 #define MAX_IMAGE_SIZE 6.0
1343 Lisp_Object Vmax_image_size;
1345 /* Allocate and return a new image structure for image specification
1346 SPEC. SPEC has a hash value of HASH. */
1348 static struct image *
1349 make_image (spec, hash)
1350 Lisp_Object spec;
1351 unsigned hash;
1353 struct image *img = (struct image *) xmalloc (sizeof *img);
1354 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
1356 xassert (valid_image_p (spec));
1357 bzero (img, sizeof *img);
1358 img->dependencies = NILP (file) ? Qnil : list1 (file);
1359 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1360 xassert (img->type != NULL);
1361 img->spec = spec;
1362 img->data.lisp_val = Qnil;
1363 img->ascent = DEFAULT_IMAGE_ASCENT;
1364 img->hash = hash;
1365 img->corners[BOT_CORNER] = -1; /* Full image */
1366 return img;
1370 /* Free image IMG which was used on frame F, including its resources. */
1372 static void
1373 free_image (f, img)
1374 struct frame *f;
1375 struct image *img;
1377 if (img)
1379 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1381 /* Remove IMG from the hash table of its cache. */
1382 if (img->prev)
1383 img->prev->next = img->next;
1384 else
1385 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1387 if (img->next)
1388 img->next->prev = img->prev;
1390 c->images[img->id] = NULL;
1392 /* Free resources, then free IMG. */
1393 img->type->free (f, img);
1394 xfree (img);
1398 /* Return 1 if the given widths and heights are valid for display;
1399 otherwise, return 0. */
1402 check_image_size (f, width, height)
1403 struct frame *f;
1404 int width;
1405 int height;
1407 int w, h;
1409 if (width <= 0 || height <= 0)
1410 return 0;
1412 if (INTEGERP (Vmax_image_size))
1413 w = h = XINT (Vmax_image_size);
1414 else if (FLOATP (Vmax_image_size))
1416 if (f != NULL)
1418 w = FRAME_PIXEL_WIDTH (f);
1419 h = FRAME_PIXEL_HEIGHT (f);
1421 else
1422 w = h = 1024; /* Arbitrary size for unknown frame. */
1423 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1424 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1426 else
1427 return 1;
1429 return (width <= w && height <= h);
1432 /* Prepare image IMG for display on frame F. Must be called before
1433 drawing an image. */
1435 void
1436 prepare_image_for_display (f, img)
1437 struct frame *f;
1438 struct image *img;
1440 EMACS_TIME t;
1442 /* We're about to display IMG, so set its timestamp to `now'. */
1443 EMACS_GET_TIME (t);
1444 img->timestamp = EMACS_SECS (t);
1446 /* If IMG doesn't have a pixmap yet, load it now, using the image
1447 type dependent loader function. */
1448 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1449 img->load_failed_p = img->type->load (f, img) == 0;
1451 #if defined (MAC_OS) && USE_CG_DRAWING
1452 if (!img->load_failed_p && img->data.ptr_val == NULL)
1454 img->data.ptr_val = mac_create_cg_image_from_image (f, img);
1455 if (img->data.ptr_val == NULL)
1457 img->load_failed_p = 1;
1458 img->type->free (f, img);
1461 #endif
1465 /* Value is the number of pixels for the ascent of image IMG when
1466 drawn in face FACE. */
1469 image_ascent (img, face, slice)
1470 struct image *img;
1471 struct face *face;
1472 struct glyph_slice *slice;
1474 int height;
1475 int ascent;
1477 if (slice->height == img->height)
1478 height = img->height + img->vmargin;
1479 else if (slice->y == 0)
1480 height = slice->height + img->vmargin;
1481 else
1482 height = slice->height;
1484 if (img->ascent == CENTERED_IMAGE_ASCENT)
1486 if (face->font)
1488 #ifdef HAVE_NTGUI
1489 /* W32 specific version. Why?. ++kfs */
1490 ascent = height / 2 - (FONT_DESCENT (face->font)
1491 - FONT_BASE (face->font)) / 2;
1492 #else
1493 /* This expression is arranged so that if the image can't be
1494 exactly centered, it will be moved slightly up. This is
1495 because a typical font is `top-heavy' (due to the presence
1496 uppercase letters), so the image placement should err towards
1497 being top-heavy too. It also just generally looks better. */
1498 ascent = (height + FONT_BASE(face->font)
1499 - FONT_DESCENT(face->font) + 1) / 2;
1500 #endif /* HAVE_NTGUI */
1502 else
1503 ascent = height / 2;
1505 else
1506 ascent = (int) (height * img->ascent / 100.0);
1508 return ascent;
1512 /* Image background colors. */
1514 /* Find the "best" corner color of a bitmap.
1515 On W32, XIMG is assumed to a device context with the bitmap selected. */
1517 static RGB_PIXEL_COLOR
1518 four_corners_best (ximg, corners, width, height)
1519 XImagePtr_or_DC ximg;
1520 int *corners;
1521 unsigned long width, height;
1523 RGB_PIXEL_COLOR corner_pixels[4], best;
1524 int i, best_count;
1526 if (corners && corners[BOT_CORNER] >= 0)
1528 /* Get the colors at the corner_pixels of ximg. */
1529 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1530 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1531 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1532 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1534 else
1536 /* Get the colors at the corner_pixels of ximg. */
1537 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1538 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1539 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1540 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1542 /* Choose the most frequently found color as background. */
1543 for (i = best_count = 0; i < 4; ++i)
1545 int j, n;
1547 for (j = n = 0; j < 4; ++j)
1548 if (corner_pixels[i] == corner_pixels[j])
1549 ++n;
1551 if (n > best_count)
1552 best = corner_pixels[i], best_count = n;
1555 return best;
1558 /* Portability macros */
1560 #ifdef HAVE_NTGUI
1562 #define Destroy_Image(img_dc, prev) \
1563 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1565 #define Free_Pixmap(display, pixmap) \
1566 DeleteObject (pixmap)
1568 #elif defined (HAVE_NS)
1570 #define Destroy_Image(ximg, dummy) \
1571 ns_release_object(ximg)
1573 #define Free_Pixmap(display, pixmap) \
1574 ns_release_object(pixmap)
1576 #else
1578 #define Destroy_Image(ximg, dummy) \
1579 XDestroyImage (ximg)
1581 #define Free_Pixmap(display, pixmap) \
1582 XFreePixmap (display, pixmap)
1584 #endif /* !HAVE_NTGUI && !HAVE_NS */
1587 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1588 it is guessed heuristically. If non-zero, XIMG is an existing
1589 XImage object (or device context with the image selected on W32) to
1590 use for the heuristic. */
1592 RGB_PIXEL_COLOR
1593 image_background (img, f, ximg)
1594 struct image *img;
1595 struct frame *f;
1596 XImagePtr_or_DC ximg;
1598 if (! img->background_valid)
1599 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1601 int free_ximg = !ximg;
1602 #ifdef HAVE_NTGUI
1603 HGDIOBJ prev;
1604 #endif /* HAVE_NTGUI */
1606 if (free_ximg)
1608 #ifndef HAVE_NTGUI
1609 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1610 0, 0, img->width, img->height, ~0, ZPixmap);
1611 #else
1612 HDC frame_dc = get_frame_dc (f);
1613 ximg = CreateCompatibleDC (frame_dc);
1614 release_frame_dc (f, frame_dc);
1615 prev = SelectObject (ximg, img->pixmap);
1616 #endif /* !HAVE_NTGUI */
1619 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1621 if (free_ximg)
1622 Destroy_Image (ximg, prev);
1624 img->background_valid = 1;
1627 return img->background;
1630 /* Return the `background_transparent' field of IMG. If IMG doesn't
1631 have one yet, it is guessed heuristically. If non-zero, MASK is an
1632 existing XImage object to use for the heuristic. */
1635 image_background_transparent (img, f, mask)
1636 struct image *img;
1637 struct frame *f;
1638 XImagePtr_or_DC mask;
1640 if (! img->background_transparent_valid)
1641 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1643 if (img->mask)
1645 int free_mask = !mask;
1646 #ifdef HAVE_NTGUI
1647 HGDIOBJ prev;
1648 #endif /* HAVE_NTGUI */
1650 if (free_mask)
1652 #ifndef HAVE_NTGUI
1653 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1654 0, 0, img->width, img->height, ~0, ZPixmap);
1655 #else
1656 HDC frame_dc = get_frame_dc (f);
1657 mask = CreateCompatibleDC (frame_dc);
1658 release_frame_dc (f, frame_dc);
1659 prev = SelectObject (mask, img->mask);
1660 #endif /* HAVE_NTGUI */
1663 img->background_transparent
1664 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1666 if (free_mask)
1667 Destroy_Image (mask, prev);
1669 else
1670 img->background_transparent = 0;
1672 img->background_transparent_valid = 1;
1675 return img->background_transparent;
1679 /***********************************************************************
1680 Helper functions for X image types
1681 ***********************************************************************/
1683 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1684 int, int));
1685 static void x_clear_image P_ ((struct frame *f, struct image *img));
1686 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1687 struct image *img,
1688 Lisp_Object color_name,
1689 unsigned long dflt));
1692 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1693 free the pixmap if any. MASK_P non-zero means clear the mask
1694 pixmap if any. COLORS_P non-zero means free colors allocated for
1695 the image, if any. */
1697 static void
1698 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1699 struct frame *f;
1700 struct image *img;
1701 int pixmap_p, mask_p, colors_p;
1703 if (pixmap_p && img->pixmap)
1705 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1706 img->pixmap = NO_PIXMAP;
1707 #ifdef HAVE_NS
1708 if (img->background_valid)
1709 ns_free_indexed_color(img->background);
1710 #endif
1711 img->background_valid = 0;
1714 if (mask_p && img->mask)
1716 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1717 img->mask = NO_PIXMAP;
1718 img->background_transparent_valid = 0;
1721 if (colors_p && img->ncolors)
1723 /* MAC_TODO: color table support. */
1724 /* W32_TODO: color table support. */
1725 #ifdef HAVE_X_WINDOWS
1726 x_free_colors (f, img->colors, img->ncolors);
1727 #endif /* HAVE_X_WINDOWS */
1728 xfree (img->colors);
1729 img->colors = NULL;
1730 img->ncolors = 0;
1733 #if defined (MAC_OS) && USE_CG_DRAWING
1734 if (img->data.ptr_val)
1736 CGImageRelease (img->data.ptr_val);
1737 img->data.ptr_val = NULL;
1739 #endif
1742 /* Free X resources of image IMG which is used on frame F. */
1744 static void
1745 x_clear_image (f, img)
1746 struct frame *f;
1747 struct image *img;
1749 BLOCK_INPUT;
1750 x_clear_image_1 (f, img, 1, 1, 1);
1751 UNBLOCK_INPUT;
1755 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1756 cannot be allocated, use DFLT. Add a newly allocated color to
1757 IMG->colors, so that it can be freed again. Value is the pixel
1758 color. */
1760 static unsigned long
1761 x_alloc_image_color (f, img, color_name, dflt)
1762 struct frame *f;
1763 struct image *img;
1764 Lisp_Object color_name;
1765 unsigned long dflt;
1767 XColor color;
1768 unsigned long result;
1770 xassert (STRINGP (color_name));
1772 if (x_defined_color (f, SDATA (color_name), &color, 1))
1774 /* This isn't called frequently so we get away with simply
1775 reallocating the color vector to the needed size, here. */
1776 ++img->ncolors;
1777 img->colors =
1778 (unsigned long *) xrealloc (img->colors,
1779 img->ncolors * sizeof *img->colors);
1780 img->colors[img->ncolors - 1] = color.pixel;
1781 result = color.pixel;
1783 else
1784 result = dflt;
1786 return result;
1791 /***********************************************************************
1792 Image Cache
1793 ***********************************************************************/
1795 static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
1796 static void cache_image P_ ((struct frame *f, struct image *img));
1797 static void postprocess_image P_ ((struct frame *, struct image *));
1799 /* Return a new, initialized image cache that is allocated from the
1800 heap. Call free_image_cache to free an image cache. */
1802 struct image_cache *
1803 make_image_cache ()
1805 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1806 int size;
1808 bzero (c, sizeof *c);
1809 c->size = 50;
1810 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1811 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1812 c->buckets = (struct image **) xmalloc (size);
1813 bzero (c->buckets, size);
1814 return c;
1818 /* Find an image matching SPEC in the cache, and return it. If no
1819 image is found, return NULL. */
1820 static struct image *
1821 search_image_cache (f, spec, hash)
1822 struct frame *f;
1823 Lisp_Object spec;
1824 unsigned hash;
1826 struct image *img;
1827 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1828 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1830 if (!c) return NULL;
1832 /* If the image spec does not specify a background color, the cached
1833 image must have the same background color as the current frame.
1834 The foreground color must also match, for the sake of monochrome
1835 images.
1837 In fact, we could ignore the foreground color matching condition
1838 for color images, or if the image spec specifies :foreground;
1839 similarly we could ignore the background color matching condition
1840 for formats that don't use transparency (such as jpeg), or if the
1841 image spec specifies :background. However, the extra memory
1842 usage is probably negligible in practice, so we don't bother. */
1844 for (img = c->buckets[i]; img; img = img->next)
1845 if (img->hash == hash
1846 && !NILP (Fequal (img->spec, spec))
1847 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1848 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1849 break;
1850 return img;
1854 /* Search frame F for an image with spec SPEC, and free it. */
1856 static void
1857 uncache_image (f, spec)
1858 struct frame *f;
1859 Lisp_Object spec;
1861 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1862 if (img)
1863 free_image (f, img);
1867 /* Free image cache of frame F. Be aware that X frames share images
1868 caches. */
1870 void
1871 free_image_cache (f)
1872 struct frame *f;
1874 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1875 if (c)
1877 int i;
1879 /* Cache should not be referenced by any frame when freed. */
1880 xassert (c->refcount == 0);
1882 for (i = 0; i < c->used; ++i)
1883 free_image (f, c->images[i]);
1884 xfree (c->images);
1885 xfree (c->buckets);
1886 xfree (c);
1887 FRAME_IMAGE_CACHE (f) = NULL;
1892 /* Clear image cache of frame F. FILTER=t means free all images.
1893 FILTER=nil means clear only images that haven't been
1894 displayed for some time.
1895 Else, only free the images which have FILTER in their `dependencies'.
1896 Should be called from time to time to reduce the number of loaded images.
1897 If image-cache-eviction-delay is non-nil, this frees images in the cache
1898 which weren't displayed for at least that many seconds. */
1900 void
1901 clear_image_cache (struct frame *f, Lisp_Object filter)
1903 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1905 if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
1907 EMACS_TIME t;
1908 unsigned long old;
1909 int i, nfreed;
1911 EMACS_GET_TIME (t);
1912 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1914 /* Block input so that we won't be interrupted by a SIGIO
1915 while being in an inconsistent state. */
1916 BLOCK_INPUT;
1918 for (i = nfreed = 0; i < c->used; ++i)
1920 struct image *img = c->images[i];
1921 if (img != NULL
1922 && (NILP (filter) ? img->timestamp < old
1923 : (EQ (Qt, filter)
1924 || !NILP (Fmember (filter, img->dependencies)))))
1926 free_image (f, img);
1927 ++nfreed;
1931 /* We may be clearing the image cache because, for example,
1932 Emacs was iconified for a longer period of time. In that
1933 case, current matrices may still contain references to
1934 images freed above. So, clear these matrices. */
1935 if (nfreed)
1937 Lisp_Object tail, frame;
1939 FOR_EACH_FRAME (tail, frame)
1941 struct frame *f = XFRAME (frame);
1942 if (FRAME_IMAGE_CACHE (f) == c)
1943 clear_current_matrices (f);
1946 ++windows_or_buffers_changed;
1949 UNBLOCK_INPUT;
1953 void
1954 clear_image_caches (Lisp_Object filter)
1956 /* FIXME: We want to do
1957 * struct terminal *t;
1958 * for (t = terminal_list; t; t = t->next_terminal)
1959 * clear_image_cache (t, filter); */
1960 Lisp_Object tail, frame;
1961 FOR_EACH_FRAME (tail, frame)
1962 if (FRAME_WINDOW_P (XFRAME (frame)))
1963 clear_image_cache (XFRAME (frame), filter);
1966 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1967 0, 1, 0,
1968 doc: /* Clear the image cache.
1969 FILTER nil or a frame means clear all images in the selected frame.
1970 FILTER t means clear the image caches of all frames.
1971 Anything else, means only clear those images which refer to FILTER,
1972 which is then usually a filename. */)
1973 (filter)
1974 Lisp_Object filter;
1976 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1977 clear_image_caches (filter);
1978 else
1979 clear_image_cache (check_x_frame (filter), Qt);
1981 return Qnil;
1985 DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
1986 1, 2, 0,
1987 doc: /* Refresh the image with specification SPEC on frame FRAME.
1988 If SPEC specifies an image file, the displayed image is updated with
1989 the current contents of that file.
1990 FRAME nil or omitted means use the selected frame.
1991 FRAME t means refresh the image on all frames. */)
1992 (spec, frame)
1993 Lisp_Object spec, frame;
1995 if (!valid_image_p (spec))
1996 error ("Invalid image specification");
1998 if (EQ (frame, Qt))
2000 Lisp_Object tail;
2001 FOR_EACH_FRAME (tail, frame)
2003 struct frame *f = XFRAME (frame);
2004 if (FRAME_WINDOW_P (f))
2005 uncache_image (f, spec);
2008 else
2009 uncache_image (check_x_frame (frame), spec);
2011 return Qnil;
2015 /* Compute masks and transform image IMG on frame F, as specified
2016 by the image's specification, */
2018 static void
2019 postprocess_image (f, img)
2020 struct frame *f;
2021 struct image *img;
2023 /* Manipulation of the image's mask. */
2024 if (img->pixmap)
2026 Lisp_Object conversion, spec;
2027 Lisp_Object mask;
2029 spec = img->spec;
2031 /* `:heuristic-mask t'
2032 `:mask heuristic'
2033 means build a mask heuristically.
2034 `:heuristic-mask (R G B)'
2035 `:mask (heuristic (R G B))'
2036 means build a mask from color (R G B) in the
2037 image.
2038 `:mask nil'
2039 means remove a mask, if any. */
2041 mask = image_spec_value (spec, QCheuristic_mask, NULL);
2042 if (!NILP (mask))
2043 x_build_heuristic_mask (f, img, mask);
2044 else
2046 int found_p;
2048 mask = image_spec_value (spec, QCmask, &found_p);
2050 if (EQ (mask, Qheuristic))
2051 x_build_heuristic_mask (f, img, Qt);
2052 else if (CONSP (mask)
2053 && EQ (XCAR (mask), Qheuristic))
2055 if (CONSP (XCDR (mask)))
2056 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
2057 else
2058 x_build_heuristic_mask (f, img, XCDR (mask));
2060 else if (NILP (mask) && found_p && img->mask)
2062 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
2063 img->mask = NO_PIXMAP;
2068 /* Should we apply an image transformation algorithm? */
2069 conversion = image_spec_value (spec, QCconversion, NULL);
2070 if (EQ (conversion, Qdisabled))
2071 x_disable_image (f, img);
2072 else if (EQ (conversion, Qlaplace))
2073 x_laplace (f, img);
2074 else if (EQ (conversion, Qemboss))
2075 x_emboss (f, img);
2076 else if (CONSP (conversion)
2077 && EQ (XCAR (conversion), Qedge_detection))
2079 Lisp_Object tem;
2080 tem = XCDR (conversion);
2081 if (CONSP (tem))
2082 x_edge_detection (f, img,
2083 Fplist_get (tem, QCmatrix),
2084 Fplist_get (tem, QCcolor_adjustment));
2090 /* Return the id of image with Lisp specification SPEC on frame F.
2091 SPEC must be a valid Lisp image specification (see valid_image_p). */
2094 lookup_image (f, spec)
2095 struct frame *f;
2096 Lisp_Object spec;
2098 struct image_cache *c;
2099 struct image *img;
2100 unsigned hash;
2101 struct gcpro gcpro1;
2102 EMACS_TIME now;
2104 /* F must be a window-system frame, and SPEC must be a valid image
2105 specification. */
2106 xassert (FRAME_WINDOW_P (f));
2107 xassert (valid_image_p (spec));
2109 c = FRAME_IMAGE_CACHE (f);
2111 GCPRO1 (spec);
2113 /* Look up SPEC in the hash table of the image cache. */
2114 hash = sxhash (spec, 0);
2115 img = search_image_cache (f, spec, hash);
2116 if (img && img->load_failed_p)
2118 free_image (f, img);
2119 img = NULL;
2122 /* If not found, create a new image and cache it. */
2123 if (img == NULL)
2125 extern Lisp_Object Qpostscript;
2127 BLOCK_INPUT;
2128 img = make_image (spec, hash);
2129 cache_image (f, img);
2130 img->load_failed_p = img->type->load (f, img) == 0;
2131 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
2132 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
2134 /* If we can't load the image, and we don't have a width and
2135 height, use some arbitrary width and height so that we can
2136 draw a rectangle for it. */
2137 if (img->load_failed_p)
2139 Lisp_Object value;
2141 value = image_spec_value (spec, QCwidth, NULL);
2142 img->width = (INTEGERP (value)
2143 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
2144 value = image_spec_value (spec, QCheight, NULL);
2145 img->height = (INTEGERP (value)
2146 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
2148 else
2150 /* Handle image type independent image attributes
2151 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2152 `:background COLOR'. */
2153 Lisp_Object ascent, margin, relief, bg;
2155 ascent = image_spec_value (spec, QCascent, NULL);
2156 if (INTEGERP (ascent))
2157 img->ascent = XFASTINT (ascent);
2158 else if (EQ (ascent, Qcenter))
2159 img->ascent = CENTERED_IMAGE_ASCENT;
2161 margin = image_spec_value (spec, QCmargin, NULL);
2162 if (INTEGERP (margin) && XINT (margin) >= 0)
2163 img->vmargin = img->hmargin = XFASTINT (margin);
2164 else if (CONSP (margin) && INTEGERP (XCAR (margin))
2165 && INTEGERP (XCDR (margin)))
2167 if (XINT (XCAR (margin)) > 0)
2168 img->hmargin = XFASTINT (XCAR (margin));
2169 if (XINT (XCDR (margin)) > 0)
2170 img->vmargin = XFASTINT (XCDR (margin));
2173 relief = image_spec_value (spec, QCrelief, NULL);
2174 if (INTEGERP (relief))
2176 img->relief = XINT (relief);
2177 img->hmargin += eabs (img->relief);
2178 img->vmargin += eabs (img->relief);
2181 if (! img->background_valid)
2183 bg = image_spec_value (img->spec, QCbackground, NULL);
2184 if (!NILP (bg))
2186 img->background
2187 = x_alloc_image_color (f, img, bg,
2188 FRAME_BACKGROUND_PIXEL (f));
2189 img->background_valid = 1;
2193 /* Do image transformations and compute masks, unless we
2194 don't have the image yet. */
2195 if (!EQ (*img->type->type, Qpostscript))
2196 postprocess_image (f, img);
2199 UNBLOCK_INPUT;
2202 /* We're using IMG, so set its timestamp to `now'. */
2203 EMACS_GET_TIME (now);
2204 img->timestamp = EMACS_SECS (now);
2206 UNGCPRO;
2208 /* Value is the image id. */
2209 return img->id;
2213 /* Cache image IMG in the image cache of frame F. */
2215 static void
2216 cache_image (f, img)
2217 struct frame *f;
2218 struct image *img;
2220 struct image_cache *c = FRAME_IMAGE_CACHE (f);
2221 int i;
2223 /* Find a free slot in c->images. */
2224 for (i = 0; i < c->used; ++i)
2225 if (c->images[i] == NULL)
2226 break;
2228 /* If no free slot found, maybe enlarge c->images. */
2229 if (i == c->used && c->used == c->size)
2231 c->size *= 2;
2232 c->images = (struct image **) xrealloc (c->images,
2233 c->size * sizeof *c->images);
2236 /* Add IMG to c->images, and assign IMG an id. */
2237 c->images[i] = img;
2238 img->id = i;
2239 if (i == c->used)
2240 ++c->used;
2242 /* Add IMG to the cache's hash table. */
2243 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
2244 img->next = c->buckets[i];
2245 if (img->next)
2246 img->next->prev = img;
2247 img->prev = NULL;
2248 c->buckets[i] = img;
2252 /* Call FN on every image in the image cache of frame F. Used to mark
2253 Lisp Objects in the image cache. */
2255 /* Mark Lisp objects in image IMG. */
2257 static void
2258 mark_image (img)
2259 struct image *img;
2261 mark_object (img->spec);
2262 mark_object (img->dependencies);
2264 if (!NILP (img->data.lisp_val))
2265 mark_object (img->data.lisp_val);
2269 void
2270 mark_image_cache (struct image_cache *c)
2272 if (c)
2274 int i;
2275 for (i = 0; i < c->used; ++i)
2276 if (c->images[i])
2277 mark_image (c->images[i]);
2283 /***********************************************************************
2284 X / MAC / W32 support code
2285 ***********************************************************************/
2287 #ifdef HAVE_NTGUI
2289 /* Macro for defining functions that will be loaded from image DLLs. */
2290 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2292 /* Macro for loading those image functions from the library. */
2293 #define LOAD_IMGLIB_FN(lib,func) { \
2294 fn_##func = (void *) GetProcAddress (lib, #func); \
2295 if (!fn_##func) return 0; \
2298 /* Load a DLL implementing an image type.
2299 The `image-library-alist' variable associates a symbol,
2300 identifying an image type, to a list of possible filenames.
2301 The function returns NULL if no library could be loaded for
2302 the given image type, or if the library was previously loaded;
2303 else the handle of the DLL. */
2304 static HMODULE
2305 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
2307 HMODULE library = NULL;
2309 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2311 Lisp_Object dlls = Fassq (type, libraries);
2313 if (CONSP (dlls))
2314 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2316 CHECK_STRING_CAR (dlls);
2317 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2318 break;
2322 return library;
2325 #endif /* HAVE_NTGUI */
2327 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2328 XImagePtr *, Pixmap *));
2329 static void x_destroy_x_image P_ ((XImagePtr));
2330 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2333 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2334 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2335 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2336 via xmalloc. Print error messages via image_error if an error
2337 occurs. Value is non-zero if successful.
2339 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2340 should indicate the bit depth of the image. */
2342 static int
2343 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2344 struct frame *f;
2345 int width, height, depth;
2346 XImagePtr *ximg;
2347 Pixmap *pixmap;
2349 #ifdef HAVE_X_WINDOWS
2350 Display *display = FRAME_X_DISPLAY (f);
2351 Window window = FRAME_X_WINDOW (f);
2352 Screen *screen = FRAME_X_SCREEN (f);
2354 xassert (interrupt_input_blocked);
2356 if (depth <= 0)
2357 depth = DefaultDepthOfScreen (screen);
2358 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2359 depth, ZPixmap, 0, NULL, width, height,
2360 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2361 if (*ximg == NULL)
2363 image_error ("Unable to allocate X image", Qnil, Qnil);
2364 return 0;
2367 /* Allocate image raster. */
2368 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2370 /* Allocate a pixmap of the same size. */
2371 *pixmap = XCreatePixmap (display, window, width, height, depth);
2372 if (*pixmap == NO_PIXMAP)
2374 x_destroy_x_image (*ximg);
2375 *ximg = NULL;
2376 image_error ("Unable to create X pixmap", Qnil, Qnil);
2377 return 0;
2380 return 1;
2381 #endif /* HAVE_X_WINDOWS */
2383 #ifdef HAVE_NTGUI
2385 BITMAPINFOHEADER *header;
2386 HDC hdc;
2387 int scanline_width_bits;
2388 int remainder;
2389 int palette_colors = 0;
2391 if (depth == 0)
2392 depth = 24;
2394 if (depth != 1 && depth != 4 && depth != 8
2395 && depth != 16 && depth != 24 && depth != 32)
2397 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2398 return 0;
2401 scanline_width_bits = width * depth;
2402 remainder = scanline_width_bits % 32;
2404 if (remainder)
2405 scanline_width_bits += 32 - remainder;
2407 /* Bitmaps with a depth less than 16 need a palette. */
2408 /* BITMAPINFO structure already contains the first RGBQUAD. */
2409 if (depth < 16)
2410 palette_colors = 1 << depth - 1;
2412 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2413 if (*ximg == NULL)
2415 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2416 return 0;
2419 header = &((*ximg)->info.bmiHeader);
2420 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2421 header->biSize = sizeof (*header);
2422 header->biWidth = width;
2423 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2424 header->biPlanes = 1;
2425 header->biBitCount = depth;
2426 header->biCompression = BI_RGB;
2427 header->biClrUsed = palette_colors;
2429 /* TODO: fill in palette. */
2430 if (depth == 1)
2432 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2433 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2434 (*ximg)->info.bmiColors[0].rgbRed = 0;
2435 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2436 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2437 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2438 (*ximg)->info.bmiColors[1].rgbRed = 255;
2439 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2442 hdc = get_frame_dc (f);
2444 /* Create a DIBSection and raster array for the bitmap,
2445 and store its handle in *pixmap. */
2446 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2447 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2448 /* casting avoids a GCC warning */
2449 (void **)&((*ximg)->data), NULL, 0);
2451 /* Realize display palette and garbage all frames. */
2452 release_frame_dc (f, hdc);
2454 if (*pixmap == NULL)
2456 DWORD err = GetLastError ();
2457 Lisp_Object errcode;
2458 /* All system errors are < 10000, so the following is safe. */
2459 XSETINT (errcode, (int) err);
2460 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2461 x_destroy_x_image (*ximg);
2462 return 0;
2465 return 1;
2467 #endif /* HAVE_NTGUI */
2469 #ifdef MAC_OS
2470 Display *display = FRAME_X_DISPLAY (f);
2471 Window window = FRAME_X_WINDOW (f);
2473 xassert (interrupt_input_blocked);
2475 /* Allocate a pixmap of the same size. */
2476 *pixmap = XCreatePixmap (display, window, width, height, depth);
2477 if (*pixmap == NO_PIXMAP)
2479 *ximg = NULL;
2480 image_error ("Unable to create X pixmap", Qnil, Qnil);
2481 return 0;
2484 #if !USE_MAC_IMAGE_IO
2485 LockPixels (GetGWorldPixMap (*pixmap));
2486 #endif
2487 *ximg = *pixmap;
2488 return 1;
2490 #endif /* MAC_OS */
2492 #ifdef HAVE_NS
2493 *pixmap = ns_image_for_XPM(width, height, depth);
2494 if (*pixmap == 0)
2496 *ximg = NULL;
2497 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
2498 return 0;
2500 *ximg = *pixmap;
2501 return 1;
2502 #endif
2506 /* Destroy XImage XIMG. Free XIMG->data. */
2508 static void
2509 x_destroy_x_image (ximg)
2510 XImagePtr ximg;
2512 xassert (interrupt_input_blocked);
2513 if (ximg)
2515 #ifdef HAVE_X_WINDOWS
2516 xfree (ximg->data);
2517 ximg->data = NULL;
2518 XDestroyImage (ximg);
2519 #endif /* HAVE_X_WINDOWS */
2520 #ifdef HAVE_NTGUI
2521 /* Data will be freed by DestroyObject. */
2522 ximg->data = NULL;
2523 xfree (ximg);
2524 #endif /* HAVE_NTGUI */
2525 #ifdef MAC_OS
2526 XDestroyImage (ximg);
2527 #endif /* MAC_OS */
2528 #ifdef HAVE_NS
2529 ns_release_object(ximg);
2530 #endif /* HAVE_NS */
2535 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2536 are width and height of both the image and pixmap. */
2538 static void
2539 x_put_x_image (f, ximg, pixmap, width, height)
2540 struct frame *f;
2541 XImagePtr ximg;
2542 Pixmap pixmap;
2543 int width, height;
2545 #ifdef HAVE_X_WINDOWS
2546 GC gc;
2548 xassert (interrupt_input_blocked);
2549 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2550 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2551 XFreeGC (FRAME_X_DISPLAY (f), gc);
2552 #endif /* HAVE_X_WINDOWS */
2554 #ifdef HAVE_NTGUI
2555 #if 0 /* I don't think this is necessary looking at where it is used. */
2556 HDC hdc = get_frame_dc (f);
2557 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2558 release_frame_dc (f, hdc);
2559 #endif
2560 #endif /* HAVE_NTGUI */
2562 #ifdef MAC_OS
2563 xassert (ximg == pixmap);
2564 #endif /* MAC_OS */
2566 #ifdef HAVE_NS
2567 xassert (ximg == pixmap);
2568 ns_retain_object(ximg);
2569 #endif
2573 /***********************************************************************
2574 File Handling
2575 ***********************************************************************/
2577 static unsigned char *slurp_file P_ ((char *, int *));
2580 /* Find image file FILE. Look in data-directory/images, then
2581 x-bitmap-file-path. Value is the encoded full name of the file
2582 found, or nil if not found. */
2584 Lisp_Object
2585 x_find_image_file (file)
2586 Lisp_Object file;
2588 Lisp_Object file_found, search_path;
2589 struct gcpro gcpro1, gcpro2;
2590 int fd;
2592 file_found = Qnil;
2593 /* TODO I think this should use something like image-load-path
2594 instead. Unfortunately, that can contain non-string elements. */
2595 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2596 Vdata_directory),
2597 Vx_bitmap_file_path);
2598 GCPRO2 (file_found, search_path);
2600 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2601 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2603 if (fd == -1)
2604 file_found = Qnil;
2605 else
2607 file_found = ENCODE_FILE (file_found);
2608 close (fd);
2611 UNGCPRO;
2612 return file_found;
2616 /* Read FILE into memory. Value is a pointer to a buffer allocated
2617 with xmalloc holding FILE's contents. Value is null if an error
2618 occurred. *SIZE is set to the size of the file. */
2620 static unsigned char *
2621 slurp_file (file, size)
2622 char *file;
2623 int *size;
2625 FILE *fp = NULL;
2626 unsigned char *buf = NULL;
2627 struct stat st;
2629 if (stat (file, &st) == 0
2630 && (fp = fopen (file, "rb")) != NULL
2631 && (buf = (unsigned char *) xmalloc (st.st_size),
2632 fread (buf, 1, st.st_size, fp) == st.st_size))
2634 *size = st.st_size;
2635 fclose (fp);
2637 else
2639 if (fp)
2640 fclose (fp);
2641 if (buf)
2643 xfree (buf);
2644 buf = NULL;
2648 return buf;
2653 #ifdef MAC_OS
2655 /***********************************************************************
2656 MAC Image Load Functions
2657 ***********************************************************************/
2659 #if USE_MAC_IMAGE_IO
2660 static int
2661 image_load_image_io (f, img, type)
2662 struct frame *f;
2663 struct image *img;
2664 CFStringRef type;
2666 CFDictionaryRef options, src_props = NULL, props = NULL;
2667 CFStringRef keys[2];
2668 CFTypeRef values[2];
2669 Lisp_Object specified_file, specified_data;
2670 CGImageSourceRef source = NULL;
2671 size_t count;
2672 CGImageRef image = NULL;
2673 int loop_count = -1;
2674 double delay_time = -1.0;
2675 int width, height;
2676 XImagePtr ximg = NULL;
2677 CGContextRef context;
2678 CGRect rectangle;
2679 int has_alpha_p, gif_p;
2681 gif_p = UTTypeEqual (type, kUTTypeGIF);
2683 keys[0] = kCGImageSourceTypeIdentifierHint;
2684 values[0] = (CFTypeRef) type;
2685 keys[1] = kCGImageSourceShouldCache;
2686 values[1] = (CFTypeRef) kCFBooleanFalse;
2687 options = CFDictionaryCreate (NULL, (const void **) keys,
2688 (const void **) values,
2689 sizeof (keys) / sizeof (keys[0]),
2690 &kCFTypeDictionaryKeyCallBacks,
2691 &kCFTypeDictionaryValueCallBacks);
2692 if (options == NULL)
2694 image_error ("Error creating options for image `%s'", img->spec, Qnil);
2695 return 0;
2698 /* Open the file. */
2699 specified_file = image_spec_value (img->spec, QCfile, NULL);
2700 specified_data = image_spec_value (img->spec, QCdata, NULL);
2702 if (NILP (specified_data))
2704 Lisp_Object file;
2705 CFStringRef path;
2706 CFURLRef url;
2708 file = x_find_image_file (specified_file);
2709 if (!STRINGP (file))
2711 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2712 return 0;
2714 path = cfstring_create_with_utf8_cstring (SDATA (file));
2715 if (path)
2717 url = CFURLCreateWithFileSystemPath (NULL, path,
2718 kCFURLPOSIXPathStyle, 0);
2719 CFRelease (path);
2720 if (url)
2722 source = CGImageSourceCreateWithURL (url, NULL);
2723 CFRelease (url);
2727 else
2729 CFDataRef data = CFDataCreate (NULL, SDATA (specified_data),
2730 SBYTES (specified_data));
2732 if (data)
2734 source = CGImageSourceCreateWithData (data, options);
2735 CFRelease (data);
2738 CFRelease (options);
2740 if (source)
2742 CFStringRef real_type = CGImageSourceGetType (source);
2744 if (real_type && UTTypeEqual (type, real_type))
2745 src_props = CGImageSourceCopyProperties (source, NULL);
2746 if (src_props)
2748 EMACS_INT ino = 0;
2750 count = CGImageSourceGetCount (source);
2751 if (gif_p)
2753 Lisp_Object image = image_spec_value (img->spec, QCindex, NULL);
2755 if (INTEGERP (image))
2756 ino = XFASTINT (image);
2758 if (ino >= 0 && ino < count)
2760 props = CGImageSourceCopyPropertiesAtIndex (source, ino, NULL);
2761 if (props)
2762 image = CGImageSourceCreateImageAtIndex (source, ino, NULL);
2765 CFRelease (source);
2768 if (image == NULL)
2770 if (src_props)
2771 CFRelease (src_props);
2772 if (props)
2773 CFRelease (props);
2774 image_error ("Error reading image `%s'", img->spec, Qnil);
2775 return 0;
2777 else
2779 CFBooleanRef boolean;
2781 if (CFDictionaryGetValueIfPresent (props, kCGImagePropertyHasAlpha,
2782 (const void **) &boolean))
2783 has_alpha_p = CFBooleanGetValue (boolean);
2784 if (gif_p)
2786 CFDictionaryRef dict;
2787 CFNumberRef number;
2789 dict = CFDictionaryGetValue (src_props,
2790 kCGImagePropertyGIFDictionary);
2791 if (dict
2792 && CFDictionaryGetValueIfPresent (dict,
2793 kCGImagePropertyGIFLoopCount,
2794 (const void **) &number))
2795 CFNumberGetValue (number, kCFNumberIntType, &loop_count);
2797 dict = CFDictionaryGetValue (props, kCGImagePropertyGIFDictionary);
2798 if (dict
2799 && CFDictionaryGetValueIfPresent (dict,
2800 kCGImagePropertyGIFDelayTime,
2801 (const void **) &number))
2802 CFNumberGetValue (number, kCFNumberDoubleType, &delay_time);
2804 CFRelease (src_props);
2805 CFRelease (props);
2808 width = img->width = CGImageGetWidth (image);
2809 height = img->height = CGImageGetHeight (image);
2811 if (!check_image_size (f, width, height))
2813 CGImageRelease (image);
2814 image_error ("Invalid image size", Qnil, Qnil);
2815 return 0;
2818 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2820 CGImageRelease (image);
2821 image_error ("Out of memory (%s)", img->spec, Qnil);
2822 return 0;
2824 rectangle = CGRectMake (0, 0, width, height);
2826 context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
2827 ximg->bytes_per_line,
2828 mac_cg_color_space_rgb,
2829 kCGImageAlphaNoneSkipFirst
2830 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
2831 | kCGBitmapByteOrder32Host
2832 #endif
2834 if (has_alpha_p)
2836 Lisp_Object specified_bg;
2837 XColor color;
2839 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2840 if (!STRINGP (specified_bg)
2841 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2843 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2844 color.red = RED16_FROM_ULONG (color.pixel);
2845 color.green = GREEN16_FROM_ULONG (color.pixel);
2846 color.blue = BLUE16_FROM_ULONG (color.pixel);
2848 CGContextSetRGBFillColor (context, color.red / 65535.0,
2849 color.green / 65535.0,
2850 color.blue / 65535.0, 1.0);
2851 CGContextFillRect (context, rectangle);
2853 CGContextDrawImage (context, rectangle, image);
2854 CGContextRelease (context);
2855 CGImageRelease (image);
2857 /* Save GIF image extension data for `image-extension-data'.
2858 Format is (count IMAGES
2859 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2860 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2861 if (gif_p)
2863 img->data.lisp_val = Qnil;
2864 if (delay_time >= 0)
2866 Lisp_Object gce = make_uninit_string (4);
2867 int centisec = delay_time * 100.0 + 0.5;
2869 /* Fill the delay time field. */
2870 SSET (gce, 1, centisec & 0xff);
2871 SSET (gce, 2, (centisec >> 8) & 0xff);
2872 /* We don't know about other fields. */
2873 SSET (gce, 0, 0);
2874 SSET (gce, 3, 0);
2875 img->data.lisp_val = Fcons (make_number (0xf9),
2876 Fcons (gce,
2877 img->data.lisp_val));
2879 if (loop_count >= 0)
2881 Lisp_Object data_sub_block = make_uninit_string (3);
2883 SSET (data_sub_block, 0, 0x01);
2884 SSET (data_sub_block, 1, loop_count & 0xff);
2885 SSET (data_sub_block, 2, (loop_count >> 8) & 0xff);
2886 img->data.lisp_val = Fcons (make_number (0),
2887 Fcons (data_sub_block,
2888 img->data.lisp_val));
2889 img->data.lisp_val = Fcons (make_number (0xff),
2890 Fcons (build_string ("NETSCAPE2.0"),
2891 img->data.lisp_val));
2893 if (count > 1)
2894 img->data.lisp_val = Fcons (Qcount,
2895 Fcons (make_number (count),
2896 img->data.lisp_val));
2899 /* Maybe fill in the background field while we have ximg handy. */
2900 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2901 IMAGE_BACKGROUND (img, f, ximg);
2903 /* Put the image into the pixmap. */
2904 x_put_x_image (f, ximg, img->pixmap, width, height);
2905 x_destroy_x_image (ximg);
2906 return 1;
2908 #else /* !USE_MAC_IMAGE_IO */
2909 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2910 OSType));
2911 #ifdef MAC_OSX
2912 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2913 #endif
2915 static OSErr
2916 find_image_fsspec (specified_file, file, fss)
2917 Lisp_Object specified_file, *file;
2918 FSSpec *fss;
2920 OSErr err;
2921 AEDesc desc;
2923 *file = x_find_image_file (specified_file);
2924 if (!STRINGP (*file))
2925 return fnfErr; /* file or directory not found;
2926 incomplete pathname */
2927 /* Try to open the image file. */
2928 err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
2929 SBYTES (*file), typeFSS, &desc);
2930 if (err == noErr)
2932 #if TARGET_API_MAC_CARBON
2933 err = AEGetDescData (&desc, fss, sizeof (FSSpec));
2934 #else
2935 *fss = *(FSSpec *)(*(desc.dataHandle));
2936 #endif
2937 AEDisposeDesc (&desc);
2939 return err;
2942 static int
2943 image_load_qt_1 (f, img, type, fss, dh)
2944 struct frame *f;
2945 struct image *img;
2946 OSType type;
2947 const FSSpec *fss;
2948 Handle dh;
2950 ComponentResult err;
2951 GraphicsImportComponent gi;
2952 Rect rect;
2953 int width, height;
2954 ImageDescriptionHandle desc_handle;
2955 short draw_all_pixels;
2956 Lisp_Object specified_bg;
2957 XColor color;
2958 XImagePtr ximg;
2959 RGBColor bg_color;
2961 err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
2962 if (err != noErr)
2964 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2965 return 0;
2967 if (dh == NULL)
2969 /* read from file system spec */
2970 err = GraphicsImportSetDataFile (gi, fss);
2971 if (err != noErr)
2973 image_error ("Cannot set fsspec to graphics importer for '%s'",
2974 img->spec, Qnil);
2975 goto error;
2978 else
2980 /* read from data handle */
2981 err = GraphicsImportSetDataHandle (gi, dh);
2982 if (err != noErr)
2984 image_error ("Cannot set data handle to graphics importer for `%s'",
2985 img->spec, Qnil);
2986 goto error;
2989 err = GraphicsImportGetImageDescription (gi, &desc_handle);
2990 if (err != noErr || desc_handle == NULL)
2992 image_error ("Error reading `%s'", img->spec, Qnil);
2993 goto error;
2995 width = img->width = (*desc_handle)->width;
2996 height = img->height = (*desc_handle)->height;
2997 DisposeHandle ((Handle)desc_handle);
2999 if (!check_image_size (f, width, height))
3001 image_error ("Invalid image size", Qnil, Qnil);
3002 goto error;
3005 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
3006 #if 0
3007 /* Don't check the error code here. It may have an undocumented
3008 value -32766. */
3009 if (err != noErr)
3011 image_error ("Error reading `%s'", img->spec, Qnil);
3012 goto error;
3014 #endif
3015 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
3017 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
3018 if (!STRINGP (specified_bg) ||
3019 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
3021 color.pixel = FRAME_BACKGROUND_PIXEL (f);
3022 color.red = RED16_FROM_ULONG (color.pixel);
3023 color.green = GREEN16_FROM_ULONG (color.pixel);
3024 color.blue = BLUE16_FROM_ULONG (color.pixel);
3028 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
3029 goto error;
3030 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
3032 CGrafPtr old_port;
3033 GDHandle old_gdh;
3035 GetGWorld (&old_port, &old_gdh);
3036 SetGWorld (ximg, NULL);
3037 bg_color.red = color.red;
3038 bg_color.green = color.green;
3039 bg_color.blue = color.blue;
3040 RGBBackColor (&bg_color);
3041 #if TARGET_API_MAC_CARBON
3042 GetPortBounds (ximg, &rect);
3043 EraseRect (&rect);
3044 #else
3045 EraseRect (&(ximg->portRect));
3046 #endif
3047 SetGWorld (old_port, old_gdh);
3049 GraphicsImportSetGWorld (gi, ximg, NULL);
3050 GraphicsImportDraw (gi);
3051 CloseComponent (gi);
3053 /* Maybe fill in the background field while we have ximg handy. */
3054 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3055 IMAGE_BACKGROUND (img, f, ximg);
3057 /* Put the image into the pixmap. */
3058 x_put_x_image (f, ximg, img->pixmap, width, height);
3059 x_destroy_x_image (ximg);
3060 return 1;
3062 error:
3063 CloseComponent (gi);
3064 return 0;
3068 /* Load an image using the QuickTime Graphics Importer.
3069 Note: The alpha channel does not work for PNG images. */
3070 static int
3071 image_load_quicktime (f, img, type)
3072 struct frame *f;
3073 struct image *img;
3074 OSType type;
3076 Lisp_Object specified_file;
3077 Lisp_Object specified_data;
3078 OSErr err;
3080 specified_file = image_spec_value (img->spec, QCfile, NULL);
3081 specified_data = image_spec_value (img->spec, QCdata, NULL);
3083 if (NILP (specified_data))
3085 /* Read from a file */
3086 Lisp_Object file;
3087 FSSpec fss;
3089 err = find_image_fsspec (specified_file, &file, &fss);
3090 if (err != noErr)
3092 if (err == fnfErr)
3093 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3094 else
3095 image_error ("Cannot open `%s'", file, Qnil);
3096 return 0;
3098 return image_load_qt_1 (f, img, type, &fss, NULL);
3100 else
3102 /* Memory source! */
3103 int success_p;
3104 Handle dh;
3106 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
3107 if (err != noErr)
3109 image_error ("Cannot allocate data handle for `%s'",
3110 img->spec, Qnil);
3111 return 0;
3113 success_p = image_load_qt_1 (f, img, type, NULL, dh);
3114 DisposeHandle (dh);
3115 return success_p;
3120 #ifdef MAC_OSX
3121 static int
3122 image_load_quartz2d (f, img, png_p)
3123 struct frame *f;
3124 struct image *img;
3125 int png_p;
3127 Lisp_Object file, specified_file;
3128 Lisp_Object specified_data, specified_bg;
3129 struct gcpro gcpro1;
3130 CGDataProviderRef source;
3131 CGImageRef image;
3132 int width, height;
3133 XColor color;
3134 XImagePtr ximg = NULL;
3135 CGContextRef context;
3136 CGRect rectangle;
3138 /* Open the file. */
3139 specified_file = image_spec_value (img->spec, QCfile, NULL);
3140 specified_data = image_spec_value (img->spec, QCdata, NULL);
3142 file = Qnil;
3143 GCPRO1 (file);
3145 if (NILP (specified_data))
3147 CFStringRef path;
3148 CFURLRef url;
3150 file = x_find_image_file (specified_file);
3151 if (!STRINGP (file))
3153 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3154 UNGCPRO;
3155 return 0;
3157 path = cfstring_create_with_utf8_cstring (SDATA (file));
3158 url = CFURLCreateWithFileSystemPath (NULL, path,
3159 kCFURLPOSIXPathStyle, 0);
3160 CFRelease (path);
3161 source = CGDataProviderCreateWithURL (url);
3162 CFRelease (url);
3164 else
3165 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
3166 SBYTES (specified_data), NULL);
3168 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3169 if (png_p)
3170 image = CGImageCreateWithPNGDataProvider (source, NULL, false,
3171 kCGRenderingIntentDefault);
3172 else
3173 #endif
3174 image = CGImageCreateWithJPEGDataProvider (source, NULL, false,
3175 kCGRenderingIntentDefault);
3177 CGDataProviderRelease (source);
3178 if (image == NULL)
3180 UNGCPRO;
3181 image_error ("Error reading image `%s'", img->spec, Qnil);
3182 return 0;
3184 width = img->width = CGImageGetWidth (image);
3185 height = img->height = CGImageGetHeight (image);
3187 if (!check_image_size (f, width, height))
3189 CGImageRelease (image);
3190 UNGCPRO;
3191 image_error ("Invalid image size", Qnil, Qnil);
3192 return 0;
3195 if (png_p)
3197 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
3198 if (!STRINGP (specified_bg) ||
3199 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
3201 color.pixel = FRAME_BACKGROUND_PIXEL (f);
3202 color.red = RED16_FROM_ULONG (color.pixel);
3203 color.green = GREEN16_FROM_ULONG (color.pixel);
3204 color.blue = BLUE16_FROM_ULONG (color.pixel);
3208 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
3210 CGImageRelease (image);
3211 UNGCPRO;
3212 return 0;
3214 rectangle = CGRectMake (0, 0, width, height);
3215 QDBeginCGContext (ximg, &context);
3216 if (png_p)
3218 CGContextSetRGBFillColor (context, color.red / 65535.0,
3219 color.green / 65535.0,
3220 color.blue / 65535.0, 1.0);
3221 CGContextFillRect (context, rectangle);
3223 CGContextDrawImage (context, rectangle, image);
3224 QDEndCGContext (ximg, &context);
3225 CGImageRelease (image);
3227 /* Maybe fill in the background field while we have ximg handy. */
3228 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3229 IMAGE_BACKGROUND (img, f, ximg);
3231 /* Put the image into the pixmap. */
3232 x_put_x_image (f, ximg, img->pixmap, width, height);
3233 x_destroy_x_image (ximg);
3234 UNGCPRO;
3235 return 1;
3237 #endif
3238 #endif /* !USE_MAC_IMAGE_IO */
3240 #endif /* MAC_OS */
3243 /***********************************************************************
3244 XBM images
3245 ***********************************************************************/
3247 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
3248 static int xbm_load P_ ((struct frame *f, struct image *img));
3249 static int xbm_load_image P_ ((struct frame *f, struct image *img,
3250 unsigned char *, unsigned char *));
3251 static int xbm_image_p P_ ((Lisp_Object object));
3252 static int xbm_read_bitmap_data P_ ((struct frame *f,
3253 unsigned char *, unsigned char *,
3254 int *, int *, unsigned char **));
3255 static int xbm_file_p P_ ((Lisp_Object));
3258 /* Indices of image specification fields in xbm_format, below. */
3260 enum xbm_keyword_index
3262 XBM_TYPE,
3263 XBM_FILE,
3264 XBM_WIDTH,
3265 XBM_HEIGHT,
3266 XBM_DATA,
3267 XBM_FOREGROUND,
3268 XBM_BACKGROUND,
3269 XBM_ASCENT,
3270 XBM_MARGIN,
3271 XBM_RELIEF,
3272 XBM_ALGORITHM,
3273 XBM_HEURISTIC_MASK,
3274 XBM_MASK,
3275 XBM_LAST
3278 /* Vector of image_keyword structures describing the format
3279 of valid XBM image specifications. */
3281 static struct image_keyword xbm_format[XBM_LAST] =
3283 {":type", IMAGE_SYMBOL_VALUE, 1},
3284 {":file", IMAGE_STRING_VALUE, 0},
3285 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3286 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3287 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3288 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
3289 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
3290 {":ascent", IMAGE_ASCENT_VALUE, 0},
3291 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3292 {":relief", IMAGE_INTEGER_VALUE, 0},
3293 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3294 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3295 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
3298 /* Structure describing the image type XBM. */
3300 static struct image_type xbm_type =
3302 &Qxbm,
3303 xbm_image_p,
3304 xbm_load,
3305 x_clear_image,
3306 NULL
3309 /* Tokens returned from xbm_scan. */
3311 enum xbm_token
3313 XBM_TK_IDENT = 256,
3314 XBM_TK_NUMBER
3318 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3319 A valid specification is a list starting with the symbol `image'
3320 The rest of the list is a property list which must contain an
3321 entry `:type xbm..
3323 If the specification specifies a file to load, it must contain
3324 an entry `:file FILENAME' where FILENAME is a string.
3326 If the specification is for a bitmap loaded from memory it must
3327 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3328 WIDTH and HEIGHT are integers > 0. DATA may be:
3330 1. a string large enough to hold the bitmap data, i.e. it must
3331 have a size >= (WIDTH + 7) / 8 * HEIGHT
3333 2. a bool-vector of size >= WIDTH * HEIGHT
3335 3. a vector of strings or bool-vectors, one for each line of the
3336 bitmap.
3338 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3339 may not be specified in this case because they are defined in the
3340 XBM file.
3342 Both the file and data forms may contain the additional entries
3343 `:background COLOR' and `:foreground COLOR'. If not present,
3344 foreground and background of the frame on which the image is
3345 displayed is used. */
3347 static int
3348 xbm_image_p (object)
3349 Lisp_Object object;
3351 struct image_keyword kw[XBM_LAST];
3353 bcopy (xbm_format, kw, sizeof kw);
3354 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
3355 return 0;
3357 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
3359 if (kw[XBM_FILE].count)
3361 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
3362 return 0;
3364 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
3366 /* In-memory XBM file. */
3367 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
3368 return 0;
3370 else
3372 Lisp_Object data;
3373 int width, height;
3375 /* Entries for `:width', `:height' and `:data' must be present. */
3376 if (!kw[XBM_WIDTH].count
3377 || !kw[XBM_HEIGHT].count
3378 || !kw[XBM_DATA].count)
3379 return 0;
3381 data = kw[XBM_DATA].value;
3382 width = XFASTINT (kw[XBM_WIDTH].value);
3383 height = XFASTINT (kw[XBM_HEIGHT].value);
3385 /* Check type of data, and width and height against contents of
3386 data. */
3387 if (VECTORP (data))
3389 int i;
3391 /* Number of elements of the vector must be >= height. */
3392 if (XVECTOR (data)->size < height)
3393 return 0;
3395 /* Each string or bool-vector in data must be large enough
3396 for one line of the image. */
3397 for (i = 0; i < height; ++i)
3399 Lisp_Object elt = XVECTOR (data)->contents[i];
3401 if (STRINGP (elt))
3403 if (SCHARS (elt)
3404 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
3405 return 0;
3407 else if (BOOL_VECTOR_P (elt))
3409 if (XBOOL_VECTOR (elt)->size < width)
3410 return 0;
3412 else
3413 return 0;
3416 else if (STRINGP (data))
3418 if (SCHARS (data)
3419 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
3420 return 0;
3422 else if (BOOL_VECTOR_P (data))
3424 if (XBOOL_VECTOR (data)->size < width * height)
3425 return 0;
3427 else
3428 return 0;
3431 return 1;
3435 /* Scan a bitmap file. FP is the stream to read from. Value is
3436 either an enumerator from enum xbm_token, or a character for a
3437 single-character token, or 0 at end of file. If scanning an
3438 identifier, store the lexeme of the identifier in SVAL. If
3439 scanning a number, store its value in *IVAL. */
3441 static int
3442 xbm_scan (s, end, sval, ival)
3443 unsigned char **s, *end;
3444 char *sval;
3445 int *ival;
3447 unsigned int c;
3449 loop:
3451 /* Skip white space. */
3452 while (*s < end && (c = *(*s)++, isspace (c)))
3455 if (*s >= end)
3456 c = 0;
3457 else if (isdigit (c))
3459 int value = 0, digit;
3461 if (c == '0' && *s < end)
3463 c = *(*s)++;
3464 if (c == 'x' || c == 'X')
3466 while (*s < end)
3468 c = *(*s)++;
3469 if (isdigit (c))
3470 digit = c - '0';
3471 else if (c >= 'a' && c <= 'f')
3472 digit = c - 'a' + 10;
3473 else if (c >= 'A' && c <= 'F')
3474 digit = c - 'A' + 10;
3475 else
3476 break;
3477 value = 16 * value + digit;
3480 else if (isdigit (c))
3482 value = c - '0';
3483 while (*s < end
3484 && (c = *(*s)++, isdigit (c)))
3485 value = 8 * value + c - '0';
3488 else
3490 value = c - '0';
3491 while (*s < end
3492 && (c = *(*s)++, isdigit (c)))
3493 value = 10 * value + c - '0';
3496 if (*s < end)
3497 *s = *s - 1;
3498 *ival = value;
3499 c = XBM_TK_NUMBER;
3501 else if (isalpha (c) || c == '_')
3503 *sval++ = c;
3504 while (*s < end
3505 && (c = *(*s)++, (isalnum (c) || c == '_')))
3506 *sval++ = c;
3507 *sval = 0;
3508 if (*s < end)
3509 *s = *s - 1;
3510 c = XBM_TK_IDENT;
3512 else if (c == '/' && **s == '*')
3514 /* C-style comment. */
3515 ++*s;
3516 while (**s && (**s != '*' || *(*s + 1) != '/'))
3517 ++*s;
3518 if (**s)
3520 *s += 2;
3521 goto loop;
3525 return c;
3528 #ifdef HAVE_NTGUI
3530 /* Create a Windows bitmap from X bitmap data. */
3531 static HBITMAP
3532 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
3534 static unsigned char swap_nibble[16]
3535 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3536 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3537 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3538 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3539 int i, j, w1, w2;
3540 unsigned char *bits, *p;
3541 HBITMAP bmp;
3543 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
3544 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3545 bits = (unsigned char *) alloca (height * w2);
3546 bzero (bits, height * w2);
3547 for (i = 0; i < height; i++)
3549 p = bits + i*w2;
3550 for (j = 0; j < w1; j++)
3552 /* Bitswap XBM bytes to match how Windows does things. */
3553 unsigned char c = *data++;
3554 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
3555 | (swap_nibble[(c>>4) & 0xf]));
3558 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
3560 return bmp;
3563 static void
3564 convert_mono_to_color_image (f, img, foreground, background)
3565 struct frame *f;
3566 struct image *img;
3567 COLORREF foreground, background;
3569 HDC hdc, old_img_dc, new_img_dc;
3570 HGDIOBJ old_prev, new_prev;
3571 HBITMAP new_pixmap;
3573 hdc = get_frame_dc (f);
3574 old_img_dc = CreateCompatibleDC (hdc);
3575 new_img_dc = CreateCompatibleDC (hdc);
3576 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
3577 release_frame_dc (f, hdc);
3578 old_prev = SelectObject (old_img_dc, img->pixmap);
3579 new_prev = SelectObject (new_img_dc, new_pixmap);
3580 /* Windows convention for mono bitmaps is black = background,
3581 white = foreground. */
3582 SetTextColor (new_img_dc, background);
3583 SetBkColor (new_img_dc, foreground);
3585 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
3586 0, 0, SRCCOPY);
3588 SelectObject (old_img_dc, old_prev);
3589 SelectObject (new_img_dc, new_prev);
3590 DeleteDC (old_img_dc);
3591 DeleteDC (new_img_dc);
3592 DeleteObject (img->pixmap);
3593 if (new_pixmap == 0)
3594 fprintf (stderr, "Failed to convert image to color.\n");
3595 else
3596 img->pixmap = new_pixmap;
3599 #define XBM_BIT_SHUFFLE(b) (~(b))
3601 #else
3603 #define XBM_BIT_SHUFFLE(b) (b)
3605 #endif /* HAVE_NTGUI */
3608 static void
3609 Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
3610 struct frame *f;
3611 struct image *img;
3612 char *data;
3613 RGB_PIXEL_COLOR fg, bg;
3614 int non_default_colors;
3616 #ifdef HAVE_NTGUI
3617 img->pixmap
3618 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
3620 /* If colors were specified, transfer the bitmap to a color one. */
3621 if (non_default_colors)
3622 convert_mono_to_color_image (f, img, fg, bg);
3624 #elif defined (HAVE_NS)
3625 img->pixmap = ns_image_from_XBM(data, img->width, img->height);
3627 #else
3628 img->pixmap
3629 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
3630 FRAME_X_WINDOW (f),
3631 data,
3632 img->width, img->height,
3633 fg, bg,
3634 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3635 #endif /* !HAVE_NTGUI && !HAVE_NS */
3640 /* Replacement for XReadBitmapFileData which isn't available under old
3641 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3642 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3643 the image. Return in *DATA the bitmap data allocated with xmalloc.
3644 Value is non-zero if successful. DATA null means just test if
3645 CONTENTS looks like an in-memory XBM file. */
3647 static int
3648 xbm_read_bitmap_data (f, contents, end, width, height, data)
3649 struct frame *f;
3650 unsigned char *contents, *end;
3651 int *width, *height;
3652 unsigned char **data;
3654 unsigned char *s = contents;
3655 char buffer[BUFSIZ];
3656 int padding_p = 0;
3657 int v10 = 0;
3658 int bytes_per_line, i, nbytes;
3659 unsigned char *p;
3660 int value;
3661 int LA1;
3663 #define match() \
3664 LA1 = xbm_scan (&s, end, buffer, &value)
3666 #define expect(TOKEN) \
3667 if (LA1 != (TOKEN)) \
3668 goto failure; \
3669 else \
3670 match ()
3672 #define expect_ident(IDENT) \
3673 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3674 match (); \
3675 else \
3676 goto failure
3678 *width = *height = -1;
3679 if (data)
3680 *data = NULL;
3681 LA1 = xbm_scan (&s, end, buffer, &value);
3683 /* Parse defines for width, height and hot-spots. */
3684 while (LA1 == '#')
3686 match ();
3687 expect_ident ("define");
3688 expect (XBM_TK_IDENT);
3690 if (LA1 == XBM_TK_NUMBER)
3692 char *p = strrchr (buffer, '_');
3693 p = p ? p + 1 : buffer;
3694 if (strcmp (p, "width") == 0)
3695 *width = value;
3696 else if (strcmp (p, "height") == 0)
3697 *height = value;
3699 expect (XBM_TK_NUMBER);
3702 if (!check_image_size (f, *width, *height))
3703 goto failure;
3704 else if (data == NULL)
3705 goto success;
3707 /* Parse bits. Must start with `static'. */
3708 expect_ident ("static");
3709 if (LA1 == XBM_TK_IDENT)
3711 if (strcmp (buffer, "unsigned") == 0)
3713 match ();
3714 expect_ident ("char");
3716 else if (strcmp (buffer, "short") == 0)
3718 match ();
3719 v10 = 1;
3720 if (*width % 16 && *width % 16 < 9)
3721 padding_p = 1;
3723 else if (strcmp (buffer, "char") == 0)
3724 match ();
3725 else
3726 goto failure;
3728 else
3729 goto failure;
3731 expect (XBM_TK_IDENT);
3732 expect ('[');
3733 expect (']');
3734 expect ('=');
3735 expect ('{');
3737 bytes_per_line = (*width + 7) / 8 + padding_p;
3738 nbytes = bytes_per_line * *height;
3739 p = *data = (unsigned char *) xmalloc (nbytes);
3741 if (v10)
3743 for (i = 0; i < nbytes; i += 2)
3745 int val = value;
3746 expect (XBM_TK_NUMBER);
3748 *p++ = XBM_BIT_SHUFFLE (val);
3749 if (!padding_p || ((i + 2) % bytes_per_line))
3750 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3752 if (LA1 == ',' || LA1 == '}')
3753 match ();
3754 else
3755 goto failure;
3758 else
3760 for (i = 0; i < nbytes; ++i)
3762 int val = value;
3763 expect (XBM_TK_NUMBER);
3765 *p++ = XBM_BIT_SHUFFLE (val);
3767 if (LA1 == ',' || LA1 == '}')
3768 match ();
3769 else
3770 goto failure;
3774 success:
3775 return 1;
3777 failure:
3779 if (data && *data)
3781 xfree (*data);
3782 *data = NULL;
3784 return 0;
3786 #undef match
3787 #undef expect
3788 #undef expect_ident
3792 /* Load XBM image IMG which will be displayed on frame F from buffer
3793 CONTENTS. END is the end of the buffer. Value is non-zero if
3794 successful. */
3796 static int
3797 xbm_load_image (f, img, contents, end)
3798 struct frame *f;
3799 struct image *img;
3800 unsigned char *contents, *end;
3802 int rc;
3803 unsigned char *data;
3804 int success_p = 0;
3806 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3807 if (rc)
3809 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3810 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3811 int non_default_colors = 0;
3812 Lisp_Object value;
3814 xassert (img->width > 0 && img->height > 0);
3816 /* Get foreground and background colors, maybe allocate colors. */
3817 value = image_spec_value (img->spec, QCforeground, NULL);
3818 if (!NILP (value))
3820 foreground = x_alloc_image_color (f, img, value, foreground);
3821 non_default_colors = 1;
3823 value = image_spec_value (img->spec, QCbackground, NULL);
3824 if (!NILP (value))
3826 background = x_alloc_image_color (f, img, value, background);
3827 img->background = background;
3828 img->background_valid = 1;
3829 non_default_colors = 1;
3832 Create_Pixmap_From_Bitmap_Data (f, img, data,
3833 foreground, background,
3834 non_default_colors);
3835 xfree (data);
3837 if (img->pixmap == NO_PIXMAP)
3839 x_clear_image (f, img);
3840 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3842 else
3843 success_p = 1;
3845 else
3846 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3848 return success_p;
3852 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3854 static int
3855 xbm_file_p (data)
3856 Lisp_Object data;
3858 int w, h;
3859 return (STRINGP (data)
3860 && xbm_read_bitmap_data (NULL, SDATA (data),
3861 (SDATA (data)
3862 + SBYTES (data)),
3863 &w, &h, NULL));
3867 /* Fill image IMG which is used on frame F with pixmap data. Value is
3868 non-zero if successful. */
3870 static int
3871 xbm_load (f, img)
3872 struct frame *f;
3873 struct image *img;
3875 int success_p = 0;
3876 Lisp_Object file_name;
3878 xassert (xbm_image_p (img->spec));
3880 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3881 file_name = image_spec_value (img->spec, QCfile, NULL);
3882 if (STRINGP (file_name))
3884 Lisp_Object file;
3885 unsigned char *contents;
3886 int size;
3887 struct gcpro gcpro1;
3889 file = x_find_image_file (file_name);
3890 GCPRO1 (file);
3891 if (!STRINGP (file))
3893 image_error ("Cannot find image file `%s'", file_name, Qnil);
3894 UNGCPRO;
3895 return 0;
3898 contents = slurp_file (SDATA (file), &size);
3899 if (contents == NULL)
3901 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3902 UNGCPRO;
3903 return 0;
3906 success_p = xbm_load_image (f, img, contents, contents + size);
3907 UNGCPRO;
3909 else
3911 struct image_keyword fmt[XBM_LAST];
3912 Lisp_Object data;
3913 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3914 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3915 int non_default_colors = 0;
3916 char *bits;
3917 int parsed_p;
3918 int in_memory_file_p = 0;
3920 /* See if data looks like an in-memory XBM file. */
3921 data = image_spec_value (img->spec, QCdata, NULL);
3922 in_memory_file_p = xbm_file_p (data);
3924 /* Parse the image specification. */
3925 bcopy (xbm_format, fmt, sizeof fmt);
3926 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3927 xassert (parsed_p);
3929 /* Get specified width, and height. */
3930 if (!in_memory_file_p)
3932 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3933 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3934 xassert (img->width > 0 && img->height > 0);
3937 /* Get foreground and background colors, maybe allocate colors. */
3938 if (fmt[XBM_FOREGROUND].count
3939 && STRINGP (fmt[XBM_FOREGROUND].value))
3941 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3942 foreground);
3943 non_default_colors = 1;
3946 if (fmt[XBM_BACKGROUND].count
3947 && STRINGP (fmt[XBM_BACKGROUND].value))
3949 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3950 background);
3951 non_default_colors = 1;
3954 if (in_memory_file_p)
3955 success_p = xbm_load_image (f, img, SDATA (data),
3956 (SDATA (data)
3957 + SBYTES (data)));
3958 else
3960 if (VECTORP (data))
3962 int i;
3963 char *p;
3964 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3966 p = bits = (char *) alloca (nbytes * img->height);
3967 for (i = 0; i < img->height; ++i, p += nbytes)
3969 Lisp_Object line = XVECTOR (data)->contents[i];
3970 if (STRINGP (line))
3971 bcopy (SDATA (line), p, nbytes);
3972 else
3973 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3976 else if (STRINGP (data))
3977 bits = SDATA (data);
3978 else
3979 bits = XBOOL_VECTOR (data)->data;
3981 #ifdef WINDOWSNT
3983 char *invertedBits;
3984 int nbytes, i;
3985 /* Windows mono bitmaps are reversed compared with X. */
3986 invertedBits = bits;
3987 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
3988 * img->height;
3989 bits = (char *) alloca(nbytes);
3990 for (i = 0; i < nbytes; i++)
3991 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3993 #endif
3994 /* Create the pixmap. */
3996 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3997 foreground, background,
3998 non_default_colors);
3999 if (img->pixmap)
4000 success_p = 1;
4001 else
4003 image_error ("Unable to create pixmap for XBM image `%s'",
4004 img->spec, Qnil);
4005 x_clear_image (f, img);
4010 return success_p;
4015 /***********************************************************************
4016 XPM images
4017 ***********************************************************************/
4019 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
4021 static int xpm_image_p P_ ((Lisp_Object object));
4022 static int xpm_load P_ ((struct frame *f, struct image *img));
4023 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
4025 #endif /* HAVE_XPM || MAC_OS || HAVE_NS */
4027 #ifdef HAVE_XPM
4028 #ifdef HAVE_NTGUI
4029 /* Indicate to xpm.h that we don't have Xlib. */
4030 #define FOR_MSW
4031 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
4032 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
4033 #define XColor xpm_XColor
4034 #define XImage xpm_XImage
4035 #define Display xpm_Display
4036 #define PIXEL_ALREADY_TYPEDEFED
4037 #include "X11/xpm.h"
4038 #undef FOR_MSW
4039 #undef XColor
4040 #undef XImage
4041 #undef Display
4042 #undef PIXEL_ALREADY_TYPEDEFED
4043 #else
4044 #include "X11/xpm.h"
4045 #endif /* HAVE_NTGUI */
4046 #endif /* HAVE_XPM */
4048 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
4049 /* The symbol `xpm' identifying XPM-format images. */
4051 Lisp_Object Qxpm;
4053 /* Indices of image specification fields in xpm_format, below. */
4055 enum xpm_keyword_index
4057 XPM_TYPE,
4058 XPM_FILE,
4059 XPM_DATA,
4060 XPM_ASCENT,
4061 XPM_MARGIN,
4062 XPM_RELIEF,
4063 XPM_ALGORITHM,
4064 XPM_HEURISTIC_MASK,
4065 XPM_MASK,
4066 XPM_COLOR_SYMBOLS,
4067 XPM_BACKGROUND,
4068 XPM_LAST
4071 /* Vector of image_keyword structures describing the format
4072 of valid XPM image specifications. */
4074 static struct image_keyword xpm_format[XPM_LAST] =
4076 {":type", IMAGE_SYMBOL_VALUE, 1},
4077 {":file", IMAGE_STRING_VALUE, 0},
4078 {":data", IMAGE_STRING_VALUE, 0},
4079 {":ascent", IMAGE_ASCENT_VALUE, 0},
4080 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
4081 {":relief", IMAGE_INTEGER_VALUE, 0},
4082 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4083 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4084 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4085 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4086 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
4089 /* Structure describing the image type XPM. */
4091 static struct image_type xpm_type =
4093 &Qxpm,
4094 xpm_image_p,
4095 xpm_load,
4096 x_clear_image,
4097 NULL
4100 #ifdef HAVE_X_WINDOWS
4102 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
4103 functions for allocating image colors. Our own functions handle
4104 color allocation failures more gracefully than the ones on the XPM
4105 lib. */
4107 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
4108 #define ALLOC_XPM_COLORS
4109 #endif
4110 #endif /* HAVE_X_WINDOWS */
4112 #ifdef ALLOC_XPM_COLORS
4114 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
4115 static void xpm_free_color_cache P_ ((void));
4116 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
4117 static int xpm_color_bucket P_ ((char *));
4118 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
4119 XColor *, int));
4121 /* An entry in a hash table used to cache color definitions of named
4122 colors. This cache is necessary to speed up XPM image loading in
4123 case we do color allocations ourselves. Without it, we would need
4124 a call to XParseColor per pixel in the image. */
4126 struct xpm_cached_color
4128 /* Next in collision chain. */
4129 struct xpm_cached_color *next;
4131 /* Color definition (RGB and pixel color). */
4132 XColor color;
4134 /* Color name. */
4135 char name[1];
4138 /* The hash table used for the color cache, and its bucket vector
4139 size. */
4141 #define XPM_COLOR_CACHE_BUCKETS 1001
4142 struct xpm_cached_color **xpm_color_cache;
4144 /* Initialize the color cache. */
4146 static void
4147 xpm_init_color_cache (f, attrs)
4148 struct frame *f;
4149 XpmAttributes *attrs;
4151 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
4152 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
4153 memset (xpm_color_cache, 0, nbytes);
4154 init_color_table ();
4156 if (attrs->valuemask & XpmColorSymbols)
4158 int i;
4159 XColor color;
4161 for (i = 0; i < attrs->numsymbols; ++i)
4162 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4163 attrs->colorsymbols[i].value, &color))
4165 color.pixel = lookup_rgb_color (f, color.red, color.green,
4166 color.blue);
4167 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
4172 /* Free the color cache. */
4174 static void
4175 xpm_free_color_cache ()
4177 struct xpm_cached_color *p, *next;
4178 int i;
4180 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
4181 for (p = xpm_color_cache[i]; p; p = next)
4183 next = p->next;
4184 xfree (p);
4187 xfree (xpm_color_cache);
4188 xpm_color_cache = NULL;
4189 free_color_table ();
4192 /* Return the bucket index for color named COLOR_NAME in the color
4193 cache. */
4195 static int
4196 xpm_color_bucket (color_name)
4197 char *color_name;
4199 unsigned h = 0;
4200 char *s;
4202 for (s = color_name; *s; ++s)
4203 h = (h << 2) ^ *s;
4204 return h %= XPM_COLOR_CACHE_BUCKETS;
4208 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4209 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4210 entry added. */
4212 static struct xpm_cached_color *
4213 xpm_cache_color (f, color_name, color, bucket)
4214 struct frame *f;
4215 char *color_name;
4216 XColor *color;
4217 int bucket;
4219 size_t nbytes;
4220 struct xpm_cached_color *p;
4222 if (bucket < 0)
4223 bucket = xpm_color_bucket (color_name);
4225 nbytes = sizeof *p + strlen (color_name);
4226 p = (struct xpm_cached_color *) xmalloc (nbytes);
4227 strcpy (p->name, color_name);
4228 p->color = *color;
4229 p->next = xpm_color_cache[bucket];
4230 xpm_color_cache[bucket] = p;
4231 return p;
4234 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4235 return the cached definition in *COLOR. Otherwise, make a new
4236 entry in the cache and allocate the color. Value is zero if color
4237 allocation failed. */
4239 static int
4240 xpm_lookup_color (f, color_name, color)
4241 struct frame *f;
4242 char *color_name;
4243 XColor *color;
4245 struct xpm_cached_color *p;
4246 int h = xpm_color_bucket (color_name);
4248 for (p = xpm_color_cache[h]; p; p = p->next)
4249 if (strcmp (p->name, color_name) == 0)
4250 break;
4252 if (p != NULL)
4253 *color = p->color;
4254 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4255 color_name, color))
4257 color->pixel = lookup_rgb_color (f, color->red, color->green,
4258 color->blue);
4259 p = xpm_cache_color (f, color_name, color, h);
4261 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4262 with transparency, and it's useful. */
4263 else if (strcmp ("opaque", color_name) == 0)
4265 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
4266 color->pixel = FRAME_FOREGROUND_PIXEL (f);
4267 p = xpm_cache_color (f, color_name, color, h);
4270 return p != NULL;
4274 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4275 CLOSURE is a pointer to the frame on which we allocate the
4276 color. Return in *COLOR the allocated color. Value is non-zero
4277 if successful. */
4279 static int
4280 xpm_alloc_color (dpy, cmap, color_name, color, closure)
4281 Display *dpy;
4282 Colormap cmap;
4283 char *color_name;
4284 XColor *color;
4285 void *closure;
4287 return xpm_lookup_color ((struct frame *) closure, color_name, color);
4291 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4292 is a pointer to the frame on which we allocate the color. Value is
4293 non-zero if successful. */
4295 static int
4296 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
4297 Display *dpy;
4298 Colormap cmap;
4299 Pixel *pixels;
4300 int npixels;
4301 void *closure;
4303 return 1;
4306 #endif /* ALLOC_XPM_COLORS */
4309 #ifdef HAVE_NTGUI
4311 /* XPM library details. */
4313 DEF_IMGLIB_FN (XpmFreeAttributes);
4314 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
4315 DEF_IMGLIB_FN (XpmReadFileToImage);
4316 DEF_IMGLIB_FN (XImageFree);
4318 static int
4319 init_xpm_functions (Lisp_Object libraries)
4321 HMODULE library;
4323 if (!(library = w32_delayed_load (libraries, Qxpm)))
4324 return 0;
4326 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
4327 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
4328 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
4329 LOAD_IMGLIB_FN (library, XImageFree);
4330 return 1;
4333 #endif /* HAVE_NTGUI */
4336 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4337 for XPM images. Such a list must consist of conses whose car and
4338 cdr are strings. */
4340 static int
4341 xpm_valid_color_symbols_p (color_symbols)
4342 Lisp_Object color_symbols;
4344 while (CONSP (color_symbols))
4346 Lisp_Object sym = XCAR (color_symbols);
4347 if (!CONSP (sym)
4348 || !STRINGP (XCAR (sym))
4349 || !STRINGP (XCDR (sym)))
4350 break;
4351 color_symbols = XCDR (color_symbols);
4354 return NILP (color_symbols);
4358 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4360 static int
4361 xpm_image_p (object)
4362 Lisp_Object object;
4364 struct image_keyword fmt[XPM_LAST];
4365 bcopy (xpm_format, fmt, sizeof fmt);
4366 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
4367 /* Either `:file' or `:data' must be present. */
4368 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
4369 /* Either no `:color-symbols' or it's a list of conses
4370 whose car and cdr are strings. */
4371 && (fmt[XPM_COLOR_SYMBOLS].count == 0
4372 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
4375 #endif /* HAVE_XPM || MAC_OS || HAVE_NS */
4377 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4379 x_create_bitmap_from_xpm_data (f, bits)
4380 struct frame *f;
4381 char **bits;
4383 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4384 int id, rc;
4385 XpmAttributes attrs;
4386 Pixmap bitmap, mask;
4388 bzero (&attrs, sizeof attrs);
4390 attrs.visual = FRAME_X_VISUAL (f);
4391 attrs.colormap = FRAME_X_COLORMAP (f);
4392 attrs.valuemask |= XpmVisual;
4393 attrs.valuemask |= XpmColormap;
4395 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4396 bits, &bitmap, &mask, &attrs);
4397 if (rc != XpmSuccess)
4399 XpmFreeAttributes (&attrs);
4400 return -1;
4403 id = x_allocate_bitmap_record (f);
4404 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
4405 dpyinfo->bitmaps[id - 1].have_mask = 1;
4406 dpyinfo->bitmaps[id - 1].mask = mask;
4407 dpyinfo->bitmaps[id - 1].file = NULL;
4408 dpyinfo->bitmaps[id - 1].height = attrs.height;
4409 dpyinfo->bitmaps[id - 1].width = attrs.width;
4410 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
4411 dpyinfo->bitmaps[id - 1].refcount = 1;
4413 XpmFreeAttributes (&attrs);
4414 return id;
4416 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4418 /* Load image IMG which will be displayed on frame F. Value is
4419 non-zero if successful. */
4421 #ifdef HAVE_XPM
4423 static int
4424 xpm_load (f, img)
4425 struct frame *f;
4426 struct image *img;
4428 int rc;
4429 XpmAttributes attrs;
4430 Lisp_Object specified_file, color_symbols;
4431 #ifdef HAVE_NTGUI
4432 HDC hdc;
4433 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
4434 #endif /* HAVE_NTGUI */
4436 /* Configure the XPM lib. Use the visual of frame F. Allocate
4437 close colors. Return colors allocated. */
4438 bzero (&attrs, sizeof attrs);
4440 #ifndef HAVE_NTGUI
4441 attrs.visual = FRAME_X_VISUAL (f);
4442 attrs.colormap = FRAME_X_COLORMAP (f);
4443 attrs.valuemask |= XpmVisual;
4444 attrs.valuemask |= XpmColormap;
4445 #endif /* HAVE_NTGUI */
4447 #ifdef ALLOC_XPM_COLORS
4448 /* Allocate colors with our own functions which handle
4449 failing color allocation more gracefully. */
4450 attrs.color_closure = f;
4451 attrs.alloc_color = xpm_alloc_color;
4452 attrs.free_colors = xpm_free_colors;
4453 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
4454 #else /* not ALLOC_XPM_COLORS */
4455 /* Let the XPM lib allocate colors. */
4456 attrs.valuemask |= XpmReturnAllocPixels;
4457 #ifdef XpmAllocCloseColors
4458 attrs.alloc_close_colors = 1;
4459 attrs.valuemask |= XpmAllocCloseColors;
4460 #else /* not XpmAllocCloseColors */
4461 attrs.closeness = 600;
4462 attrs.valuemask |= XpmCloseness;
4463 #endif /* not XpmAllocCloseColors */
4464 #endif /* ALLOC_XPM_COLORS */
4466 /* If image specification contains symbolic color definitions, add
4467 these to `attrs'. */
4468 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4469 if (CONSP (color_symbols))
4471 Lisp_Object tail;
4472 XpmColorSymbol *xpm_syms;
4473 int i, size;
4475 attrs.valuemask |= XpmColorSymbols;
4477 /* Count number of symbols. */
4478 attrs.numsymbols = 0;
4479 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
4480 ++attrs.numsymbols;
4482 /* Allocate an XpmColorSymbol array. */
4483 size = attrs.numsymbols * sizeof *xpm_syms;
4484 xpm_syms = (XpmColorSymbol *) alloca (size);
4485 bzero (xpm_syms, size);
4486 attrs.colorsymbols = xpm_syms;
4488 /* Fill the color symbol array. */
4489 for (tail = color_symbols, i = 0;
4490 CONSP (tail);
4491 ++i, tail = XCDR (tail))
4493 Lisp_Object name = XCAR (XCAR (tail));
4494 Lisp_Object color = XCDR (XCAR (tail));
4495 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
4496 strcpy (xpm_syms[i].name, SDATA (name));
4497 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
4498 strcpy (xpm_syms[i].value, SDATA (color));
4502 /* Create a pixmap for the image, either from a file, or from a
4503 string buffer containing data in the same format as an XPM file. */
4504 #ifdef ALLOC_XPM_COLORS
4505 xpm_init_color_cache (f, &attrs);
4506 #endif
4508 specified_file = image_spec_value (img->spec, QCfile, NULL);
4510 #ifdef HAVE_NTGUI
4512 HDC frame_dc = get_frame_dc (f);
4513 hdc = CreateCompatibleDC (frame_dc);
4514 release_frame_dc (f, frame_dc);
4516 #endif /* HAVE_NTGUI */
4518 if (STRINGP (specified_file))
4520 Lisp_Object file = x_find_image_file (specified_file);
4521 if (!STRINGP (file))
4523 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4524 return 0;
4527 #ifdef HAVE_NTGUI
4528 /* XpmReadFileToPixmap is not available in the Windows port of
4529 libxpm. But XpmReadFileToImage almost does what we want. */
4530 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
4531 &xpm_image, &xpm_mask,
4532 &attrs);
4533 #else
4534 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4535 SDATA (file), &img->pixmap, &img->mask,
4536 &attrs);
4537 #endif /* HAVE_NTGUI */
4539 else
4541 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
4542 #ifdef HAVE_NTGUI
4543 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4544 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4545 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
4546 &xpm_image, &xpm_mask,
4547 &attrs);
4548 #else
4549 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4550 SDATA (buffer),
4551 &img->pixmap, &img->mask,
4552 &attrs);
4553 #endif /* HAVE_NTGUI */
4556 if (rc == XpmSuccess)
4558 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4559 img->colors = colors_in_color_table (&img->ncolors);
4560 #else /* not ALLOC_XPM_COLORS */
4561 int i;
4563 #ifdef HAVE_NTGUI
4564 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4565 plus some duplicate attributes. */
4566 if (xpm_image && xpm_image->bitmap)
4568 img->pixmap = xpm_image->bitmap;
4569 /* XImageFree in libXpm frees XImage struct without destroying
4570 the bitmap, which is what we want. */
4571 fn_XImageFree (xpm_image);
4573 if (xpm_mask && xpm_mask->bitmap)
4575 /* The mask appears to be inverted compared with what we expect.
4576 TODO: invert our expectations. See other places where we
4577 have to invert bits because our idea of masks is backwards. */
4578 HGDIOBJ old_obj;
4579 old_obj = SelectObject (hdc, xpm_mask->bitmap);
4581 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
4582 SelectObject (hdc, old_obj);
4584 img->mask = xpm_mask->bitmap;
4585 fn_XImageFree (xpm_mask);
4586 DeleteDC (hdc);
4589 DeleteDC (hdc);
4590 #endif /* HAVE_NTGUI */
4592 /* Remember allocated colors. */
4593 img->ncolors = attrs.nalloc_pixels;
4594 img->colors = (unsigned long *) xmalloc (img->ncolors
4595 * sizeof *img->colors);
4596 for (i = 0; i < attrs.nalloc_pixels; ++i)
4598 img->colors[i] = attrs.alloc_pixels[i];
4599 #ifdef DEBUG_X_COLORS
4600 register_color (img->colors[i]);
4601 #endif
4603 #endif /* not ALLOC_XPM_COLORS */
4605 img->width = attrs.width;
4606 img->height = attrs.height;
4607 xassert (img->width > 0 && img->height > 0);
4609 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4610 #ifdef HAVE_NTGUI
4611 fn_XpmFreeAttributes (&attrs);
4612 #else
4613 XpmFreeAttributes (&attrs);
4614 #endif /* HAVE_NTGUI */
4616 else
4618 #ifdef HAVE_NTGUI
4619 DeleteDC (hdc);
4620 #endif /* HAVE_NTGUI */
4622 switch (rc)
4624 case XpmOpenFailed:
4625 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
4626 break;
4628 case XpmFileInvalid:
4629 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4630 break;
4632 case XpmNoMemory:
4633 image_error ("Out of memory (%s)", img->spec, Qnil);
4634 break;
4636 case XpmColorFailed:
4637 image_error ("Color allocation error (%s)", img->spec, Qnil);
4638 break;
4640 default:
4641 image_error ("Unknown error (%s)", img->spec, Qnil);
4642 break;
4646 #ifdef ALLOC_XPM_COLORS
4647 xpm_free_color_cache ();
4648 #endif
4649 return rc == XpmSuccess;
4652 #endif /* HAVE_XPM */
4654 #if defined (MAC_OS) || ( defined (HAVE_NS) && !defined (HAVE_XPM) )
4656 /* XPM support functions for Mac OS where libxpm is not available.
4657 Only XPM version 3 (without any extensions) is supported. */
4659 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
4660 const unsigned char **, int *));
4661 static Lisp_Object xpm_make_color_table_v
4662 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4663 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4664 static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
4665 int, Lisp_Object));
4666 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
4667 const unsigned char *, int));
4668 static Lisp_Object xpm_make_color_table_h
4669 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4670 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4671 static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
4672 int, Lisp_Object));
4673 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
4674 const unsigned char *, int));
4675 static int xpm_str_to_color_key P_ ((const char *));
4676 static int xpm_load_image P_ ((struct frame *, struct image *,
4677 const unsigned char *, const unsigned char *));
4679 /* Tokens returned from xpm_scan. */
4681 enum xpm_token
4683 XPM_TK_IDENT = 256,
4684 XPM_TK_STRING,
4685 XPM_TK_EOF
4688 /* Scan an XPM data and return a character (< 256) or a token defined
4689 by enum xpm_token above. *S and END are the start (inclusive) and
4690 the end (exclusive) addresses of the data, respectively. Advance
4691 *S while scanning. If token is either XPM_TK_IDENT or
4692 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4693 length of the corresponding token, respectively. */
4695 static int
4696 xpm_scan (s, end, beg, len)
4697 const unsigned char **s, *end, **beg;
4698 int *len;
4700 int c;
4702 while (*s < end)
4704 /* Skip white-space. */
4705 while (*s < end && (c = *(*s)++, isspace (c)))
4708 /* gnus-pointer.xpm uses '-' in its identifier.
4709 sb-dir-plus.xpm uses '+' in its identifier. */
4710 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4712 *beg = *s - 1;
4713 while (*s < end
4714 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4715 ++*s;
4716 *len = *s - *beg;
4717 return XPM_TK_IDENT;
4719 else if (c == '"')
4721 *beg = *s;
4722 while (*s < end && **s != '"')
4723 ++*s;
4724 *len = *s - *beg;
4725 if (*s < end)
4726 ++*s;
4727 return XPM_TK_STRING;
4729 else if (c == '/')
4731 if (*s < end && **s == '*')
4733 /* C-style comment. */
4734 ++*s;
4737 while (*s < end && *(*s)++ != '*')
4740 while (*s < end && **s != '/');
4741 if (*s < end)
4742 ++*s;
4744 else
4745 return c;
4747 else
4748 return c;
4751 return XPM_TK_EOF;
4754 /* Functions for color table lookup in XPM data. A key is a string
4755 specifying the color of each pixel in XPM data. A value is either
4756 an integer that specifies a pixel color, Qt that specifies
4757 transparency, or Qnil for the unspecified color. If the length of
4758 the key string is one, a vector is used as a table. Otherwise, a
4759 hash table is used. */
4761 static Lisp_Object
4762 xpm_make_color_table_v (put_func, get_func)
4763 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4764 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4766 *put_func = xpm_put_color_table_v;
4767 *get_func = xpm_get_color_table_v;
4768 return Fmake_vector (make_number (256), Qnil);
4771 static void
4772 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4773 Lisp_Object color_table;
4774 const unsigned char *chars_start;
4775 int chars_len;
4776 Lisp_Object color;
4778 XVECTOR (color_table)->contents[*chars_start] = color;
4781 static Lisp_Object
4782 xpm_get_color_table_v (color_table, chars_start, chars_len)
4783 Lisp_Object color_table;
4784 const unsigned char *chars_start;
4785 int chars_len;
4787 return XVECTOR (color_table)->contents[*chars_start];
4790 static Lisp_Object
4791 xpm_make_color_table_h (put_func, get_func)
4792 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4793 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4795 *put_func = xpm_put_color_table_h;
4796 *get_func = xpm_get_color_table_h;
4797 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4798 make_float (DEFAULT_REHASH_SIZE),
4799 make_float (DEFAULT_REHASH_THRESHOLD),
4800 Qnil, Qnil, Qnil);
4803 static void
4804 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4805 Lisp_Object color_table;
4806 const unsigned char *chars_start;
4807 int chars_len;
4808 Lisp_Object color;
4810 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4811 unsigned hash_code;
4812 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4814 hash_lookup (table, chars, &hash_code);
4815 hash_put (table, chars, color, hash_code);
4818 static Lisp_Object
4819 xpm_get_color_table_h (color_table, chars_start, chars_len)
4820 Lisp_Object color_table;
4821 const unsigned char *chars_start;
4822 int chars_len;
4824 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4825 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4826 NULL);
4828 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4831 enum xpm_color_key {
4832 XPM_COLOR_KEY_S,
4833 XPM_COLOR_KEY_M,
4834 XPM_COLOR_KEY_G4,
4835 XPM_COLOR_KEY_G,
4836 XPM_COLOR_KEY_C
4839 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4841 static int
4842 xpm_str_to_color_key (s)
4843 const char *s;
4845 int i;
4847 for (i = 0;
4848 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4849 i++)
4850 if (strcmp (xpm_color_key_strings[i], s) == 0)
4851 return i;
4852 return -1;
4855 static int
4856 xpm_load_image (f, img, contents, end)
4857 struct frame *f;
4858 struct image *img;
4859 const unsigned char *contents, *end;
4861 const unsigned char *s = contents, *beg, *str;
4862 unsigned char buffer[BUFSIZ];
4863 int width, height, x, y;
4864 int num_colors, chars_per_pixel;
4865 int len, LA1;
4866 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4867 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
4868 Lisp_Object frame, color_symbols, color_table;
4869 int best_key, have_mask = 0;
4870 XImagePtr ximg = NULL, mask_img = NULL;
4872 #define match() \
4873 LA1 = xpm_scan (&s, end, &beg, &len)
4875 #define expect(TOKEN) \
4876 if (LA1 != (TOKEN)) \
4877 goto failure; \
4878 else \
4879 match ()
4881 #define expect_ident(IDENT) \
4882 if (LA1 == XPM_TK_IDENT \
4883 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4884 match (); \
4885 else \
4886 goto failure
4888 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4889 goto failure;
4890 s += 9;
4891 match();
4892 expect_ident ("static");
4893 expect_ident ("char");
4894 expect ('*');
4895 expect (XPM_TK_IDENT);
4896 expect ('[');
4897 expect (']');
4898 expect ('=');
4899 expect ('{');
4900 expect (XPM_TK_STRING);
4901 if (len >= BUFSIZ)
4902 goto failure;
4903 memcpy (buffer, beg, len);
4904 buffer[len] = '\0';
4905 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4906 &num_colors, &chars_per_pixel) != 4
4907 || width <= 0 || height <= 0
4908 || num_colors <= 0 || chars_per_pixel <= 0)
4909 goto failure;
4911 if (!check_image_size (f, width, height))
4913 image_error ("Invalid image size", Qnil, Qnil);
4914 goto failure;
4917 expect (',');
4919 XSETFRAME (frame, f);
4920 if (!NILP (Fxw_display_color_p (frame)))
4921 best_key = XPM_COLOR_KEY_C;
4922 else if (!NILP (Fx_display_grayscale_p (frame)))
4923 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4924 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4925 else
4926 best_key = XPM_COLOR_KEY_M;
4928 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4929 if (chars_per_pixel == 1)
4930 color_table = xpm_make_color_table_v (&put_color_table,
4931 &get_color_table);
4932 else
4933 color_table = xpm_make_color_table_h (&put_color_table,
4934 &get_color_table);
4936 while (num_colors-- > 0)
4938 unsigned char *color, *max_color;
4939 int key, next_key, max_key = 0;
4940 Lisp_Object symbol_color = Qnil, color_val;
4941 XColor cdef;
4943 expect (XPM_TK_STRING);
4944 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4945 goto failure;
4946 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4947 buffer[len - chars_per_pixel] = '\0';
4949 str = strtok (buffer, " \t");
4950 if (str == NULL)
4951 goto failure;
4952 key = xpm_str_to_color_key (str);
4953 if (key < 0)
4954 goto failure;
4957 color = strtok (NULL, " \t");
4958 if (color == NULL)
4959 goto failure;
4961 while ((str = strtok (NULL, " \t")) != NULL)
4963 next_key = xpm_str_to_color_key (str);
4964 if (next_key >= 0)
4965 break;
4966 color[strlen (color)] = ' ';
4969 if (key == XPM_COLOR_KEY_S)
4971 if (NILP (symbol_color))
4972 symbol_color = build_string (color);
4974 else if (max_key < key && key <= best_key)
4976 max_key = key;
4977 max_color = color;
4979 key = next_key;
4981 while (str);
4983 color_val = Qnil;
4984 if (!NILP (color_symbols) && !NILP (symbol_color))
4986 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4988 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4990 if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0)
4991 color_val = Qt;
4992 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4993 &cdef, 0))
4994 color_val = make_number (cdef.pixel);
4997 if (NILP (color_val) && max_key > 0)
4999 if (xstrcasecmp (max_color, "None") == 0)
5000 color_val = Qt;
5001 else if (x_defined_color (f, max_color, &cdef, 0))
5002 color_val = make_number (cdef.pixel);
5004 if (!NILP (color_val))
5005 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
5007 expect (',');
5010 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5011 &ximg, &img->pixmap)
5012 #ifndef HAVE_NS
5013 || !x_create_x_image_and_pixmap (f, width, height, 1,
5014 &mask_img, &img->mask)
5015 #endif
5018 image_error ("Out of memory (%s)", img->spec, Qnil);
5019 goto error;
5022 for (y = 0; y < height; y++)
5024 expect (XPM_TK_STRING);
5025 str = beg;
5026 if (len < width * chars_per_pixel)
5027 goto failure;
5028 for (x = 0; x < width; x++, str += chars_per_pixel)
5030 Lisp_Object color_val =
5031 (*get_color_table) (color_table, str, chars_per_pixel);
5033 XPutPixel (ximg, x, y,
5034 (INTEGERP (color_val) ? XINT (color_val)
5035 : FRAME_FOREGROUND_PIXEL (f)));
5036 #ifndef HAVE_NS
5037 XPutPixel (mask_img, x, y,
5038 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
5039 : (have_mask = 1, PIX_MASK_RETAIN)));
5040 #else
5041 if (EQ(color_val, Qt))
5042 ns_set_alpha(ximg, x, y, 0);
5043 #endif
5045 if (y + 1 < height)
5046 expect (',');
5049 img->width = width;
5050 img->height = height;
5052 /* Maybe fill in the background field while we have ximg handy. */
5053 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5054 IMAGE_BACKGROUND (img, f, ximg);
5056 x_put_x_image (f, ximg, img->pixmap, width, height);
5057 x_destroy_x_image (ximg);
5058 #ifndef HAVE_NS
5059 if (have_mask)
5061 /* Fill in the background_transparent field while we have the
5062 mask handy. */
5063 image_background_transparent (img, f, mask_img);
5065 x_put_x_image (f, mask_img, img->mask, width, height);
5066 x_destroy_x_image (mask_img);
5068 else
5070 x_destroy_x_image (mask_img);
5071 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5072 img->mask = NO_PIXMAP;
5074 #endif
5075 return 1;
5077 failure:
5078 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
5079 error:
5080 x_destroy_x_image (ximg);
5081 x_destroy_x_image (mask_img);
5082 x_clear_image (f, img);
5083 return 0;
5085 #undef match
5086 #undef expect
5087 #undef expect_ident
5090 static int
5091 xpm_load (f, img)
5092 struct frame *f;
5093 struct image *img;
5095 int success_p = 0;
5096 Lisp_Object file_name;
5098 /* If IMG->spec specifies a file name, create a non-file spec from it. */
5099 file_name = image_spec_value (img->spec, QCfile, NULL);
5100 if (STRINGP (file_name))
5102 Lisp_Object file;
5103 unsigned char *contents;
5104 int size;
5105 struct gcpro gcpro1;
5107 file = x_find_image_file (file_name);
5108 GCPRO1 (file);
5109 if (!STRINGP (file))
5111 image_error ("Cannot find image file `%s'", file_name, Qnil);
5112 UNGCPRO;
5113 return 0;
5116 contents = slurp_file (SDATA (file), &size);
5117 if (contents == NULL)
5119 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
5120 UNGCPRO;
5121 return 0;
5124 success_p = xpm_load_image (f, img, contents, contents + size);
5125 xfree (contents);
5126 UNGCPRO;
5128 else
5130 Lisp_Object data;
5132 data = image_spec_value (img->spec, QCdata, NULL);
5133 success_p = xpm_load_image (f, img, SDATA (data),
5134 SDATA (data) + SBYTES (data));
5137 return success_p;
5140 #endif /* MAC_OS || (HAVE_NS && !HAVE_XPM) */
5144 /***********************************************************************
5145 Color table
5146 ***********************************************************************/
5148 #ifdef COLOR_TABLE_SUPPORT
5150 /* An entry in the color table mapping an RGB color to a pixel color. */
5152 struct ct_color
5154 int r, g, b;
5155 unsigned long pixel;
5157 /* Next in color table collision list. */
5158 struct ct_color *next;
5161 /* The bucket vector size to use. Must be prime. */
5163 #define CT_SIZE 101
5165 /* Value is a hash of the RGB color given by R, G, and B. */
5167 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5169 /* The color hash table. */
5171 struct ct_color **ct_table;
5173 /* Number of entries in the color table. */
5175 int ct_colors_allocated;
5177 /* Initialize the color table. */
5179 static void
5180 init_color_table ()
5182 int size = CT_SIZE * sizeof (*ct_table);
5183 ct_table = (struct ct_color **) xmalloc (size);
5184 bzero (ct_table, size);
5185 ct_colors_allocated = 0;
5189 /* Free memory associated with the color table. */
5191 static void
5192 free_color_table ()
5194 int i;
5195 struct ct_color *p, *next;
5197 for (i = 0; i < CT_SIZE; ++i)
5198 for (p = ct_table[i]; p; p = next)
5200 next = p->next;
5201 xfree (p);
5204 xfree (ct_table);
5205 ct_table = NULL;
5209 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5210 entry for that color already is in the color table, return the
5211 pixel color of that entry. Otherwise, allocate a new color for R,
5212 G, B, and make an entry in the color table. */
5214 static unsigned long
5215 lookup_rgb_color (f, r, g, b)
5216 struct frame *f;
5217 int r, g, b;
5219 unsigned hash = CT_HASH_RGB (r, g, b);
5220 int i = hash % CT_SIZE;
5221 struct ct_color *p;
5222 Display_Info *dpyinfo;
5224 /* Handle TrueColor visuals specially, which improves performance by
5225 two orders of magnitude. Freeing colors on TrueColor visuals is
5226 a nop, and pixel colors specify RGB values directly. See also
5227 the Xlib spec, chapter 3.1. */
5228 dpyinfo = FRAME_X_DISPLAY_INFO (f);
5229 if (dpyinfo->red_bits > 0)
5231 unsigned long pr, pg, pb;
5233 /* Apply gamma-correction like normal color allocation does. */
5234 if (f->gamma)
5236 XColor color;
5237 color.red = r, color.green = g, color.blue = b;
5238 gamma_correct (f, &color);
5239 r = color.red, g = color.green, b = color.blue;
5242 /* Scale down RGB values to the visual's bits per RGB, and shift
5243 them to the right position in the pixel color. Note that the
5244 original RGB values are 16-bit values, as usual in X. */
5245 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
5246 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
5247 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
5249 /* Assemble the pixel color. */
5250 return pr | pg | pb;
5253 for (p = ct_table[i]; p; p = p->next)
5254 if (p->r == r && p->g == g && p->b == b)
5255 break;
5257 if (p == NULL)
5260 #ifdef HAVE_X_WINDOWS
5261 XColor color;
5262 Colormap cmap;
5263 int rc;
5265 color.red = r;
5266 color.green = g;
5267 color.blue = b;
5269 cmap = FRAME_X_COLORMAP (f);
5270 rc = x_alloc_nearest_color (f, cmap, &color);
5271 if (rc)
5273 ++ct_colors_allocated;
5274 p = (struct ct_color *) xmalloc (sizeof *p);
5275 p->r = r;
5276 p->g = g;
5277 p->b = b;
5278 p->pixel = color.pixel;
5279 p->next = ct_table[i];
5280 ct_table[i] = p;
5282 else
5283 return FRAME_FOREGROUND_PIXEL (f);
5285 #else
5286 COLORREF color;
5287 #ifdef HAVE_NTGUI
5288 color = PALETTERGB (r, g, b);
5289 #else
5290 color = RGB_TO_ULONG (r, g, b);
5291 #endif /* HAVE_NTGUI */
5292 ++ct_colors_allocated;
5293 p = (struct ct_color *) xmalloc (sizeof *p);
5294 p->r = r;
5295 p->g = g;
5296 p->b = b;
5297 p->pixel = color;
5298 p->next = ct_table[i];
5299 ct_table[i] = p;
5300 #endif /* HAVE_X_WINDOWS */
5304 return p->pixel;
5308 /* Look up pixel color PIXEL which is used on frame F in the color
5309 table. If not already present, allocate it. Value is PIXEL. */
5311 static unsigned long
5312 lookup_pixel_color (f, pixel)
5313 struct frame *f;
5314 unsigned long pixel;
5316 int i = pixel % CT_SIZE;
5317 struct ct_color *p;
5319 for (p = ct_table[i]; p; p = p->next)
5320 if (p->pixel == pixel)
5321 break;
5323 if (p == NULL)
5325 XColor color;
5326 Colormap cmap;
5327 int rc;
5329 #ifdef HAVE_X_WINDOWS
5330 cmap = FRAME_X_COLORMAP (f);
5331 color.pixel = pixel;
5332 x_query_color (f, &color);
5333 rc = x_alloc_nearest_color (f, cmap, &color);
5334 #else
5335 BLOCK_INPUT;
5336 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5337 color.pixel = pixel;
5338 XQueryColor (NULL, cmap, &color);
5339 rc = x_alloc_nearest_color (f, cmap, &color);
5340 UNBLOCK_INPUT;
5341 #endif /* HAVE_X_WINDOWS */
5343 if (rc)
5345 ++ct_colors_allocated;
5347 p = (struct ct_color *) xmalloc (sizeof *p);
5348 p->r = color.red;
5349 p->g = color.green;
5350 p->b = color.blue;
5351 p->pixel = pixel;
5352 p->next = ct_table[i];
5353 ct_table[i] = p;
5355 else
5356 return FRAME_FOREGROUND_PIXEL (f);
5358 return p->pixel;
5362 /* Value is a vector of all pixel colors contained in the color table,
5363 allocated via xmalloc. Set *N to the number of colors. */
5365 static unsigned long *
5366 colors_in_color_table (n)
5367 int *n;
5369 int i, j;
5370 struct ct_color *p;
5371 unsigned long *colors;
5373 if (ct_colors_allocated == 0)
5375 *n = 0;
5376 colors = NULL;
5378 else
5380 colors = (unsigned long *) xmalloc (ct_colors_allocated
5381 * sizeof *colors);
5382 *n = ct_colors_allocated;
5384 for (i = j = 0; i < CT_SIZE; ++i)
5385 for (p = ct_table[i]; p; p = p->next)
5386 colors[j++] = p->pixel;
5389 return colors;
5392 #else /* COLOR_TABLE_SUPPORT */
5394 static unsigned long
5395 lookup_rgb_color (f, r, g, b)
5396 struct frame *f;
5397 int r, g, b;
5399 unsigned long pixel;
5401 #ifdef MAC_OS
5402 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
5403 gamma_correct (f, &pixel);
5404 #endif /* MAC_OS */
5406 #ifdef HAVE_NTGUI
5407 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
5408 #endif /* HAVE_NTGUI */
5410 #ifdef HAVE_NS
5411 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
5412 #endif /* HAVE_NS */
5413 return pixel;
5416 static void
5417 init_color_table ()
5420 #endif /* COLOR_TABLE_SUPPORT */
5423 /***********************************************************************
5424 Algorithms
5425 ***********************************************************************/
5427 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
5428 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
5429 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
5431 #ifdef HAVE_NTGUI
5432 static void XPutPixel (XImagePtr , int, int, COLORREF);
5433 #endif /* HAVE_NTGUI */
5435 /* Non-zero means draw a cross on images having `:conversion
5436 disabled'. */
5438 int cross_disabled_images;
5440 /* Edge detection matrices for different edge-detection
5441 strategies. */
5443 static int emboss_matrix[9] = {
5444 /* x - 1 x x + 1 */
5445 2, -1, 0, /* y - 1 */
5446 -1, 0, 1, /* y */
5447 0, 1, -2 /* y + 1 */
5450 static int laplace_matrix[9] = {
5451 /* x - 1 x x + 1 */
5452 1, 0, 0, /* y - 1 */
5453 0, 0, 0, /* y */
5454 0, 0, -1 /* y + 1 */
5457 /* Value is the intensity of the color whose red/green/blue values
5458 are R, G, and B. */
5460 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5463 /* On frame F, return an array of XColor structures describing image
5464 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5465 non-zero means also fill the red/green/blue members of the XColor
5466 structures. Value is a pointer to the array of XColors structures,
5467 allocated with xmalloc; it must be freed by the caller. */
5469 static XColor *
5470 x_to_xcolors (f, img, rgb_p)
5471 struct frame *f;
5472 struct image *img;
5473 int rgb_p;
5475 int x, y;
5476 XColor *colors, *p;
5477 XImagePtr_or_DC ximg;
5478 #ifdef HAVE_NTGUI
5479 HDC hdc;
5480 HGDIOBJ prev;
5481 #endif /* HAVE_NTGUI */
5483 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
5485 #ifndef HAVE_NTGUI
5486 /* Get the X image IMG->pixmap. */
5487 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
5488 0, 0, img->width, img->height, ~0, ZPixmap);
5489 #else
5490 /* Load the image into a memory device context. */
5491 hdc = get_frame_dc (f);
5492 ximg = CreateCompatibleDC (hdc);
5493 release_frame_dc (f, hdc);
5494 prev = SelectObject (ximg, img->pixmap);
5495 #endif /* HAVE_NTGUI */
5497 /* Fill the `pixel' members of the XColor array. I wished there
5498 were an easy and portable way to circumvent XGetPixel. */
5499 p = colors;
5500 for (y = 0; y < img->height; ++y)
5502 XColor *row = p;
5504 #ifdef HAVE_X_WINDOWS
5505 for (x = 0; x < img->width; ++x, ++p)
5506 p->pixel = XGetPixel (ximg, x, y);
5507 if (rgb_p)
5508 x_query_colors (f, row, img->width);
5510 #else
5512 for (x = 0; x < img->width; ++x, ++p)
5514 /* W32_TODO: palette support needed here? */
5515 p->pixel = GET_PIXEL (ximg, x, y);
5516 if (rgb_p)
5518 #if defined (MAC_OS) || defined (HAVE_NS)
5519 p->red = RED16_FROM_ULONG (p->pixel);
5520 p->green = GREEN16_FROM_ULONG (p->pixel);
5521 p->blue = BLUE16_FROM_ULONG (p->pixel);
5522 #endif /* MAC_OS */
5523 #ifdef HAVE_NTGUI
5524 p->red = 256 * GetRValue (p->pixel);
5525 p->green = 256 * GetGValue (p->pixel);
5526 p->blue = 256 * GetBValue (p->pixel);
5527 #endif /* HAVE_NTGUI */
5530 #endif /* HAVE_X_WINDOWS */
5533 Destroy_Image (ximg, prev);
5535 return colors;
5538 #ifdef HAVE_NTGUI
5540 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5541 created with CreateDIBSection, with the pointer to the bit values
5542 stored in ximg->data. */
5544 static void
5545 XPutPixel (ximg, x, y, color)
5546 XImagePtr ximg;
5547 int x, y;
5548 COLORREF color;
5550 int width = ximg->info.bmiHeader.biWidth;
5551 int height = ximg->info.bmiHeader.biHeight;
5552 unsigned char * pixel;
5554 /* True color images. */
5555 if (ximg->info.bmiHeader.biBitCount == 24)
5557 int rowbytes = width * 3;
5558 /* Ensure scanlines are aligned on 4 byte boundaries. */
5559 if (rowbytes % 4)
5560 rowbytes += 4 - (rowbytes % 4);
5562 pixel = ximg->data + y * rowbytes + x * 3;
5563 /* Windows bitmaps are in BGR order. */
5564 *pixel = GetBValue (color);
5565 *(pixel + 1) = GetGValue (color);
5566 *(pixel + 2) = GetRValue (color);
5568 /* Monochrome images. */
5569 else if (ximg->info.bmiHeader.biBitCount == 1)
5571 int rowbytes = width / 8;
5572 /* Ensure scanlines are aligned on 4 byte boundaries. */
5573 if (rowbytes % 4)
5574 rowbytes += 4 - (rowbytes % 4);
5575 pixel = ximg->data + y * rowbytes + x / 8;
5576 /* Filter out palette info. */
5577 if (color & 0x00ffffff)
5578 *pixel = *pixel | (1 << x % 8);
5579 else
5580 *pixel = *pixel & ~(1 << x % 8);
5582 else
5583 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
5586 #endif /* HAVE_NTGUI */
5588 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5589 RGB members are set. F is the frame on which this all happens.
5590 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5592 static void
5593 x_from_xcolors (f, img, colors)
5594 struct frame *f;
5595 struct image *img;
5596 XColor *colors;
5598 int x, y;
5599 XImagePtr oimg = NULL;
5600 Pixmap pixmap = NULL;
5601 XColor *p;
5603 init_color_table ();
5605 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5606 &oimg, &pixmap);
5607 p = colors;
5608 for (y = 0; y < img->height; ++y)
5609 for (x = 0; x < img->width; ++x, ++p)
5611 unsigned long pixel;
5612 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
5613 XPutPixel (oimg, x, y, pixel);
5616 xfree (colors);
5617 x_clear_image_1 (f, img, 1, 0, 1);
5619 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5620 x_destroy_x_image (oimg);
5621 img->pixmap = pixmap;
5622 #ifdef COLOR_TABLE_SUPPORT
5623 img->colors = colors_in_color_table (&img->ncolors);
5624 free_color_table ();
5625 #endif /* COLOR_TABLE_SUPPORT */
5629 /* On frame F, perform edge-detection on image IMG.
5631 MATRIX is a nine-element array specifying the transformation
5632 matrix. See emboss_matrix for an example.
5634 COLOR_ADJUST is a color adjustment added to each pixel of the
5635 outgoing image. */
5637 static void
5638 x_detect_edges (f, img, matrix, color_adjust)
5639 struct frame *f;
5640 struct image *img;
5641 int matrix[9], color_adjust;
5643 XColor *colors = x_to_xcolors (f, img, 1);
5644 XColor *new, *p;
5645 int x, y, i, sum;
5647 for (i = sum = 0; i < 9; ++i)
5648 sum += eabs (matrix[i]);
5650 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5652 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5654 for (y = 0; y < img->height; ++y)
5656 p = COLOR (new, 0, y);
5657 p->red = p->green = p->blue = 0xffff/2;
5658 p = COLOR (new, img->width - 1, y);
5659 p->red = p->green = p->blue = 0xffff/2;
5662 for (x = 1; x < img->width - 1; ++x)
5664 p = COLOR (new, x, 0);
5665 p->red = p->green = p->blue = 0xffff/2;
5666 p = COLOR (new, x, img->height - 1);
5667 p->red = p->green = p->blue = 0xffff/2;
5670 for (y = 1; y < img->height - 1; ++y)
5672 p = COLOR (new, 1, y);
5674 for (x = 1; x < img->width - 1; ++x, ++p)
5676 int r, g, b, y1, x1;
5678 r = g = b = i = 0;
5679 for (y1 = y - 1; y1 < y + 2; ++y1)
5680 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
5681 if (matrix[i])
5683 XColor *t = COLOR (colors, x1, y1);
5684 r += matrix[i] * t->red;
5685 g += matrix[i] * t->green;
5686 b += matrix[i] * t->blue;
5689 r = (r / sum + color_adjust) & 0xffff;
5690 g = (g / sum + color_adjust) & 0xffff;
5691 b = (b / sum + color_adjust) & 0xffff;
5692 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
5696 xfree (colors);
5697 x_from_xcolors (f, img, new);
5699 #undef COLOR
5703 /* Perform the pre-defined `emboss' edge-detection on image IMG
5704 on frame F. */
5706 static void
5707 x_emboss (f, img)
5708 struct frame *f;
5709 struct image *img;
5711 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
5715 /* Transform image IMG which is used on frame F with a Laplace
5716 edge-detection algorithm. The result is an image that can be used
5717 to draw disabled buttons, for example. */
5719 static void
5720 x_laplace (f, img)
5721 struct frame *f;
5722 struct image *img;
5724 x_detect_edges (f, img, laplace_matrix, 45000);
5728 /* Perform edge-detection on image IMG on frame F, with specified
5729 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5731 MATRIX must be either
5733 - a list of at least 9 numbers in row-major form
5734 - a vector of at least 9 numbers
5736 COLOR_ADJUST nil means use a default; otherwise it must be a
5737 number. */
5739 static void
5740 x_edge_detection (f, img, matrix, color_adjust)
5741 struct frame *f;
5742 struct image *img;
5743 Lisp_Object matrix, color_adjust;
5745 int i = 0;
5746 int trans[9];
5748 if (CONSP (matrix))
5750 for (i = 0;
5751 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5752 ++i, matrix = XCDR (matrix))
5753 trans[i] = XFLOATINT (XCAR (matrix));
5755 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5757 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5758 trans[i] = XFLOATINT (AREF (matrix, i));
5761 if (NILP (color_adjust))
5762 color_adjust = make_number (0xffff / 2);
5764 if (i == 9 && NUMBERP (color_adjust))
5765 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5769 /* Transform image IMG on frame F so that it looks disabled. */
5771 static void
5772 x_disable_image (f, img)
5773 struct frame *f;
5774 struct image *img;
5776 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5777 #ifdef HAVE_NTGUI
5778 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5779 #else
5780 int n_planes = dpyinfo->n_planes;
5781 #endif /* HAVE_NTGUI */
5783 if (n_planes >= 2)
5785 /* Color (or grayscale). Convert to gray, and equalize. Just
5786 drawing such images with a stipple can look very odd, so
5787 we're using this method instead. */
5788 XColor *colors = x_to_xcolors (f, img, 1);
5789 XColor *p, *end;
5790 const int h = 15000;
5791 const int l = 30000;
5793 for (p = colors, end = colors + img->width * img->height;
5794 p < end;
5795 ++p)
5797 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5798 int i2 = (0xffff - h - l) * i / 0xffff + l;
5799 p->red = p->green = p->blue = i2;
5802 x_from_xcolors (f, img, colors);
5805 /* Draw a cross over the disabled image, if we must or if we
5806 should. */
5807 if (n_planes < 2 || cross_disabled_images)
5809 #ifndef HAVE_NTGUI
5810 Display *dpy = FRAME_X_DISPLAY (f);
5811 GC gc;
5813 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5815 #ifdef MAC_OS
5816 #define MaskForeground(f) PIX_MASK_DRAW
5817 #else
5818 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5819 #endif
5821 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
5822 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5823 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5824 img->width - 1, img->height - 1);
5825 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5826 img->width - 1, 0);
5827 XFreeGC (dpy, gc);
5829 if (img->mask)
5831 gc = XCreateGC (dpy, img->mask, 0, NULL);
5832 XSetForeground (dpy, gc, MaskForeground (f));
5833 XDrawLine (dpy, img->mask, gc, 0, 0,
5834 img->width - 1, img->height - 1);
5835 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5836 img->width - 1, 0);
5837 XFreeGC (dpy, gc);
5839 #endif /* !HAVE_NS */
5840 #else
5841 HDC hdc, bmpdc;
5842 HGDIOBJ prev;
5844 hdc = get_frame_dc (f);
5845 bmpdc = CreateCompatibleDC (hdc);
5846 release_frame_dc (f, hdc);
5848 prev = SelectObject (bmpdc, img->pixmap);
5850 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5851 MoveToEx (bmpdc, 0, 0, NULL);
5852 LineTo (bmpdc, img->width - 1, img->height - 1);
5853 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5854 LineTo (bmpdc, img->width - 1, 0);
5856 if (img->mask)
5858 SelectObject (bmpdc, img->mask);
5859 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5860 MoveToEx (bmpdc, 0, 0, NULL);
5861 LineTo (bmpdc, img->width - 1, img->height - 1);
5862 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5863 LineTo (bmpdc, img->width - 1, 0);
5865 SelectObject (bmpdc, prev);
5866 DeleteDC (bmpdc);
5867 #endif /* HAVE_NTGUI */
5872 /* Build a mask for image IMG which is used on frame F. FILE is the
5873 name of an image file, for error messages. HOW determines how to
5874 determine the background color of IMG. If it is a list '(R G B)',
5875 with R, G, and B being integers >= 0, take that as the color of the
5876 background. Otherwise, determine the background color of IMG
5877 heuristically. Value is non-zero if successful. */
5879 static int
5880 x_build_heuristic_mask (f, img, how)
5881 struct frame *f;
5882 struct image *img;
5883 Lisp_Object how;
5885 XImagePtr_or_DC ximg;
5886 #ifndef HAVE_NTGUI
5887 XImagePtr mask_img;
5888 #else
5889 HDC frame_dc;
5890 HGDIOBJ prev;
5891 char *mask_img;
5892 int row_width;
5893 #endif /* HAVE_NTGUI */
5894 int x, y, rc, use_img_background;
5895 unsigned long bg = 0;
5897 if (img->mask)
5899 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5900 img->mask = NO_PIXMAP;
5901 img->background_transparent_valid = 0;
5904 #ifndef HAVE_NTGUI
5905 #ifndef HAVE_NS
5906 /* Create an image and pixmap serving as mask. */
5907 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5908 &mask_img, &img->mask);
5909 if (!rc)
5910 return 0;
5911 #endif /* !HAVE_NS */
5913 /* Get the X image of IMG->pixmap. */
5914 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5915 img->width, img->height,
5916 ~0, ZPixmap);
5917 #else
5918 /* Create the bit array serving as mask. */
5919 row_width = (img->width + 7) / 8;
5920 mask_img = xmalloc (row_width * img->height);
5921 bzero (mask_img, row_width * img->height);
5923 /* Create a memory device context for IMG->pixmap. */
5924 frame_dc = get_frame_dc (f);
5925 ximg = CreateCompatibleDC (frame_dc);
5926 release_frame_dc (f, frame_dc);
5927 prev = SelectObject (ximg, img->pixmap);
5928 #endif /* HAVE_NTGUI */
5930 /* Determine the background color of ximg. If HOW is `(R G B)'
5931 take that as color. Otherwise, use the image's background color. */
5932 use_img_background = 1;
5934 if (CONSP (how))
5936 int rgb[3], i;
5938 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5940 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5941 how = XCDR (how);
5944 if (i == 3 && NILP (how))
5946 char color_name[30];
5947 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5948 bg = (
5949 #ifdef HAVE_NTGUI
5950 0x00ffffff & /* Filter out palette info. */
5951 #endif /* HAVE_NTGUI */
5952 x_alloc_image_color (f, img, build_string (color_name), 0));
5953 use_img_background = 0;
5957 if (use_img_background)
5958 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5960 /* Set all bits in mask_img to 1 whose color in ximg is different
5961 from the background color bg. */
5962 #ifndef HAVE_NTGUI
5963 for (y = 0; y < img->height; ++y)
5964 for (x = 0; x < img->width; ++x)
5965 #ifndef HAVE_NS
5966 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5967 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5968 #else
5969 if (XGetPixel (ximg, x, y) == bg)
5970 ns_set_alpha(ximg, x, y, 0);
5971 #endif /* HAVE_NS */
5972 #ifndef HAVE_NS
5973 /* Fill in the background_transparent field while we have the mask handy. */
5974 image_background_transparent (img, f, mask_img);
5976 /* Put mask_img into img->mask. */
5977 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5978 x_destroy_x_image (mask_img);
5979 #endif /* !HAVE_NS */
5980 #else
5981 for (y = 0; y < img->height; ++y)
5982 for (x = 0; x < img->width; ++x)
5984 COLORREF p = GetPixel (ximg, x, y);
5985 if (p != bg)
5986 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5989 /* Create the mask image. */
5990 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5991 mask_img);
5992 /* Fill in the background_transparent field while we have the mask handy. */
5993 SelectObject (ximg, img->mask);
5994 image_background_transparent (img, f, ximg);
5996 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5997 xfree (mask_img);
5998 #endif /* HAVE_NTGUI */
6000 Destroy_Image (ximg, prev);
6002 return 1;
6006 /***********************************************************************
6007 PBM (mono, gray, color)
6008 ***********************************************************************/
6010 static int pbm_image_p P_ ((Lisp_Object object));
6011 static int pbm_load P_ ((struct frame *f, struct image *img));
6012 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
6014 /* The symbol `pbm' identifying images of this type. */
6016 Lisp_Object Qpbm;
6018 /* Indices of image specification fields in gs_format, below. */
6020 enum pbm_keyword_index
6022 PBM_TYPE,
6023 PBM_FILE,
6024 PBM_DATA,
6025 PBM_ASCENT,
6026 PBM_MARGIN,
6027 PBM_RELIEF,
6028 PBM_ALGORITHM,
6029 PBM_HEURISTIC_MASK,
6030 PBM_MASK,
6031 PBM_FOREGROUND,
6032 PBM_BACKGROUND,
6033 PBM_LAST
6036 /* Vector of image_keyword structures describing the format
6037 of valid user-defined image specifications. */
6039 static struct image_keyword pbm_format[PBM_LAST] =
6041 {":type", IMAGE_SYMBOL_VALUE, 1},
6042 {":file", IMAGE_STRING_VALUE, 0},
6043 {":data", IMAGE_STRING_VALUE, 0},
6044 {":ascent", IMAGE_ASCENT_VALUE, 0},
6045 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6046 {":relief", IMAGE_INTEGER_VALUE, 0},
6047 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6048 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6049 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6050 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6051 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6054 /* Structure describing the image type `pbm'. */
6056 static struct image_type pbm_type =
6058 &Qpbm,
6059 pbm_image_p,
6060 pbm_load,
6061 x_clear_image,
6062 NULL
6066 /* Return non-zero if OBJECT is a valid PBM image specification. */
6068 static int
6069 pbm_image_p (object)
6070 Lisp_Object object;
6072 struct image_keyword fmt[PBM_LAST];
6074 bcopy (pbm_format, fmt, sizeof fmt);
6076 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
6077 return 0;
6079 /* Must specify either :data or :file. */
6080 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
6084 /* Scan a decimal number from *S and return it. Advance *S while
6085 reading the number. END is the end of the string. Value is -1 at
6086 end of input. */
6088 static int
6089 pbm_scan_number (s, end)
6090 unsigned char **s, *end;
6092 int c = 0, val = -1;
6094 while (*s < end)
6096 /* Skip white-space. */
6097 while (*s < end && (c = *(*s)++, isspace (c)))
6100 if (c == '#')
6102 /* Skip comment to end of line. */
6103 while (*s < end && (c = *(*s)++, c != '\n'))
6106 else if (isdigit (c))
6108 /* Read decimal number. */
6109 val = c - '0';
6110 while (*s < end && (c = *(*s)++, isdigit (c)))
6111 val = 10 * val + c - '0';
6112 break;
6114 else
6115 break;
6118 return val;
6122 #ifdef HAVE_NTGUI
6123 #if 0 /* Unused. ++kfs */
6125 /* Read FILE into memory. Value is a pointer to a buffer allocated
6126 with xmalloc holding FILE's contents. Value is null if an error
6127 occurred. *SIZE is set to the size of the file. */
6129 static char *
6130 pbm_read_file (file, size)
6131 Lisp_Object file;
6132 int *size;
6134 FILE *fp = NULL;
6135 char *buf = NULL;
6136 struct stat st;
6138 if (stat (SDATA (file), &st) == 0
6139 && (fp = fopen (SDATA (file), "rb")) != NULL
6140 && (buf = (char *) xmalloc (st.st_size),
6141 fread (buf, 1, st.st_size, fp) == st.st_size))
6143 *size = st.st_size;
6144 fclose (fp);
6146 else
6148 if (fp)
6149 fclose (fp);
6150 if (buf)
6152 xfree (buf);
6153 buf = NULL;
6157 return buf;
6159 #endif
6160 #endif /* HAVE_NTGUI */
6162 /* Load PBM image IMG for use on frame F. */
6164 static int
6165 pbm_load (f, img)
6166 struct frame *f;
6167 struct image *img;
6169 int raw_p, x, y;
6170 int width, height, max_color_idx = 0;
6171 XImagePtr ximg;
6172 Lisp_Object file, specified_file;
6173 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
6174 struct gcpro gcpro1;
6175 unsigned char *contents = NULL;
6176 unsigned char *end, *p;
6177 int size;
6179 specified_file = image_spec_value (img->spec, QCfile, NULL);
6180 file = Qnil;
6181 GCPRO1 (file);
6183 if (STRINGP (specified_file))
6185 file = x_find_image_file (specified_file);
6186 if (!STRINGP (file))
6188 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6189 UNGCPRO;
6190 return 0;
6193 contents = slurp_file (SDATA (file), &size);
6194 if (contents == NULL)
6196 image_error ("Error reading `%s'", file, Qnil);
6197 UNGCPRO;
6198 return 0;
6201 p = contents;
6202 end = contents + size;
6204 else
6206 Lisp_Object data;
6207 data = image_spec_value (img->spec, QCdata, NULL);
6208 p = SDATA (data);
6209 end = p + SBYTES (data);
6212 /* Check magic number. */
6213 if (end - p < 2 || *p++ != 'P')
6215 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6216 error:
6217 xfree (contents);
6218 UNGCPRO;
6219 return 0;
6222 switch (*p++)
6224 case '1':
6225 raw_p = 0, type = PBM_MONO;
6226 break;
6228 case '2':
6229 raw_p = 0, type = PBM_GRAY;
6230 break;
6232 case '3':
6233 raw_p = 0, type = PBM_COLOR;
6234 break;
6236 case '4':
6237 raw_p = 1, type = PBM_MONO;
6238 break;
6240 case '5':
6241 raw_p = 1, type = PBM_GRAY;
6242 break;
6244 case '6':
6245 raw_p = 1, type = PBM_COLOR;
6246 break;
6248 default:
6249 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6250 goto error;
6253 /* Read width, height, maximum color-component. Characters
6254 starting with `#' up to the end of a line are ignored. */
6255 width = pbm_scan_number (&p, end);
6256 height = pbm_scan_number (&p, end);
6258 if (type != PBM_MONO)
6260 max_color_idx = pbm_scan_number (&p, end);
6261 if (max_color_idx > 65535 || max_color_idx < 0)
6263 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
6264 goto error;
6268 if (!check_image_size (f, width, height))
6270 image_error ("Invalid image size", Qnil, Qnil);
6271 goto error;
6274 if (!x_create_x_image_and_pixmap (f, width, height, 0,
6275 &ximg, &img->pixmap))
6276 goto error;
6278 /* Initialize the color hash table. */
6279 init_color_table ();
6281 if (type == PBM_MONO)
6283 int c = 0, g;
6284 struct image_keyword fmt[PBM_LAST];
6285 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
6286 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
6288 /* Parse the image specification. */
6289 bcopy (pbm_format, fmt, sizeof fmt);
6290 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
6292 /* Get foreground and background colors, maybe allocate colors. */
6293 if (fmt[PBM_FOREGROUND].count
6294 && STRINGP (fmt[PBM_FOREGROUND].value))
6295 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
6296 if (fmt[PBM_BACKGROUND].count
6297 && STRINGP (fmt[PBM_BACKGROUND].value))
6299 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
6300 img->background = bg;
6301 img->background_valid = 1;
6304 for (y = 0; y < height; ++y)
6305 for (x = 0; x < width; ++x)
6307 if (raw_p)
6309 if ((x & 7) == 0)
6311 if (p >= end)
6313 x_destroy_x_image (ximg);
6314 x_clear_image (f, img);
6315 image_error ("Invalid image size in image `%s'",
6316 img->spec, Qnil);
6317 goto error;
6319 c = *p++;
6321 g = c & 0x80;
6322 c <<= 1;
6324 else
6325 g = pbm_scan_number (&p, end);
6327 XPutPixel (ximg, x, y, g ? fg : bg);
6330 else
6332 int expected_size = height * width;
6333 if (max_color_idx > 255)
6334 expected_size *= 2;
6335 if (type == PBM_COLOR)
6336 expected_size *= 3;
6338 if (raw_p && p + expected_size > end)
6340 x_destroy_x_image (ximg);
6341 x_clear_image (f, img);
6342 image_error ("Invalid image size in image `%s'",
6343 img->spec, Qnil);
6344 goto error;
6347 for (y = 0; y < height; ++y)
6348 for (x = 0; x < width; ++x)
6350 int r, g, b;
6352 if (type == PBM_GRAY && raw_p)
6354 r = g = b = *p++;
6355 if (max_color_idx > 255)
6356 r = g = b = r * 256 + *p++;
6358 else if (type == PBM_GRAY)
6359 r = g = b = pbm_scan_number (&p, end);
6360 else if (raw_p)
6362 r = *p++;
6363 if (max_color_idx > 255)
6364 r = r * 256 + *p++;
6365 g = *p++;
6366 if (max_color_idx > 255)
6367 g = g * 256 + *p++;
6368 b = *p++;
6369 if (max_color_idx > 255)
6370 b = b * 256 + *p++;
6372 else
6374 r = pbm_scan_number (&p, end);
6375 g = pbm_scan_number (&p, end);
6376 b = pbm_scan_number (&p, end);
6379 if (r < 0 || g < 0 || b < 0)
6381 x_destroy_x_image (ximg);
6382 image_error ("Invalid pixel value in image `%s'",
6383 img->spec, Qnil);
6384 goto error;
6387 /* RGB values are now in the range 0..max_color_idx.
6388 Scale this to the range 0..0xffff supported by X. */
6389 r = (double) r * 65535 / max_color_idx;
6390 g = (double) g * 65535 / max_color_idx;
6391 b = (double) b * 65535 / max_color_idx;
6392 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6396 #ifdef COLOR_TABLE_SUPPORT
6397 /* Store in IMG->colors the colors allocated for the image, and
6398 free the color table. */
6399 img->colors = colors_in_color_table (&img->ncolors);
6400 free_color_table ();
6401 #endif /* COLOR_TABLE_SUPPORT */
6403 img->width = width;
6404 img->height = height;
6406 /* Maybe fill in the background field while we have ximg handy. */
6408 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6409 /* Casting avoids a GCC warning. */
6410 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6412 /* Put the image into a pixmap. */
6413 x_put_x_image (f, ximg, img->pixmap, width, height);
6414 x_destroy_x_image (ximg);
6416 /* X and W32 versions did it here, MAC version above. ++kfs
6417 img->width = width;
6418 img->height = height; */
6420 UNGCPRO;
6421 xfree (contents);
6422 return 1;
6426 /***********************************************************************
6428 ***********************************************************************/
6430 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
6432 /* Function prototypes. */
6434 static int png_image_p P_ ((Lisp_Object object));
6435 static int png_load P_ ((struct frame *f, struct image *img));
6437 /* The symbol `png' identifying images of this type. */
6439 Lisp_Object Qpng;
6441 /* Indices of image specification fields in png_format, below. */
6443 enum png_keyword_index
6445 PNG_TYPE,
6446 PNG_DATA,
6447 PNG_FILE,
6448 PNG_ASCENT,
6449 PNG_MARGIN,
6450 PNG_RELIEF,
6451 PNG_ALGORITHM,
6452 PNG_HEURISTIC_MASK,
6453 PNG_MASK,
6454 PNG_BACKGROUND,
6455 PNG_LAST
6458 /* Vector of image_keyword structures describing the format
6459 of valid user-defined image specifications. */
6461 static struct image_keyword png_format[PNG_LAST] =
6463 {":type", IMAGE_SYMBOL_VALUE, 1},
6464 {":data", IMAGE_STRING_VALUE, 0},
6465 {":file", IMAGE_STRING_VALUE, 0},
6466 {":ascent", IMAGE_ASCENT_VALUE, 0},
6467 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6468 {":relief", IMAGE_INTEGER_VALUE, 0},
6469 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6470 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6471 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6472 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6475 /* Structure describing the image type `png'. */
6477 static struct image_type png_type =
6479 &Qpng,
6480 png_image_p,
6481 png_load,
6482 x_clear_image,
6483 NULL
6486 /* Return non-zero if OBJECT is a valid PNG image specification. */
6488 static int
6489 png_image_p (object)
6490 Lisp_Object object;
6492 struct image_keyword fmt[PNG_LAST];
6493 bcopy (png_format, fmt, sizeof fmt);
6495 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
6496 return 0;
6498 /* Must specify either the :data or :file keyword. */
6499 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6502 #endif /* HAVE_PNG || MAC_OS || HAVE_NS */
6505 #ifdef HAVE_PNG
6507 #if defined HAVE_LIBPNG_PNG_H
6508 # include <libpng/png.h>
6509 #else
6510 # include <png.h>
6511 #endif
6513 #ifdef HAVE_NTGUI
6514 /* PNG library details. */
6516 DEF_IMGLIB_FN (png_get_io_ptr);
6517 DEF_IMGLIB_FN (png_check_sig);
6518 DEF_IMGLIB_FN (png_create_read_struct);
6519 DEF_IMGLIB_FN (png_create_info_struct);
6520 DEF_IMGLIB_FN (png_destroy_read_struct);
6521 DEF_IMGLIB_FN (png_set_read_fn);
6522 DEF_IMGLIB_FN (png_set_sig_bytes);
6523 DEF_IMGLIB_FN (png_read_info);
6524 DEF_IMGLIB_FN (png_get_IHDR);
6525 DEF_IMGLIB_FN (png_get_valid);
6526 DEF_IMGLIB_FN (png_set_strip_16);
6527 DEF_IMGLIB_FN (png_set_expand);
6528 DEF_IMGLIB_FN (png_set_gray_to_rgb);
6529 DEF_IMGLIB_FN (png_set_background);
6530 DEF_IMGLIB_FN (png_get_bKGD);
6531 DEF_IMGLIB_FN (png_read_update_info);
6532 DEF_IMGLIB_FN (png_get_channels);
6533 DEF_IMGLIB_FN (png_get_rowbytes);
6534 DEF_IMGLIB_FN (png_read_image);
6535 DEF_IMGLIB_FN (png_read_end);
6536 DEF_IMGLIB_FN (png_error);
6538 static int
6539 init_png_functions (Lisp_Object libraries)
6541 HMODULE library;
6543 /* Try loading libpng under probable names. */
6544 if (!(library = w32_delayed_load (libraries, Qpng)))
6545 return 0;
6547 LOAD_IMGLIB_FN (library, png_get_io_ptr);
6548 LOAD_IMGLIB_FN (library, png_check_sig);
6549 LOAD_IMGLIB_FN (library, png_create_read_struct);
6550 LOAD_IMGLIB_FN (library, png_create_info_struct);
6551 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
6552 LOAD_IMGLIB_FN (library, png_set_read_fn);
6553 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
6554 LOAD_IMGLIB_FN (library, png_read_info);
6555 LOAD_IMGLIB_FN (library, png_get_IHDR);
6556 LOAD_IMGLIB_FN (library, png_get_valid);
6557 LOAD_IMGLIB_FN (library, png_set_strip_16);
6558 LOAD_IMGLIB_FN (library, png_set_expand);
6559 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
6560 LOAD_IMGLIB_FN (library, png_set_background);
6561 LOAD_IMGLIB_FN (library, png_get_bKGD);
6562 LOAD_IMGLIB_FN (library, png_read_update_info);
6563 LOAD_IMGLIB_FN (library, png_get_channels);
6564 LOAD_IMGLIB_FN (library, png_get_rowbytes);
6565 LOAD_IMGLIB_FN (library, png_read_image);
6566 LOAD_IMGLIB_FN (library, png_read_end);
6567 LOAD_IMGLIB_FN (library, png_error);
6568 return 1;
6570 #else
6572 #define fn_png_get_io_ptr png_get_io_ptr
6573 #define fn_png_check_sig png_check_sig
6574 #define fn_png_create_read_struct png_create_read_struct
6575 #define fn_png_create_info_struct png_create_info_struct
6576 #define fn_png_destroy_read_struct png_destroy_read_struct
6577 #define fn_png_set_read_fn png_set_read_fn
6578 #define fn_png_set_sig_bytes png_set_sig_bytes
6579 #define fn_png_read_info png_read_info
6580 #define fn_png_get_IHDR png_get_IHDR
6581 #define fn_png_get_valid png_get_valid
6582 #define fn_png_set_strip_16 png_set_strip_16
6583 #define fn_png_set_expand png_set_expand
6584 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6585 #define fn_png_set_background png_set_background
6586 #define fn_png_get_bKGD png_get_bKGD
6587 #define fn_png_read_update_info png_read_update_info
6588 #define fn_png_get_channels png_get_channels
6589 #define fn_png_get_rowbytes png_get_rowbytes
6590 #define fn_png_read_image png_read_image
6591 #define fn_png_read_end png_read_end
6592 #define fn_png_error png_error
6594 #endif /* HAVE_NTGUI */
6596 /* Error and warning handlers installed when the PNG library
6597 is initialized. */
6599 static void
6600 my_png_error (png_ptr, msg)
6601 png_struct *png_ptr;
6602 char *msg;
6604 xassert (png_ptr != NULL);
6605 image_error ("PNG error: %s", build_string (msg), Qnil);
6606 longjmp (png_ptr->jmpbuf, 1);
6610 static void
6611 my_png_warning (png_ptr, msg)
6612 png_struct *png_ptr;
6613 char *msg;
6615 xassert (png_ptr != NULL);
6616 image_error ("PNG warning: %s", build_string (msg), Qnil);
6619 /* Memory source for PNG decoding. */
6621 struct png_memory_storage
6623 unsigned char *bytes; /* The data */
6624 size_t len; /* How big is it? */
6625 int index; /* Where are we? */
6629 /* Function set as reader function when reading PNG image from memory.
6630 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6631 bytes from the input to DATA. */
6633 static void
6634 png_read_from_memory (png_ptr, data, length)
6635 png_structp png_ptr;
6636 png_bytep data;
6637 png_size_t length;
6639 struct png_memory_storage *tbr
6640 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
6642 if (length > tbr->len - tbr->index)
6643 fn_png_error (png_ptr, "Read error");
6645 bcopy (tbr->bytes + tbr->index, data, length);
6646 tbr->index = tbr->index + length;
6650 /* Function set as reader function when reading PNG image from a file.
6651 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6652 bytes from the input to DATA. */
6654 static void
6655 png_read_from_file (png_ptr, data, length)
6656 png_structp png_ptr;
6657 png_bytep data;
6658 png_size_t length;
6660 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
6662 if (fread (data, 1, length, fp) < length)
6663 fn_png_error (png_ptr, "Read error");
6667 /* Load PNG image IMG for use on frame F. Value is non-zero if
6668 successful. */
6670 static int
6671 png_load (f, img)
6672 struct frame *f;
6673 struct image *img;
6675 Lisp_Object file, specified_file;
6676 Lisp_Object specified_data;
6677 int x, y, i;
6678 XImagePtr ximg, mask_img = NULL;
6679 struct gcpro gcpro1;
6680 png_struct *png_ptr = NULL;
6681 png_info *info_ptr = NULL, *end_info = NULL;
6682 FILE *volatile fp = NULL;
6683 png_byte sig[8];
6684 png_byte * volatile pixels = NULL;
6685 png_byte ** volatile rows = NULL;
6686 png_uint_32 width, height;
6687 int bit_depth, color_type, interlace_type;
6688 png_byte channels;
6689 png_uint_32 row_bytes;
6690 int transparent_p;
6691 struct png_memory_storage tbr; /* Data to be read */
6693 /* Find out what file to load. */
6694 specified_file = image_spec_value (img->spec, QCfile, NULL);
6695 specified_data = image_spec_value (img->spec, QCdata, NULL);
6696 file = Qnil;
6697 GCPRO1 (file);
6699 if (NILP (specified_data))
6701 file = x_find_image_file (specified_file);
6702 if (!STRINGP (file))
6704 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6705 UNGCPRO;
6706 return 0;
6709 /* Open the image file. */
6710 fp = fopen (SDATA (file), "rb");
6711 if (!fp)
6713 image_error ("Cannot open image file `%s'", file, Qnil);
6714 UNGCPRO;
6715 return 0;
6718 /* Check PNG signature. */
6719 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6720 || !fn_png_check_sig (sig, sizeof sig))
6722 image_error ("Not a PNG file: `%s'", file, Qnil);
6723 UNGCPRO;
6724 fclose (fp);
6725 return 0;
6728 else
6730 /* Read from memory. */
6731 tbr.bytes = SDATA (specified_data);
6732 tbr.len = SBYTES (specified_data);
6733 tbr.index = 0;
6735 /* Check PNG signature. */
6736 if (tbr.len < sizeof sig
6737 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6739 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6740 UNGCPRO;
6741 return 0;
6744 /* Need to skip past the signature. */
6745 tbr.bytes += sizeof (sig);
6748 /* Initialize read and info structs for PNG lib. Casting return
6749 value avoids a GCC warning on W32. */
6750 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6751 NULL, my_png_error,
6752 my_png_warning);
6753 if (!png_ptr)
6755 if (fp) fclose (fp);
6756 UNGCPRO;
6757 return 0;
6760 /* Casting return value avoids a GCC warning on W32. */
6761 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6762 if (!info_ptr)
6764 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6765 if (fp) fclose (fp);
6766 UNGCPRO;
6767 return 0;
6770 /* Casting return value avoids a GCC warning on W32. */
6771 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6772 if (!end_info)
6774 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6775 if (fp) fclose (fp);
6776 UNGCPRO;
6777 return 0;
6780 /* Set error jump-back. We come back here when the PNG library
6781 detects an error. */
6782 if (setjmp (png_ptr->jmpbuf))
6784 error:
6785 if (png_ptr)
6786 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6787 xfree (pixels);
6788 xfree (rows);
6789 if (fp) fclose (fp);
6790 UNGCPRO;
6791 return 0;
6794 /* Read image info. */
6795 if (!NILP (specified_data))
6796 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6797 else
6798 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6800 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6801 fn_png_read_info (png_ptr, info_ptr);
6802 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6803 &interlace_type, NULL, NULL);
6805 if (!check_image_size (f, width, height))
6806 goto error;
6808 /* If image contains simply transparency data, we prefer to
6809 construct a clipping mask. */
6810 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6811 transparent_p = 1;
6812 else
6813 transparent_p = 0;
6815 /* This function is easier to write if we only have to handle
6816 one data format: RGB or RGBA with 8 bits per channel. Let's
6817 transform other formats into that format. */
6819 /* Strip more than 8 bits per channel. */
6820 if (bit_depth == 16)
6821 fn_png_set_strip_16 (png_ptr);
6823 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6824 if available. */
6825 fn_png_set_expand (png_ptr);
6827 /* Convert grayscale images to RGB. */
6828 if (color_type == PNG_COLOR_TYPE_GRAY
6829 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6830 fn_png_set_gray_to_rgb (png_ptr);
6832 /* Handle alpha channel by combining the image with a background
6833 color. Do this only if a real alpha channel is supplied. For
6834 simple transparency, we prefer a clipping mask. */
6835 if (!transparent_p)
6837 /* png_color_16 *image_bg; */
6838 Lisp_Object specified_bg
6839 = image_spec_value (img->spec, QCbackground, NULL);
6840 int shift = (bit_depth == 16) ? 0 : 8;
6842 if (STRINGP (specified_bg))
6843 /* The user specified `:background', use that. */
6845 /* W32 version incorrectly used COLORREF here!! ++kfs */
6846 XColor color;
6847 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6849 png_color_16 user_bg;
6851 bzero (&user_bg, sizeof user_bg);
6852 user_bg.red = color.red >> shift;
6853 user_bg.green = color.green >> shift;
6854 user_bg.blue = color.blue >> shift;
6856 fn_png_set_background (png_ptr, &user_bg,
6857 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6860 else
6862 /* We use the current frame background, ignoring any default
6863 background color set by the image. */
6864 #ifdef HAVE_X_WINDOWS
6865 XColor color;
6866 png_color_16 frame_background;
6868 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6869 x_query_color (f, &color);
6871 bzero (&frame_background, sizeof frame_background);
6872 frame_background.red = color.red >> shift;
6873 frame_background.green = color.green >> shift;
6874 frame_background.blue = color.blue >> shift;
6875 #endif /* HAVE_X_WINDOWS */
6877 #ifdef HAVE_NTGUI
6878 COLORREF color;
6879 png_color_16 frame_background;
6880 color = FRAME_BACKGROUND_PIXEL (f);
6881 #if 0 /* W32 TODO : Colormap support. */
6882 x_query_color (f, &color);
6883 #endif
6884 bzero (&frame_background, sizeof frame_background);
6885 frame_background.red = GetRValue (color);
6886 frame_background.green = GetGValue (color);
6887 frame_background.blue = GetBValue (color);
6888 #endif /* HAVE_NTGUI */
6890 #ifdef MAC_OS
6891 unsigned long color;
6892 png_color_16 frame_background;
6893 color = FRAME_BACKGROUND_PIXEL (f);
6894 #if 0 /* MAC/W32 TODO : Colormap support. */
6895 x_query_color (f, &color);
6896 #endif
6897 bzero (&frame_background, sizeof frame_background);
6898 frame_background.red = RED_FROM_ULONG (color);
6899 frame_background.green = GREEN_FROM_ULONG (color);
6900 frame_background.blue = BLUE_FROM_ULONG (color);
6901 #endif /* MAC_OS */
6903 fn_png_set_background (png_ptr, &frame_background,
6904 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6908 /* Update info structure. */
6909 fn_png_read_update_info (png_ptr, info_ptr);
6911 /* Get number of channels. Valid values are 1 for grayscale images
6912 and images with a palette, 2 for grayscale images with transparency
6913 information (alpha channel), 3 for RGB images, and 4 for RGB
6914 images with alpha channel, i.e. RGBA. If conversions above were
6915 sufficient we should only have 3 or 4 channels here. */
6916 channels = fn_png_get_channels (png_ptr, info_ptr);
6917 xassert (channels == 3 || channels == 4);
6919 /* Number of bytes needed for one row of the image. */
6920 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6922 /* Allocate memory for the image. */
6923 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6924 rows = (png_byte **) xmalloc (height * sizeof *rows);
6925 for (i = 0; i < height; ++i)
6926 rows[i] = pixels + i * row_bytes;
6928 /* Read the entire image. */
6929 fn_png_read_image (png_ptr, rows);
6930 fn_png_read_end (png_ptr, info_ptr);
6931 if (fp)
6933 fclose (fp);
6934 fp = NULL;
6937 /* Create the X image and pixmap. */
6938 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6939 &img->pixmap))
6940 goto error;
6942 /* Create an image and pixmap serving as mask if the PNG image
6943 contains an alpha channel. */
6944 if (channels == 4
6945 && !transparent_p
6946 && !x_create_x_image_and_pixmap (f, width, height, 1,
6947 &mask_img, &img->mask))
6949 x_destroy_x_image (ximg);
6950 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6951 img->pixmap = NO_PIXMAP;
6952 goto error;
6955 /* Fill the X image and mask from PNG data. */
6956 init_color_table ();
6958 for (y = 0; y < height; ++y)
6960 png_byte *p = rows[y];
6962 for (x = 0; x < width; ++x)
6964 unsigned r, g, b;
6966 r = *p++ << 8;
6967 g = *p++ << 8;
6968 b = *p++ << 8;
6969 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6970 /* An alpha channel, aka mask channel, associates variable
6971 transparency with an image. Where other image formats
6972 support binary transparency---fully transparent or fully
6973 opaque---PNG allows up to 254 levels of partial transparency.
6974 The PNG library implements partial transparency by combining
6975 the image with a specified background color.
6977 I'm not sure how to handle this here nicely: because the
6978 background on which the image is displayed may change, for
6979 real alpha channel support, it would be necessary to create
6980 a new image for each possible background.
6982 What I'm doing now is that a mask is created if we have
6983 boolean transparency information. Otherwise I'm using
6984 the frame's background color to combine the image with. */
6986 if (channels == 4)
6988 if (mask_img)
6989 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6990 ++p;
6995 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6996 /* Set IMG's background color from the PNG image, unless the user
6997 overrode it. */
6999 png_color_16 *bg;
7000 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
7002 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
7003 img->background_valid = 1;
7007 #ifdef COLOR_TABLE_SUPPORT
7008 /* Remember colors allocated for this image. */
7009 img->colors = colors_in_color_table (&img->ncolors);
7010 free_color_table ();
7011 #endif /* COLOR_TABLE_SUPPORT */
7013 /* Clean up. */
7014 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
7015 xfree (rows);
7016 xfree (pixels);
7018 img->width = width;
7019 img->height = height;
7021 /* Maybe fill in the background field while we have ximg handy.
7022 Casting avoids a GCC warning. */
7023 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7025 /* Put the image into the pixmap, then free the X image and its buffer. */
7026 x_put_x_image (f, ximg, img->pixmap, width, height);
7027 x_destroy_x_image (ximg);
7029 /* Same for the mask. */
7030 if (mask_img)
7032 /* Fill in the background_transparent field while we have the
7033 mask handy. Casting avoids a GCC warning. */
7034 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
7036 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
7037 x_destroy_x_image (mask_img);
7040 UNGCPRO;
7041 return 1;
7044 #else /* HAVE_PNG */
7046 #ifdef MAC_OS
7047 static int
7048 png_load (f, img)
7049 struct frame *f;
7050 struct image *img;
7052 #if USE_MAC_IMAGE_IO
7053 return image_load_image_io (f, img, kUTTypePNG);
7054 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
7055 return image_load_quartz2d (f, img, 1);
7056 #else
7057 return image_load_quicktime (f, img, kQTFileTypePNG);
7058 #endif
7060 #endif /* MAC_OS */
7062 #ifdef HAVE_NS
7063 static int
7064 png_load (struct frame *f, struct image *img)
7066 return ns_load_image(f, img,
7067 image_spec_value (img->spec, QCfile, NULL),
7068 image_spec_value (img->spec, QCdata, NULL));
7070 #endif /* HAVE_NS */
7073 #endif /* !HAVE_PNG */
7077 /***********************************************************************
7078 JPEG
7079 ***********************************************************************/
7081 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
7083 static int jpeg_image_p P_ ((Lisp_Object object));
7084 static int jpeg_load P_ ((struct frame *f, struct image *img));
7086 /* The symbol `jpeg' identifying images of this type. */
7088 Lisp_Object Qjpeg;
7090 /* Indices of image specification fields in gs_format, below. */
7092 enum jpeg_keyword_index
7094 JPEG_TYPE,
7095 JPEG_DATA,
7096 JPEG_FILE,
7097 JPEG_ASCENT,
7098 JPEG_MARGIN,
7099 JPEG_RELIEF,
7100 JPEG_ALGORITHM,
7101 JPEG_HEURISTIC_MASK,
7102 JPEG_MASK,
7103 JPEG_BACKGROUND,
7104 JPEG_LAST
7107 /* Vector of image_keyword structures describing the format
7108 of valid user-defined image specifications. */
7110 static struct image_keyword jpeg_format[JPEG_LAST] =
7112 {":type", IMAGE_SYMBOL_VALUE, 1},
7113 {":data", IMAGE_STRING_VALUE, 0},
7114 {":file", IMAGE_STRING_VALUE, 0},
7115 {":ascent", IMAGE_ASCENT_VALUE, 0},
7116 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7117 {":relief", IMAGE_INTEGER_VALUE, 0},
7118 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7119 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7120 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7121 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7124 /* Structure describing the image type `jpeg'. */
7126 static struct image_type jpeg_type =
7128 &Qjpeg,
7129 jpeg_image_p,
7130 jpeg_load,
7131 x_clear_image,
7132 NULL
7135 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7137 static int
7138 jpeg_image_p (object)
7139 Lisp_Object object;
7141 struct image_keyword fmt[JPEG_LAST];
7143 bcopy (jpeg_format, fmt, sizeof fmt);
7145 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
7146 return 0;
7148 /* Must specify either the :data or :file keyword. */
7149 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
7152 #endif /* HAVE_JPEG || MAC_OS || HAVE_NS */
7154 #ifdef HAVE_JPEG
7156 /* Work around a warning about HAVE_STDLIB_H being redefined in
7157 jconfig.h. */
7158 #ifdef HAVE_STDLIB_H
7159 #define HAVE_STDLIB_H_1
7160 #undef HAVE_STDLIB_H
7161 #endif /* HAVE_STLIB_H */
7163 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
7164 /* In older releases of the jpeg library, jpeglib.h will define boolean
7165 differently depending on __WIN32__, so make sure it is defined. */
7166 #define __WIN32__ 1
7167 #endif
7169 #include <jpeglib.h>
7170 #include <jerror.h>
7171 #include <setjmp.h>
7173 #ifdef HAVE_STLIB_H_1
7174 #define HAVE_STDLIB_H 1
7175 #endif
7177 #ifdef HAVE_NTGUI
7179 /* JPEG library details. */
7180 DEF_IMGLIB_FN (jpeg_CreateDecompress);
7181 DEF_IMGLIB_FN (jpeg_start_decompress);
7182 DEF_IMGLIB_FN (jpeg_finish_decompress);
7183 DEF_IMGLIB_FN (jpeg_destroy_decompress);
7184 DEF_IMGLIB_FN (jpeg_read_header);
7185 DEF_IMGLIB_FN (jpeg_read_scanlines);
7186 DEF_IMGLIB_FN (jpeg_std_error);
7187 DEF_IMGLIB_FN (jpeg_resync_to_restart);
7189 static int
7190 init_jpeg_functions (Lisp_Object libraries)
7192 HMODULE library;
7194 if (!(library = w32_delayed_load (libraries, Qjpeg)))
7195 return 0;
7197 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
7198 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
7199 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
7200 LOAD_IMGLIB_FN (library, jpeg_read_header);
7201 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
7202 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
7203 LOAD_IMGLIB_FN (library, jpeg_std_error);
7204 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
7205 return 1;
7208 /* Wrapper since we can't directly assign the function pointer
7209 to another function pointer that was declared more completely easily. */
7210 static boolean
7211 jpeg_resync_to_restart_wrapper (cinfo, desired)
7212 j_decompress_ptr cinfo;
7213 int desired;
7215 return fn_jpeg_resync_to_restart (cinfo, desired);
7218 #else
7220 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7221 #define fn_jpeg_start_decompress jpeg_start_decompress
7222 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7223 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7224 #define fn_jpeg_read_header jpeg_read_header
7225 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7226 #define fn_jpeg_std_error jpeg_std_error
7227 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7229 #endif /* HAVE_NTGUI */
7231 struct my_jpeg_error_mgr
7233 struct jpeg_error_mgr pub;
7234 jmp_buf setjmp_buffer;
7238 static void
7239 my_error_exit (cinfo)
7240 j_common_ptr cinfo;
7242 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7243 longjmp (mgr->setjmp_buffer, 1);
7247 /* Init source method for JPEG data source manager. Called by
7248 jpeg_read_header() before any data is actually read. See
7249 libjpeg.doc from the JPEG lib distribution. */
7251 static void
7252 our_common_init_source (cinfo)
7253 j_decompress_ptr cinfo;
7258 /* Method to terminate data source. Called by
7259 jpeg_finish_decompress() after all data has been processed. */
7261 static void
7262 our_common_term_source (cinfo)
7263 j_decompress_ptr cinfo;
7268 /* Fill input buffer method for JPEG data source manager. Called
7269 whenever more data is needed. We read the whole image in one step,
7270 so this only adds a fake end of input marker at the end. */
7272 static JOCTET our_memory_buffer[2];
7274 static boolean
7275 our_memory_fill_input_buffer (cinfo)
7276 j_decompress_ptr cinfo;
7278 /* Insert a fake EOI marker. */
7279 struct jpeg_source_mgr *src = cinfo->src;
7281 our_memory_buffer[0] = (JOCTET) 0xFF;
7282 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
7284 src->next_input_byte = our_memory_buffer;
7285 src->bytes_in_buffer = 2;
7286 return 1;
7290 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7291 is the JPEG data source manager. */
7293 static void
7294 our_memory_skip_input_data (cinfo, num_bytes)
7295 j_decompress_ptr cinfo;
7296 long num_bytes;
7298 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7300 if (src)
7302 if (num_bytes > src->bytes_in_buffer)
7303 ERREXIT (cinfo, JERR_INPUT_EOF);
7305 src->bytes_in_buffer -= num_bytes;
7306 src->next_input_byte += num_bytes;
7311 /* Set up the JPEG lib for reading an image from DATA which contains
7312 LEN bytes. CINFO is the decompression info structure created for
7313 reading the image. */
7315 static void
7316 jpeg_memory_src (cinfo, data, len)
7317 j_decompress_ptr cinfo;
7318 JOCTET *data;
7319 unsigned int len;
7321 struct jpeg_source_mgr *src;
7323 if (cinfo->src == NULL)
7325 /* First time for this JPEG object? */
7326 cinfo->src = (struct jpeg_source_mgr *)
7327 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7328 sizeof (struct jpeg_source_mgr));
7329 src = (struct jpeg_source_mgr *) cinfo->src;
7330 src->next_input_byte = data;
7333 src = (struct jpeg_source_mgr *) cinfo->src;
7334 src->init_source = our_common_init_source;
7335 src->fill_input_buffer = our_memory_fill_input_buffer;
7336 src->skip_input_data = our_memory_skip_input_data;
7337 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7338 src->term_source = our_common_term_source;
7339 src->bytes_in_buffer = len;
7340 src->next_input_byte = data;
7344 struct jpeg_stdio_mgr
7346 struct jpeg_source_mgr mgr;
7347 boolean finished;
7348 FILE *file;
7349 JOCTET *buffer;
7353 /* Size of buffer to read JPEG from file.
7354 Not too big, as we want to use alloc_small. */
7355 #define JPEG_STDIO_BUFFER_SIZE 8192
7358 /* Fill input buffer method for JPEG data source manager. Called
7359 whenever more data is needed. The data is read from a FILE *. */
7361 static boolean
7362 our_stdio_fill_input_buffer (cinfo)
7363 j_decompress_ptr cinfo;
7365 struct jpeg_stdio_mgr *src;
7367 src = (struct jpeg_stdio_mgr *) cinfo->src;
7368 if (!src->finished)
7370 size_t bytes;
7372 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
7373 if (bytes > 0)
7374 src->mgr.bytes_in_buffer = bytes;
7375 else
7377 WARNMS (cinfo, JWRN_JPEG_EOF);
7378 src->finished = 1;
7379 src->buffer[0] = (JOCTET) 0xFF;
7380 src->buffer[1] = (JOCTET) JPEG_EOI;
7381 src->mgr.bytes_in_buffer = 2;
7383 src->mgr.next_input_byte = src->buffer;
7386 return 1;
7390 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7391 is the JPEG data source manager. */
7393 static void
7394 our_stdio_skip_input_data (cinfo, num_bytes)
7395 j_decompress_ptr cinfo;
7396 long num_bytes;
7398 struct jpeg_stdio_mgr *src;
7399 src = (struct jpeg_stdio_mgr *) cinfo->src;
7401 while (num_bytes > 0 && !src->finished)
7403 if (num_bytes <= src->mgr.bytes_in_buffer)
7405 src->mgr.bytes_in_buffer -= num_bytes;
7406 src->mgr.next_input_byte += num_bytes;
7407 break;
7409 else
7411 num_bytes -= src->mgr.bytes_in_buffer;
7412 src->mgr.bytes_in_buffer = 0;
7413 src->mgr.next_input_byte = NULL;
7415 our_stdio_fill_input_buffer (cinfo);
7421 /* Set up the JPEG lib for reading an image from a FILE *.
7422 CINFO is the decompression info structure created for
7423 reading the image. */
7425 static void
7426 jpeg_file_src (cinfo, fp)
7427 j_decompress_ptr cinfo;
7428 FILE *fp;
7430 struct jpeg_stdio_mgr *src;
7432 if (cinfo->src != NULL)
7433 src = (struct jpeg_stdio_mgr *) cinfo->src;
7434 else
7436 /* First time for this JPEG object? */
7437 cinfo->src = (struct jpeg_source_mgr *)
7438 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7439 sizeof (struct jpeg_stdio_mgr));
7440 src = (struct jpeg_stdio_mgr *) cinfo->src;
7441 src->buffer = (JOCTET *)
7442 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7443 JPEG_STDIO_BUFFER_SIZE);
7446 src->file = fp;
7447 src->finished = 0;
7448 src->mgr.init_source = our_common_init_source;
7449 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
7450 src->mgr.skip_input_data = our_stdio_skip_input_data;
7451 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7452 src->mgr.term_source = our_common_term_source;
7453 src->mgr.bytes_in_buffer = 0;
7454 src->mgr.next_input_byte = NULL;
7458 /* Load image IMG for use on frame F. Patterned after example.c
7459 from the JPEG lib. */
7461 static int
7462 jpeg_load (f, img)
7463 struct frame *f;
7464 struct image *img;
7466 struct jpeg_decompress_struct cinfo;
7467 struct my_jpeg_error_mgr mgr;
7468 Lisp_Object file, specified_file;
7469 Lisp_Object specified_data;
7470 FILE * volatile fp = NULL;
7471 JSAMPARRAY buffer;
7472 int row_stride, x, y;
7473 XImagePtr ximg = NULL;
7474 int rc;
7475 unsigned long *colors;
7476 int width, height;
7477 struct gcpro gcpro1;
7479 /* Open the JPEG file. */
7480 specified_file = image_spec_value (img->spec, QCfile, NULL);
7481 specified_data = image_spec_value (img->spec, QCdata, NULL);
7482 file = Qnil;
7483 GCPRO1 (file);
7485 if (NILP (specified_data))
7487 file = x_find_image_file (specified_file);
7488 if (!STRINGP (file))
7490 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7491 UNGCPRO;
7492 return 0;
7495 fp = fopen (SDATA (file), "rb");
7496 if (fp == NULL)
7498 image_error ("Cannot open `%s'", file, Qnil);
7499 UNGCPRO;
7500 return 0;
7504 /* Customize libjpeg's error handling to call my_error_exit when an
7505 error is detected. This function will perform a longjmp.
7506 Casting return value avoids a GCC warning on W32. */
7507 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
7508 mgr.pub.error_exit = my_error_exit;
7510 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7512 if (rc == 1)
7514 /* Called from my_error_exit. Display a JPEG error. */
7515 char buffer[JMSG_LENGTH_MAX];
7516 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7517 image_error ("Error reading JPEG image `%s': %s", img->spec,
7518 build_string (buffer));
7521 /* Close the input file and destroy the JPEG object. */
7522 if (fp)
7523 fclose ((FILE *) fp);
7524 fn_jpeg_destroy_decompress (&cinfo);
7526 /* If we already have an XImage, free that. */
7527 x_destroy_x_image (ximg);
7529 /* Free pixmap and colors. */
7530 x_clear_image (f, img);
7532 UNGCPRO;
7533 return 0;
7536 /* Create the JPEG decompression object. Let it read from fp.
7537 Read the JPEG image header. */
7538 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
7540 if (NILP (specified_data))
7541 jpeg_file_src (&cinfo, (FILE *) fp);
7542 else
7543 jpeg_memory_src (&cinfo, SDATA (specified_data),
7544 SBYTES (specified_data));
7546 fn_jpeg_read_header (&cinfo, 1);
7548 /* Customize decompression so that color quantization will be used.
7549 Start decompression. */
7550 cinfo.quantize_colors = 1;
7551 fn_jpeg_start_decompress (&cinfo);
7552 width = img->width = cinfo.output_width;
7553 height = img->height = cinfo.output_height;
7555 if (!check_image_size (f, width, height))
7557 image_error ("Invalid image size", Qnil, Qnil);
7558 longjmp (mgr.setjmp_buffer, 2);
7561 /* Create X image and pixmap. */
7562 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7563 longjmp (mgr.setjmp_buffer, 2);
7565 /* Allocate colors. When color quantization is used,
7566 cinfo.actual_number_of_colors has been set with the number of
7567 colors generated, and cinfo.colormap is a two-dimensional array
7568 of color indices in the range 0..cinfo.actual_number_of_colors.
7569 No more than 255 colors will be generated. */
7571 int i, ir, ig, ib;
7573 if (cinfo.out_color_components > 2)
7574 ir = 0, ig = 1, ib = 2;
7575 else if (cinfo.out_color_components > 1)
7576 ir = 0, ig = 1, ib = 0;
7577 else
7578 ir = 0, ig = 0, ib = 0;
7580 /* Use the color table mechanism because it handles colors that
7581 cannot be allocated nicely. Such colors will be replaced with
7582 a default color, and we don't have to care about which colors
7583 can be freed safely, and which can't. */
7584 init_color_table ();
7585 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
7586 * sizeof *colors);
7588 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
7590 /* Multiply RGB values with 255 because X expects RGB values
7591 in the range 0..0xffff. */
7592 int r = cinfo.colormap[ir][i] << 8;
7593 int g = cinfo.colormap[ig][i] << 8;
7594 int b = cinfo.colormap[ib][i] << 8;
7595 colors[i] = lookup_rgb_color (f, r, g, b);
7598 #ifdef COLOR_TABLE_SUPPORT
7599 /* Remember those colors actually allocated. */
7600 img->colors = colors_in_color_table (&img->ncolors);
7601 free_color_table ();
7602 #endif /* COLOR_TABLE_SUPPORT */
7605 /* Read pixels. */
7606 row_stride = width * cinfo.output_components;
7607 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
7608 row_stride, 1);
7609 for (y = 0; y < height; ++y)
7611 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
7612 for (x = 0; x < cinfo.output_width; ++x)
7613 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
7616 /* Clean up. */
7617 fn_jpeg_finish_decompress (&cinfo);
7618 fn_jpeg_destroy_decompress (&cinfo);
7619 if (fp)
7620 fclose ((FILE *) fp);
7622 /* Maybe fill in the background field while we have ximg handy. */
7623 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7624 /* Casting avoids a GCC warning. */
7625 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7627 /* Put the image into the pixmap. */
7628 x_put_x_image (f, ximg, img->pixmap, width, height);
7629 x_destroy_x_image (ximg);
7630 UNGCPRO;
7631 return 1;
7634 #else /* HAVE_JPEG */
7636 #ifdef MAC_OS
7637 static int
7638 jpeg_load (f, img)
7639 struct frame *f;
7640 struct image *img;
7642 #if USE_MAC_IMAGE_IO
7643 return image_load_image_io (f, img, kUTTypeJPEG);
7644 #elif defined (MAC_OSX)
7645 return image_load_quartz2d (f, img, 0);
7646 #else
7647 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7648 #endif
7650 #endif /* MAC_OS */
7652 #ifdef HAVE_NS
7653 static int
7654 jpeg_load (struct frame *f, struct image *img)
7656 return ns_load_image(f, img,
7657 image_spec_value (img->spec, QCfile, NULL),
7658 image_spec_value (img->spec, QCdata, NULL));
7660 #endif /* HAVE_NS */
7662 #endif /* !HAVE_JPEG */
7666 /***********************************************************************
7667 TIFF
7668 ***********************************************************************/
7670 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
7672 static int tiff_image_p P_ ((Lisp_Object object));
7673 static int tiff_load P_ ((struct frame *f, struct image *img));
7675 /* The symbol `tiff' identifying images of this type. */
7677 Lisp_Object Qtiff;
7679 /* Indices of image specification fields in tiff_format, below. */
7681 enum tiff_keyword_index
7683 TIFF_TYPE,
7684 TIFF_DATA,
7685 TIFF_FILE,
7686 TIFF_ASCENT,
7687 TIFF_MARGIN,
7688 TIFF_RELIEF,
7689 TIFF_ALGORITHM,
7690 TIFF_HEURISTIC_MASK,
7691 TIFF_MASK,
7692 TIFF_BACKGROUND,
7693 TIFF_LAST
7696 /* Vector of image_keyword structures describing the format
7697 of valid user-defined image specifications. */
7699 static struct image_keyword tiff_format[TIFF_LAST] =
7701 {":type", IMAGE_SYMBOL_VALUE, 1},
7702 {":data", IMAGE_STRING_VALUE, 0},
7703 {":file", IMAGE_STRING_VALUE, 0},
7704 {":ascent", IMAGE_ASCENT_VALUE, 0},
7705 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7706 {":relief", IMAGE_INTEGER_VALUE, 0},
7707 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7708 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7709 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7710 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7713 /* Structure describing the image type `tiff'. */
7715 static struct image_type tiff_type =
7717 &Qtiff,
7718 tiff_image_p,
7719 tiff_load,
7720 x_clear_image,
7721 NULL
7724 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7726 static int
7727 tiff_image_p (object)
7728 Lisp_Object object;
7730 struct image_keyword fmt[TIFF_LAST];
7731 bcopy (tiff_format, fmt, sizeof fmt);
7733 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
7734 return 0;
7736 /* Must specify either the :data or :file keyword. */
7737 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7740 #endif /* HAVE_TIFF || MAC_OS || HAVE_NS */
7742 #ifdef HAVE_TIFF
7744 #include <tiffio.h>
7746 #ifdef HAVE_NTGUI
7748 /* TIFF library details. */
7749 DEF_IMGLIB_FN (TIFFSetErrorHandler);
7750 DEF_IMGLIB_FN (TIFFSetWarningHandler);
7751 DEF_IMGLIB_FN (TIFFOpen);
7752 DEF_IMGLIB_FN (TIFFClientOpen);
7753 DEF_IMGLIB_FN (TIFFGetField);
7754 DEF_IMGLIB_FN (TIFFReadRGBAImage);
7755 DEF_IMGLIB_FN (TIFFClose);
7757 static int
7758 init_tiff_functions (Lisp_Object libraries)
7760 HMODULE library;
7762 if (!(library = w32_delayed_load (libraries, Qtiff)))
7763 return 0;
7765 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
7766 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
7767 LOAD_IMGLIB_FN (library, TIFFOpen);
7768 LOAD_IMGLIB_FN (library, TIFFClientOpen);
7769 LOAD_IMGLIB_FN (library, TIFFGetField);
7770 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
7771 LOAD_IMGLIB_FN (library, TIFFClose);
7772 return 1;
7775 #else
7777 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7778 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7779 #define fn_TIFFOpen TIFFOpen
7780 #define fn_TIFFClientOpen TIFFClientOpen
7781 #define fn_TIFFGetField TIFFGetField
7782 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7783 #define fn_TIFFClose TIFFClose
7785 #endif /* HAVE_NTGUI */
7788 /* Reading from a memory buffer for TIFF images Based on the PNG
7789 memory source, but we have to provide a lot of extra functions.
7790 Blah.
7792 We really only need to implement read and seek, but I am not
7793 convinced that the TIFF library is smart enough not to destroy
7794 itself if we only hand it the function pointers we need to
7795 override. */
7797 typedef struct
7799 unsigned char *bytes;
7800 size_t len;
7801 int index;
7803 tiff_memory_source;
7805 static size_t
7806 tiff_read_from_memory (data, buf, size)
7807 thandle_t data;
7808 tdata_t buf;
7809 tsize_t size;
7811 tiff_memory_source *src = (tiff_memory_source *) data;
7813 if (size > src->len - src->index)
7814 return (size_t) -1;
7815 bcopy (src->bytes + src->index, buf, size);
7816 src->index += size;
7817 return size;
7820 static size_t
7821 tiff_write_from_memory (data, buf, size)
7822 thandle_t data;
7823 tdata_t buf;
7824 tsize_t size;
7826 return (size_t) -1;
7829 static toff_t
7830 tiff_seek_in_memory (data, off, whence)
7831 thandle_t data;
7832 toff_t off;
7833 int whence;
7835 tiff_memory_source *src = (tiff_memory_source *) data;
7836 int idx;
7838 switch (whence)
7840 case SEEK_SET: /* Go from beginning of source. */
7841 idx = off;
7842 break;
7844 case SEEK_END: /* Go from end of source. */
7845 idx = src->len + off;
7846 break;
7848 case SEEK_CUR: /* Go from current position. */
7849 idx = src->index + off;
7850 break;
7852 default: /* Invalid `whence'. */
7853 return -1;
7856 if (idx > src->len || idx < 0)
7857 return -1;
7859 src->index = idx;
7860 return src->index;
7863 static int
7864 tiff_close_memory (data)
7865 thandle_t data;
7867 /* NOOP */
7868 return 0;
7871 static int
7872 tiff_mmap_memory (data, pbase, psize)
7873 thandle_t data;
7874 tdata_t *pbase;
7875 toff_t *psize;
7877 /* It is already _IN_ memory. */
7878 return 0;
7881 static void
7882 tiff_unmap_memory (data, base, size)
7883 thandle_t data;
7884 tdata_t base;
7885 toff_t size;
7887 /* We don't need to do this. */
7890 static toff_t
7891 tiff_size_of_memory (data)
7892 thandle_t data;
7894 return ((tiff_memory_source *) data)->len;
7898 static void
7899 tiff_error_handler (title, format, ap)
7900 const char *title, *format;
7901 va_list ap;
7903 char buf[512];
7904 int len;
7906 len = sprintf (buf, "TIFF error: %s ", title);
7907 vsprintf (buf + len, format, ap);
7908 add_to_log (buf, Qnil, Qnil);
7912 static void
7913 tiff_warning_handler (title, format, ap)
7914 const char *title, *format;
7915 va_list ap;
7917 char buf[512];
7918 int len;
7920 len = sprintf (buf, "TIFF warning: %s ", title);
7921 vsprintf (buf + len, format, ap);
7922 add_to_log (buf, Qnil, Qnil);
7926 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7927 successful. */
7929 static int
7930 tiff_load (f, img)
7931 struct frame *f;
7932 struct image *img;
7934 Lisp_Object file, specified_file;
7935 Lisp_Object specified_data;
7936 TIFF *tiff;
7937 int width, height, x, y;
7938 uint32 *buf;
7939 int rc;
7940 XImagePtr ximg;
7941 struct gcpro gcpro1;
7942 tiff_memory_source memsrc;
7944 specified_file = image_spec_value (img->spec, QCfile, NULL);
7945 specified_data = image_spec_value (img->spec, QCdata, NULL);
7946 file = Qnil;
7947 GCPRO1 (file);
7949 fn_TIFFSetErrorHandler (tiff_error_handler);
7950 fn_TIFFSetWarningHandler (tiff_warning_handler);
7952 if (NILP (specified_data))
7954 /* Read from a file */
7955 file = x_find_image_file (specified_file);
7956 if (!STRINGP (file))
7958 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7959 UNGCPRO;
7960 return 0;
7963 /* Try to open the image file. Casting return value avoids a
7964 GCC warning on W32. */
7965 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7966 if (tiff == NULL)
7968 image_error ("Cannot open `%s'", file, Qnil);
7969 UNGCPRO;
7970 return 0;
7973 else
7975 /* Memory source! */
7976 memsrc.bytes = SDATA (specified_data);
7977 memsrc.len = SBYTES (specified_data);
7978 memsrc.index = 0;
7980 /* Casting return value avoids a GCC warning on W32. */
7981 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7982 (TIFFReadWriteProc) tiff_read_from_memory,
7983 (TIFFReadWriteProc) tiff_write_from_memory,
7984 tiff_seek_in_memory,
7985 tiff_close_memory,
7986 tiff_size_of_memory,
7987 tiff_mmap_memory,
7988 tiff_unmap_memory);
7990 if (!tiff)
7992 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7993 UNGCPRO;
7994 return 0;
7998 /* Get width and height of the image, and allocate a raster buffer
7999 of width x height 32-bit values. */
8000 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
8001 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
8003 if (!check_image_size (f, width, height))
8005 image_error ("Invalid image size", Qnil, Qnil);
8006 UNGCPRO;
8007 return 0;
8010 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
8012 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
8013 fn_TIFFClose (tiff);
8014 if (!rc)
8016 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
8017 xfree (buf);
8018 UNGCPRO;
8019 return 0;
8022 /* Create the X image and pixmap. */
8023 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8025 xfree (buf);
8026 UNGCPRO;
8027 return 0;
8030 /* Initialize the color table. */
8031 init_color_table ();
8033 /* Process the pixel raster. Origin is in the lower-left corner. */
8034 for (y = 0; y < height; ++y)
8036 uint32 *row = buf + y * width;
8038 for (x = 0; x < width; ++x)
8040 uint32 abgr = row[x];
8041 int r = TIFFGetR (abgr) << 8;
8042 int g = TIFFGetG (abgr) << 8;
8043 int b = TIFFGetB (abgr) << 8;
8044 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
8048 #ifdef COLOR_TABLE_SUPPORT
8049 /* Remember the colors allocated for the image. Free the color table. */
8050 img->colors = colors_in_color_table (&img->ncolors);
8051 free_color_table ();
8052 #endif /* COLOR_TABLE_SUPPORT */
8054 img->width = width;
8055 img->height = height;
8057 /* Maybe fill in the background field while we have ximg handy. */
8058 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8059 /* Casting avoids a GCC warning on W32. */
8060 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8062 /* Put the image into the pixmap, then free the X image and its buffer. */
8063 x_put_x_image (f, ximg, img->pixmap, width, height);
8064 x_destroy_x_image (ximg);
8065 xfree (buf);
8067 UNGCPRO;
8068 return 1;
8071 #else /* HAVE_TIFF */
8073 #ifdef MAC_OS
8074 static int
8075 tiff_load (f, img)
8076 struct frame *f;
8077 struct image *img;
8079 #if USE_MAC_IMAGE_IO
8080 return image_load_image_io (f, img, kUTTypeTIFF);
8081 #else
8082 return image_load_quicktime (f, img, kQTFileTypeTIFF);
8083 #endif
8085 #endif /* MAC_OS */
8087 #ifdef HAVE_NS
8088 static int
8089 tiff_load (struct frame *f, struct image *img)
8091 return ns_load_image(f, img,
8092 image_spec_value (img->spec, QCfile, NULL),
8093 image_spec_value (img->spec, QCdata, NULL));
8095 #endif /* HAVE_NS */
8097 #endif /* !HAVE_TIFF */
8101 /***********************************************************************
8103 ***********************************************************************/
8105 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
8107 static int gif_image_p P_ ((Lisp_Object object));
8108 static int gif_load P_ ((struct frame *f, struct image *img));
8109 static void gif_clear_image P_ ((struct frame *f, struct image *img));
8111 /* The symbol `gif' identifying images of this type. */
8113 Lisp_Object Qgif;
8115 /* Indices of image specification fields in gif_format, below. */
8117 enum gif_keyword_index
8119 GIF_TYPE,
8120 GIF_DATA,
8121 GIF_FILE,
8122 GIF_ASCENT,
8123 GIF_MARGIN,
8124 GIF_RELIEF,
8125 GIF_ALGORITHM,
8126 GIF_HEURISTIC_MASK,
8127 GIF_MASK,
8128 GIF_IMAGE,
8129 GIF_BACKGROUND,
8130 GIF_LAST
8133 /* Vector of image_keyword structures describing the format
8134 of valid user-defined image specifications. */
8136 static struct image_keyword gif_format[GIF_LAST] =
8138 {":type", IMAGE_SYMBOL_VALUE, 1},
8139 {":data", IMAGE_STRING_VALUE, 0},
8140 {":file", IMAGE_STRING_VALUE, 0},
8141 {":ascent", IMAGE_ASCENT_VALUE, 0},
8142 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8143 {":relief", IMAGE_INTEGER_VALUE, 0},
8144 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8145 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8146 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8147 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8148 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8151 /* Structure describing the image type `gif'. */
8153 static struct image_type gif_type =
8155 &Qgif,
8156 gif_image_p,
8157 gif_load,
8158 gif_clear_image,
8159 NULL
8162 /* Free X resources of GIF image IMG which is used on frame F. */
8164 static void
8165 gif_clear_image (f, img)
8166 struct frame *f;
8167 struct image *img;
8169 /* IMG->data.ptr_val may contain extension data. */
8170 img->data.lisp_val = Qnil;
8171 x_clear_image (f, img);
8174 /* Return non-zero if OBJECT is a valid GIF image specification. */
8176 static int
8177 gif_image_p (object)
8178 Lisp_Object object;
8180 struct image_keyword fmt[GIF_LAST];
8181 bcopy (gif_format, fmt, sizeof fmt);
8183 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8184 return 0;
8186 /* Must specify either the :data or :file keyword. */
8187 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8190 #endif /* HAVE_GIF || MAC_OS */
8192 #ifdef HAVE_GIF
8194 #if defined (HAVE_NTGUI) || defined (MAC_OS)
8195 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
8196 Undefine before redefining to avoid a preprocessor warning. */
8197 #ifdef DrawText
8198 #undef DrawText
8199 #endif
8200 /* avoid conflict with QuickdrawText.h */
8201 #define DrawText gif_DrawText
8202 #include <gif_lib.h>
8203 #undef DrawText
8205 #else /* HAVE_NTGUI || MAC_OS */
8207 #include <gif_lib.h>
8209 #endif /* HAVE_NTGUI || MAC_OS */
8212 #ifdef HAVE_NTGUI
8214 /* GIF library details. */
8215 DEF_IMGLIB_FN (DGifCloseFile);
8216 DEF_IMGLIB_FN (DGifSlurp);
8217 DEF_IMGLIB_FN (DGifOpen);
8218 DEF_IMGLIB_FN (DGifOpenFileName);
8220 static int
8221 init_gif_functions (Lisp_Object libraries)
8223 HMODULE library;
8225 if (!(library = w32_delayed_load (libraries, Qgif)))
8226 return 0;
8228 LOAD_IMGLIB_FN (library, DGifCloseFile);
8229 LOAD_IMGLIB_FN (library, DGifSlurp);
8230 LOAD_IMGLIB_FN (library, DGifOpen);
8231 LOAD_IMGLIB_FN (library, DGifOpenFileName);
8232 return 1;
8235 #else
8237 #define fn_DGifCloseFile DGifCloseFile
8238 #define fn_DGifSlurp DGifSlurp
8239 #define fn_DGifOpen DGifOpen
8240 #define fn_DGifOpenFileName DGifOpenFileName
8242 #endif /* HAVE_NTGUI */
8244 /* Reading a GIF image from memory
8245 Based on the PNG memory stuff to a certain extent. */
8247 typedef struct
8249 unsigned char *bytes;
8250 size_t len;
8251 int index;
8253 gif_memory_source;
8255 /* Make the current memory source available to gif_read_from_memory.
8256 It's done this way because not all versions of libungif support
8257 a UserData field in the GifFileType structure. */
8258 static gif_memory_source *current_gif_memory_src;
8260 static int
8261 gif_read_from_memory (file, buf, len)
8262 GifFileType *file;
8263 GifByteType *buf;
8264 int len;
8266 gif_memory_source *src = current_gif_memory_src;
8268 if (len > src->len - src->index)
8269 return -1;
8271 bcopy (src->bytes + src->index, buf, len);
8272 src->index += len;
8273 return len;
8277 /* Load GIF image IMG for use on frame F. Value is non-zero if
8278 successful. */
8280 static int interlace_start[] = {0, 4, 2, 1};
8281 static int interlace_increment[] = {8, 8, 4, 2};
8283 static int
8284 gif_load (f, img)
8285 struct frame *f;
8286 struct image *img;
8288 Lisp_Object file, specified_file;
8289 Lisp_Object specified_data;
8290 int rc, width, height, x, y, i;
8291 XImagePtr ximg;
8292 ColorMapObject *gif_color_map;
8293 unsigned long pixel_colors[256];
8294 GifFileType *gif;
8295 struct gcpro gcpro1;
8296 Lisp_Object image;
8297 int ino, image_height, image_width;
8298 gif_memory_source memsrc;
8299 unsigned char *raster;
8301 specified_file = image_spec_value (img->spec, QCfile, NULL);
8302 specified_data = image_spec_value (img->spec, QCdata, NULL);
8303 file = Qnil;
8304 GCPRO1 (file);
8306 if (NILP (specified_data))
8308 file = x_find_image_file (specified_file);
8309 if (!STRINGP (file))
8311 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8312 UNGCPRO;
8313 return 0;
8316 /* Open the GIF file. Casting return value avoids a GCC warning
8317 on W32. */
8318 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
8319 if (gif == NULL)
8321 image_error ("Cannot open `%s'", file, Qnil);
8322 UNGCPRO;
8323 return 0;
8326 else
8328 /* Read from memory! */
8329 current_gif_memory_src = &memsrc;
8330 memsrc.bytes = SDATA (specified_data);
8331 memsrc.len = SBYTES (specified_data);
8332 memsrc.index = 0;
8334 /* Casting return value avoids a GCC warning on W32. */
8335 gif = (GifFileType *) fn_DGifOpen (&memsrc, gif_read_from_memory);
8336 if (!gif)
8338 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8339 UNGCPRO;
8340 return 0;
8344 /* Before reading entire contents, check the declared image size. */
8345 if (!check_image_size (f, gif->SWidth, gif->SHeight))
8347 image_error ("Invalid image size", Qnil, Qnil);
8348 fn_DGifCloseFile (gif);
8349 UNGCPRO;
8350 return 0;
8353 /* Read entire contents. */
8354 rc = fn_DGifSlurp (gif);
8355 if (rc == GIF_ERROR)
8357 image_error ("Error reading `%s'", img->spec, Qnil);
8358 fn_DGifCloseFile (gif);
8359 UNGCPRO;
8360 return 0;
8363 image = image_spec_value (img->spec, QCindex, NULL);
8364 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8365 if (ino >= gif->ImageCount)
8367 image_error ("Invalid image number `%s' in image `%s'",
8368 image, img->spec);
8369 fn_DGifCloseFile (gif);
8370 UNGCPRO;
8371 return 0;
8374 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
8375 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
8376 image_height = gif->SavedImages[ino].ImageDesc.Height;
8377 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
8378 image_width = gif->SavedImages[ino].ImageDesc.Width;
8379 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
8381 width = img->width = max (gif->SWidth,
8382 max (gif->Image.Left + gif->Image.Width,
8383 img->corners[RIGHT_CORNER]));
8384 height = img->height = max (gif->SHeight,
8385 max (gif->Image.Top + gif->Image.Height,
8386 img->corners[BOT_CORNER]));
8388 if (!check_image_size (f, width, height))
8390 image_error ("Invalid image size", Qnil, Qnil);
8391 fn_DGifCloseFile (gif);
8392 UNGCPRO;
8393 return 0;
8396 /* Create the X image and pixmap. */
8397 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8399 fn_DGifCloseFile (gif);
8400 UNGCPRO;
8401 return 0;
8404 /* Allocate colors. */
8405 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8406 if (!gif_color_map)
8407 gif_color_map = gif->SColorMap;
8408 init_color_table ();
8409 bzero (pixel_colors, sizeof pixel_colors);
8411 if (gif_color_map)
8412 for (i = 0; i < gif_color_map->ColorCount; ++i)
8414 int r = gif_color_map->Colors[i].Red << 8;
8415 int g = gif_color_map->Colors[i].Green << 8;
8416 int b = gif_color_map->Colors[i].Blue << 8;
8417 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8420 #ifdef COLOR_TABLE_SUPPORT
8421 img->colors = colors_in_color_table (&img->ncolors);
8422 free_color_table ();
8423 #endif /* COLOR_TABLE_SUPPORT */
8425 /* Clear the part of the screen image that are not covered by
8426 the image from the GIF file. Full animated GIF support
8427 requires more than can be done here (see the gif89 spec,
8428 disposal methods). Let's simply assume that the part
8429 not covered by a sub-image is in the frame's background color. */
8430 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
8431 for (x = 0; x < width; ++x)
8432 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8434 for (y = img->corners[BOT_CORNER]; y < height; ++y)
8435 for (x = 0; x < width; ++x)
8436 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8438 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
8440 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
8441 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8442 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
8443 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8446 /* Read the GIF image into the X image. We use a local variable
8447 `raster' here because RasterBits below is a char *, and invites
8448 problems with bytes >= 0x80. */
8449 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8451 if (gif->SavedImages[ino].ImageDesc.Interlace)
8453 int pass;
8454 int row = interlace_start[0];
8456 pass = 0;
8458 for (y = 0; y < image_height; y++)
8460 if (row >= image_height)
8462 row = interlace_start[++pass];
8463 while (row >= image_height)
8464 row = interlace_start[++pass];
8467 for (x = 0; x < image_width; x++)
8469 int i = raster[(y * image_width) + x];
8470 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8471 row + img->corners[TOP_CORNER], pixel_colors[i]);
8474 row += interlace_increment[pass];
8477 else
8479 for (y = 0; y < image_height; ++y)
8480 for (x = 0; x < image_width; ++x)
8482 int i = raster[y * image_width + x];
8483 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8484 y + img->corners[TOP_CORNER], pixel_colors[i]);
8488 /* Save GIF image extension data for `image-extension-data'.
8489 Format is (count IMAGES FUNCTION "BYTES" ...). */
8490 img->data.lisp_val = Qnil;
8491 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
8493 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
8494 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
8495 /* Append (... FUNCTION "BYTES") */
8496 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
8497 Fcons (make_number (ext->Function),
8498 img->data.lisp_val));
8499 img->data.lisp_val = Fnreverse (img->data.lisp_val);
8501 if (gif->ImageCount > 1)
8502 img->data.lisp_val = Fcons (Qcount,
8503 Fcons (make_number (gif->ImageCount),
8504 img->data.lisp_val));
8506 fn_DGifCloseFile (gif);
8508 /* Maybe fill in the background field while we have ximg handy. */
8509 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8510 /* Casting avoids a GCC warning. */
8511 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8513 /* Put the image into the pixmap, then free the X image and its buffer. */
8514 x_put_x_image (f, ximg, img->pixmap, width, height);
8515 x_destroy_x_image (ximg);
8517 UNGCPRO;
8518 return 1;
8521 #else /* !HAVE_GIF */
8523 #ifdef MAC_OS
8524 static int
8525 gif_load (f, img)
8526 struct frame *f;
8527 struct image *img;
8529 #if USE_MAC_IMAGE_IO
8530 return image_load_image_io (f, img, kUTTypeGIF);
8531 #else /* !USE_MAC_IMAGE_IO */
8532 Lisp_Object specified_file, file;
8533 Lisp_Object specified_data;
8534 OSErr err;
8535 Boolean graphic_p, movie_p, prefer_graphic_p;
8536 Handle dh = NULL;
8537 Movie movie = NULL;
8538 Lisp_Object image;
8539 Track track = NULL;
8540 Media media = NULL;
8541 long nsamples;
8542 Rect rect;
8543 Lisp_Object specified_bg;
8544 XColor color;
8545 RGBColor bg_color;
8546 int width, height;
8547 XImagePtr ximg;
8548 TimeScale time_scale;
8549 TimeValue time, duration;
8550 int ino;
8551 CGrafPtr old_port;
8552 GDHandle old_gdh;
8554 specified_file = image_spec_value (img->spec, QCfile, NULL);
8555 specified_data = image_spec_value (img->spec, QCdata, NULL);
8557 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8558 EnterMovies ();
8560 if (NILP (specified_data))
8562 /* Read from a file */
8563 FSSpec fss;
8564 short refnum;
8566 err = find_image_fsspec (specified_file, &file, &fss);
8567 if (err != noErr)
8569 if (err == fnfErr)
8570 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8571 else
8572 goto open_error;
8575 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
8576 &graphic_p, &movie_p, &prefer_graphic_p, 0);
8577 if (err != noErr)
8578 goto open_error;
8580 if (!graphic_p && !movie_p)
8581 goto open_error;
8582 if (prefer_graphic_p)
8583 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
8584 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
8585 if (err != noErr)
8586 goto open_error;
8587 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
8588 CloseMovieFile (refnum);
8589 if (err != noErr)
8591 image_error ("Error reading `%s'", file, Qnil);
8592 return 0;
8595 else
8597 /* Memory source! */
8598 Handle dref = NULL;
8599 long file_type_atom[3];
8601 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
8602 if (err != noErr)
8604 image_error ("Cannot allocate data handle for `%s'",
8605 img->spec, Qnil);
8606 goto error;
8609 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
8610 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
8611 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
8612 err = PtrToHand (&dh, &dref, sizeof (Handle));
8613 if (err == noErr)
8614 /* no file name */
8615 err = PtrAndHand ("\p", dref, 1);
8616 if (err == noErr)
8617 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
8618 if (err != noErr)
8620 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
8621 goto error;
8623 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8624 &movie_p, &prefer_graphic_p, 0);
8625 if (err != noErr)
8626 goto open_error;
8628 if (!graphic_p && !movie_p)
8629 goto open_error;
8630 if (prefer_graphic_p)
8632 int success_p;
8634 DisposeHandle (dref);
8635 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8636 DisposeHandle (dh);
8637 return success_p;
8639 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8640 HandleDataHandlerSubType);
8641 DisposeHandle (dref);
8642 if (err != noErr)
8643 goto open_error;
8646 image = image_spec_value (img->spec, QCindex, NULL);
8647 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8648 track = GetMovieIndTrack (movie, 1);
8649 media = GetTrackMedia (track);
8650 nsamples = GetMediaSampleCount (media);
8651 if (ino >= nsamples)
8653 image_error ("Invalid image number `%s' in image `%s'",
8654 image, img->spec);
8655 goto error;
8657 time_scale = GetMediaTimeScale (media);
8659 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8660 if (!STRINGP (specified_bg)
8661 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8663 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8664 color.red = RED16_FROM_ULONG (color.pixel);
8665 color.green = GREEN16_FROM_ULONG (color.pixel);
8666 color.blue = BLUE16_FROM_ULONG (color.pixel);
8668 GetMovieBox (movie, &rect);
8669 width = img->width = rect.right - rect.left;
8670 height = img->height = rect.bottom - rect.top;
8671 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8672 goto error;
8674 GetGWorld (&old_port, &old_gdh);
8675 SetGWorld (ximg, NULL);
8676 bg_color.red = color.red;
8677 bg_color.green = color.green;
8678 bg_color.blue = color.blue;
8679 RGBBackColor (&bg_color);
8680 SetGWorld (old_port, old_gdh);
8681 SetMovieActive (movie, 1);
8682 SetMovieGWorld (movie, ximg, NULL);
8683 SampleNumToMediaTime (media, ino + 1, &time, &duration);
8684 SetMovieTimeValue (movie, time);
8685 MoviesTask (movie, 0L);
8686 DisposeTrackMedia (media);
8687 DisposeMovieTrack (track);
8688 DisposeMovie (movie);
8689 if (dh)
8690 DisposeHandle (dh);
8692 /* Save GIF image extension data for `image-extension-data'.
8693 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8695 Lisp_Object gce = make_uninit_string (4);
8696 int centisec = ((float)duration / time_scale) * 100.0f + 0.5f;
8698 /* Fill the delay time field. */
8699 SSET (gce, 1, centisec & 0xff);
8700 SSET (gce, 2, (centisec >> 8) & 0xff);
8701 /* We don't know about other fields. */
8702 SSET (gce, 0, 0);
8703 SSET (gce, 3, 0);
8705 img->data.lisp_val = list4 (Qcount, make_number (nsamples),
8706 make_number (0xf9), gce);
8709 /* Maybe fill in the background field while we have ximg handy. */
8710 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8711 IMAGE_BACKGROUND (img, f, ximg);
8713 /* Put the image into the pixmap. */
8714 x_put_x_image (f, ximg, img->pixmap, width, height);
8715 x_destroy_x_image (ximg);
8716 return 1;
8718 open_error:
8719 image_error ("Cannot open `%s'", file, Qnil);
8720 error:
8721 if (media)
8722 DisposeTrackMedia (media);
8723 if (track)
8724 DisposeMovieTrack (track);
8725 if (movie)
8726 DisposeMovie (movie);
8727 if (dh)
8728 DisposeHandle (dh);
8729 return 0;
8730 #endif /* !USE_MAC_IMAGE_IO */
8732 #endif /* MAC_OS */
8734 #ifdef HAVE_NS
8735 static int
8736 gif_load (struct frame *f, struct image *img)
8738 return ns_load_image(f, img,
8739 image_spec_value (img->spec, QCfile, NULL),
8740 image_spec_value (img->spec, QCdata, NULL));
8742 #endif /* HAVE_NS */
8744 #endif /* HAVE_GIF */
8748 /***********************************************************************
8750 ***********************************************************************/
8752 #if defined (HAVE_RSVG)
8754 /* Function prototypes. */
8756 static int svg_image_p P_ ((Lisp_Object object));
8757 static int svg_load P_ ((struct frame *f, struct image *img));
8759 static int svg_load_image P_ ((struct frame *, struct image *,
8760 unsigned char *, unsigned int));
8762 /* The symbol `svg' identifying images of this type. */
8764 Lisp_Object Qsvg;
8766 /* Indices of image specification fields in svg_format, below. */
8768 enum svg_keyword_index
8770 SVG_TYPE,
8771 SVG_DATA,
8772 SVG_FILE,
8773 SVG_ASCENT,
8774 SVG_MARGIN,
8775 SVG_RELIEF,
8776 SVG_ALGORITHM,
8777 SVG_HEURISTIC_MASK,
8778 SVG_MASK,
8779 SVG_BACKGROUND,
8780 SVG_LAST
8783 /* Vector of image_keyword structures describing the format
8784 of valid user-defined image specifications. */
8786 static struct image_keyword svg_format[SVG_LAST] =
8788 {":type", IMAGE_SYMBOL_VALUE, 1},
8789 {":data", IMAGE_STRING_VALUE, 0},
8790 {":file", IMAGE_STRING_VALUE, 0},
8791 {":ascent", IMAGE_ASCENT_VALUE, 0},
8792 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8793 {":relief", IMAGE_INTEGER_VALUE, 0},
8794 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8795 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8796 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8797 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8800 /* Structure describing the image type `svg'. Its the same type of
8801 structure defined for all image formats, handled by emacs image
8802 functions. See struct image_type in dispextern.h. */
8804 static struct image_type svg_type =
8806 /* An identifier showing that this is an image structure for the SVG format. */
8807 &Qsvg,
8808 /* Handle to a function that can be used to identify a SVG file. */
8809 svg_image_p,
8810 /* Handle to function used to load a SVG file. */
8811 svg_load,
8812 /* Handle to function to free sresources for SVG. */
8813 x_clear_image,
8814 /* An internal field to link to the next image type in a list of
8815 image types, will be filled in when registering the format. */
8816 NULL
8820 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8821 this by calling parse_image_spec and supplying the keywords that
8822 identify the SVG format. */
8824 static int
8825 svg_image_p (object)
8826 Lisp_Object object;
8828 struct image_keyword fmt[SVG_LAST];
8829 bcopy (svg_format, fmt, sizeof fmt);
8831 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
8832 return 0;
8834 /* Must specify either the :data or :file keyword. */
8835 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
8838 #include <librsvg/rsvg.h>
8840 #ifdef HAVE_NTGUI
8842 /* SVG library functions. */
8843 DEF_IMGLIB_FN (rsvg_handle_new);
8844 DEF_IMGLIB_FN (rsvg_handle_set_size_callback);
8845 DEF_IMGLIB_FN (rsvg_handle_write);
8846 DEF_IMGLIB_FN (rsvg_handle_close);
8847 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf);
8848 DEF_IMGLIB_FN (rsvg_handle_free);
8850 DEF_IMGLIB_FN (gdk_pixbuf_get_width);
8851 DEF_IMGLIB_FN (gdk_pixbuf_get_height);
8852 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels);
8853 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride);
8854 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace);
8855 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels);
8856 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha);
8857 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample);
8859 DEF_IMGLIB_FN (g_type_init);
8860 DEF_IMGLIB_FN (g_object_unref);
8861 DEF_IMGLIB_FN (g_error_free);
8863 Lisp_Object Qgdk_pixbuf, Qglib;
8865 static int
8866 init_svg_functions (Lisp_Object libraries)
8868 HMODULE library, gdklib, glib;
8870 if (!(glib = w32_delayed_load (libraries, Qglib))
8871 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
8872 || !(library = w32_delayed_load (libraries, Qsvg)))
8873 return 0;
8875 LOAD_IMGLIB_FN (library, rsvg_handle_new);
8876 LOAD_IMGLIB_FN (library, rsvg_handle_set_size_callback);
8877 LOAD_IMGLIB_FN (library, rsvg_handle_write);
8878 LOAD_IMGLIB_FN (library, rsvg_handle_close);
8879 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
8880 LOAD_IMGLIB_FN (library, rsvg_handle_free);
8882 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
8883 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
8884 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
8885 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
8886 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
8887 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
8888 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
8889 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
8891 LOAD_IMGLIB_FN (glib, g_type_init);
8892 LOAD_IMGLIB_FN (glib, g_object_unref);
8893 LOAD_IMGLIB_FN (glib, g_error_free);
8894 return 1;
8897 #else
8898 /* The following aliases for library functions allow dynamic loading
8899 to be used on some platforms. */
8900 #define fn_rsvg_handle_new rsvg_handle_new
8901 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8902 #define fn_rsvg_handle_write rsvg_handle_write
8903 #define fn_rsvg_handle_close rsvg_handle_close
8904 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8905 #define fn_rsvg_handle_free rsvg_handle_free
8907 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8908 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8909 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8910 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8911 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8912 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8913 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8914 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8916 #define fn_g_type_init g_type_init
8917 #define fn_g_object_unref g_object_unref
8918 #define fn_g_error_free g_error_free
8919 #endif /* !HAVE_NTGUI */
8921 /* Load SVG image IMG for use on frame F. Value is non-zero if
8922 successful. this function will go into the svg_type structure, and
8923 the prototype thus needs to be compatible with that structure. */
8925 static int
8926 svg_load (f, img)
8927 struct frame *f;
8928 struct image *img;
8930 int success_p = 0;
8931 Lisp_Object file_name;
8933 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8934 file_name = image_spec_value (img->spec, QCfile, NULL);
8935 if (STRINGP (file_name))
8937 Lisp_Object file;
8938 unsigned char *contents;
8939 int size;
8940 struct gcpro gcpro1;
8942 file = x_find_image_file (file_name);
8943 GCPRO1 (file);
8944 if (!STRINGP (file))
8946 image_error ("Cannot find image file `%s'", file_name, Qnil);
8947 UNGCPRO;
8948 return 0;
8951 /* Read the entire file into memory. */
8952 contents = slurp_file (SDATA (file), &size);
8953 if (contents == NULL)
8955 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
8956 UNGCPRO;
8957 return 0;
8959 /* If the file was slurped into memory properly, parse it. */
8960 success_p = svg_load_image (f, img, contents, size);
8961 xfree (contents);
8962 UNGCPRO;
8964 /* Else its not a file, its a lisp object. Load the image from a
8965 lisp object rather than a file. */
8966 else
8968 Lisp_Object data;
8970 data = image_spec_value (img->spec, QCdata, NULL);
8971 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
8974 return success_p;
8977 /* svg_load_image is a helper function for svg_load, which does the
8978 actual loading given contents and size, apart from frame and image
8979 structures, passed from svg_load.
8981 Uses librsvg to do most of the image processing.
8983 Returns non-zero when successful. */
8984 static int
8985 svg_load_image (f, img, contents, size)
8986 /* Pointer to emacs frame structure. */
8987 struct frame *f;
8988 /* Pointer to emacs image structure. */
8989 struct image *img;
8990 /* String containing the SVG XML data to be parsed. */
8991 unsigned char *contents;
8992 /* Size of data in bytes. */
8993 unsigned int size;
8995 RsvgHandle *rsvg_handle;
8996 GError *error = NULL;
8997 GdkPixbuf *pixbuf;
8998 int width;
8999 int height;
9000 const guint8 *pixels;
9001 int rowstride;
9002 XImagePtr ximg;
9003 Lisp_Object specified_bg;
9004 XColor background;
9005 int x;
9006 int y;
9008 /* g_type_init is a glib function that must be called prior to using
9009 gnome type library functions. */
9010 fn_g_type_init ();
9011 /* Make a handle to a new rsvg object. */
9012 rsvg_handle = fn_rsvg_handle_new ();
9014 /* Parse the contents argument and fill in the rsvg_handle. */
9015 fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
9016 if (error)
9017 goto rsvg_error;
9019 /* The parsing is complete, rsvg_handle is ready to used, close it
9020 for further writes. */
9021 fn_rsvg_handle_close (rsvg_handle, &error);
9022 if (error)
9023 goto rsvg_error;
9024 /* We can now get a valid pixel buffer from the svg file, if all
9025 went ok. */
9026 pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
9027 eassert (pixbuf);
9029 /* Extract some meta data from the svg handle. */
9030 width = fn_gdk_pixbuf_get_width (pixbuf);
9031 height = fn_gdk_pixbuf_get_height (pixbuf);
9032 pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
9033 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
9035 /* Validate the svg meta data. */
9036 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
9037 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
9038 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
9039 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
9041 /* Try to create a x pixmap to hold the svg pixmap. */
9042 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
9044 fn_g_object_unref (pixbuf);
9045 return 0;
9048 init_color_table ();
9050 /* Handle alpha channel by combining the image with a background
9051 color. */
9052 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
9053 if (STRINGP (specified_bg)
9054 && x_defined_color (f, SDATA (specified_bg), &background, 0))
9056 background.red >>= 8;
9057 background.green >>= 8;
9058 background.blue >>= 8;
9060 else
9062 #ifdef HAVE_X_WINDOWS
9063 background.pixel = FRAME_BACKGROUND_PIXEL (f);
9064 x_query_color (f, &background);
9066 /* SVG pixmaps specify transparency in the last byte, so right
9067 shift 8 bits to get rid of it, since emacs doesn't support
9068 transparency. */
9069 background.red >>= 8;
9070 background.green >>= 8;
9071 background.blue >>= 8;
9072 #elif defined (MAC_OS)
9073 background.pixel = FRAME_BACKGROUND_PIXEL (f);
9074 background.red = RED_FROM_ULONG (background.pixel);
9075 background.green = GREEN_FROM_ULONG (background.pixel);
9076 background.blue = BLUE_FROM_ULONG (background.pixel);
9077 #elif defined (HAVE_NTGUI)
9078 background.pixel = FRAME_BACKGROUND_PIXEL (f);
9079 #if 0 /* W32 TODO : Colormap support. */
9080 x_query_color (f, &background);
9081 #endif
9083 /* SVG pixmaps specify transparency in the last byte, so right
9084 shift 8 bits to get rid of it, since emacs doesn't support
9085 transparency. */
9086 background.red >>= 8;
9087 background.green >>= 8;
9088 background.blue >>= 8;
9089 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
9090 #error FIXME
9091 #endif
9094 /* This loop handles opacity values, since Emacs assumes
9095 non-transparent images. Each pixel must be "flattened" by
9096 calculating the resulting color, given the transparency of the
9097 pixel, and the image background color. */
9098 for (y = 0; y < height; ++y)
9100 for (x = 0; x < width; ++x)
9102 unsigned red;
9103 unsigned green;
9104 unsigned blue;
9105 unsigned opacity;
9107 red = *pixels++;
9108 green = *pixels++;
9109 blue = *pixels++;
9110 opacity = *pixels++;
9112 red = ((red * opacity)
9113 + (background.red * ((1 << 8) - opacity)));
9114 green = ((green * opacity)
9115 + (background.green * ((1 << 8) - opacity)));
9116 blue = ((blue * opacity)
9117 + (background.blue * ((1 << 8) - opacity)));
9119 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
9122 pixels += rowstride - 4 * width;
9125 #ifdef COLOR_TABLE_SUPPORT
9126 /* Remember colors allocated for this image. */
9127 img->colors = colors_in_color_table (&img->ncolors);
9128 free_color_table ();
9129 #endif /* COLOR_TABLE_SUPPORT */
9131 fn_g_object_unref (pixbuf);
9133 img->width = width;
9134 img->height = height;
9136 /* Maybe fill in the background field while we have ximg handy.
9137 Casting avoids a GCC warning. */
9138 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
9140 /* Put the image into the pixmap, then free the X image and its
9141 buffer. */
9142 x_put_x_image (f, ximg, img->pixmap, width, height);
9143 x_destroy_x_image (ximg);
9145 return 1;
9147 rsvg_error:
9148 /* FIXME: Use error->message so the user knows what is the actual
9149 problem with the image. */
9150 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
9151 fn_g_error_free (error);
9152 return 0;
9155 #endif /* defined (HAVE_RSVG) */
9160 /***********************************************************************
9161 Ghostscript
9162 ***********************************************************************/
9164 #ifdef HAVE_X_WINDOWS
9165 #define HAVE_GHOSTSCRIPT 1
9166 #endif /* HAVE_X_WINDOWS */
9168 /* The symbol `postscript' identifying images of this type. */
9170 Lisp_Object Qpostscript;
9172 #ifdef HAVE_GHOSTSCRIPT
9174 static int gs_image_p P_ ((Lisp_Object object));
9175 static int gs_load P_ ((struct frame *f, struct image *img));
9176 static void gs_clear_image P_ ((struct frame *f, struct image *img));
9178 /* Keyword symbols. */
9180 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
9182 /* Indices of image specification fields in gs_format, below. */
9184 enum gs_keyword_index
9186 GS_TYPE,
9187 GS_PT_WIDTH,
9188 GS_PT_HEIGHT,
9189 GS_FILE,
9190 GS_LOADER,
9191 GS_BOUNDING_BOX,
9192 GS_ASCENT,
9193 GS_MARGIN,
9194 GS_RELIEF,
9195 GS_ALGORITHM,
9196 GS_HEURISTIC_MASK,
9197 GS_MASK,
9198 GS_BACKGROUND,
9199 GS_LAST
9202 /* Vector of image_keyword structures describing the format
9203 of valid user-defined image specifications. */
9205 static struct image_keyword gs_format[GS_LAST] =
9207 {":type", IMAGE_SYMBOL_VALUE, 1},
9208 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9209 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9210 {":file", IMAGE_STRING_VALUE, 1},
9211 {":loader", IMAGE_FUNCTION_VALUE, 0},
9212 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9213 {":ascent", IMAGE_ASCENT_VALUE, 0},
9214 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9215 {":relief", IMAGE_INTEGER_VALUE, 0},
9216 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9217 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9218 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9219 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9222 /* Structure describing the image type `ghostscript'. */
9224 static struct image_type gs_type =
9226 &Qpostscript,
9227 gs_image_p,
9228 gs_load,
9229 gs_clear_image,
9230 NULL
9234 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9236 static void
9237 gs_clear_image (f, img)
9238 struct frame *f;
9239 struct image *img;
9241 /* IMG->data.ptr_val may contain a recorded colormap. */
9242 xfree (img->data.ptr_val);
9243 x_clear_image (f, img);
9247 /* Return non-zero if OBJECT is a valid Ghostscript image
9248 specification. */
9250 static int
9251 gs_image_p (object)
9252 Lisp_Object object;
9254 struct image_keyword fmt[GS_LAST];
9255 Lisp_Object tem;
9256 int i;
9258 bcopy (gs_format, fmt, sizeof fmt);
9260 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9261 return 0;
9263 /* Bounding box must be a list or vector containing 4 integers. */
9264 tem = fmt[GS_BOUNDING_BOX].value;
9265 if (CONSP (tem))
9267 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9268 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9269 return 0;
9270 if (!NILP (tem))
9271 return 0;
9273 else if (VECTORP (tem))
9275 if (XVECTOR (tem)->size != 4)
9276 return 0;
9277 for (i = 0; i < 4; ++i)
9278 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9279 return 0;
9281 else
9282 return 0;
9284 return 1;
9288 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9289 if successful. */
9291 static int
9292 gs_load (f, img)
9293 struct frame *f;
9294 struct image *img;
9296 char buffer[100];
9297 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9298 struct gcpro gcpro1, gcpro2;
9299 Lisp_Object frame;
9300 double in_width, in_height;
9301 Lisp_Object pixel_colors = Qnil;
9303 /* Compute pixel size of pixmap needed from the given size in the
9304 image specification. Sizes in the specification are in pt. 1 pt
9305 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9306 info. */
9307 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9308 in_width = XFASTINT (pt_width) / 72.0;
9309 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9310 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9311 in_height = XFASTINT (pt_height) / 72.0;
9312 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9314 if (!check_image_size (f, img->width, img->height))
9316 image_error ("Invalid image size", Qnil, Qnil);
9317 return 0;
9320 /* Create the pixmap. */
9321 xassert (img->pixmap == NO_PIXMAP);
9323 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9324 BLOCK_INPUT;
9325 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9326 img->width, img->height,
9327 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9328 UNBLOCK_INPUT;
9330 if (!img->pixmap)
9332 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9333 return 0;
9336 /* Call the loader to fill the pixmap. It returns a process object
9337 if successful. We do not record_unwind_protect here because
9338 other places in redisplay like calling window scroll functions
9339 don't either. Let the Lisp loader use `unwind-protect' instead. */
9340 GCPRO2 (window_and_pixmap_id, pixel_colors);
9342 sprintf (buffer, "%lu %lu",
9343 (unsigned long) FRAME_X_WINDOW (f),
9344 (unsigned long) img->pixmap);
9345 window_and_pixmap_id = build_string (buffer);
9347 sprintf (buffer, "%lu %lu",
9348 FRAME_FOREGROUND_PIXEL (f),
9349 FRAME_BACKGROUND_PIXEL (f));
9350 pixel_colors = build_string (buffer);
9352 XSETFRAME (frame, f);
9353 loader = image_spec_value (img->spec, QCloader, NULL);
9354 if (NILP (loader))
9355 loader = intern ("gs-load-image");
9357 img->data.lisp_val = call6 (loader, frame, img->spec,
9358 make_number (img->width),
9359 make_number (img->height),
9360 window_and_pixmap_id,
9361 pixel_colors);
9362 UNGCPRO;
9363 return PROCESSP (img->data.lisp_val);
9367 /* Kill the Ghostscript process that was started to fill PIXMAP on
9368 frame F. Called from XTread_socket when receiving an event
9369 telling Emacs that Ghostscript has finished drawing. */
9371 void
9372 x_kill_gs_process (pixmap, f)
9373 Pixmap pixmap;
9374 struct frame *f;
9376 struct image_cache *c = FRAME_IMAGE_CACHE (f);
9377 int class, i;
9378 struct image *img;
9380 /* Find the image containing PIXMAP. */
9381 for (i = 0; i < c->used; ++i)
9382 if (c->images[i]->pixmap == pixmap)
9383 break;
9385 /* Should someone in between have cleared the image cache, for
9386 instance, give up. */
9387 if (i == c->used)
9388 return;
9390 /* Kill the GS process. We should have found PIXMAP in the image
9391 cache and its image should contain a process object. */
9392 img = c->images[i];
9393 xassert (PROCESSP (img->data.lisp_val));
9394 Fkill_process (img->data.lisp_val, Qnil);
9395 img->data.lisp_val = Qnil;
9397 #if defined (HAVE_X_WINDOWS)
9399 /* On displays with a mutable colormap, figure out the colors
9400 allocated for the image by looking at the pixels of an XImage for
9401 img->pixmap. */
9402 class = FRAME_X_VISUAL (f)->class;
9403 if (class != StaticColor && class != StaticGray && class != TrueColor)
9405 XImagePtr ximg;
9407 BLOCK_INPUT;
9409 /* Try to get an XImage for img->pixmep. */
9410 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9411 0, 0, img->width, img->height, ~0, ZPixmap);
9412 if (ximg)
9414 int x, y;
9416 /* Initialize the color table. */
9417 init_color_table ();
9419 /* For each pixel of the image, look its color up in the
9420 color table. After having done so, the color table will
9421 contain an entry for each color used by the image. */
9422 for (y = 0; y < img->height; ++y)
9423 for (x = 0; x < img->width; ++x)
9425 unsigned long pixel = XGetPixel (ximg, x, y);
9426 lookup_pixel_color (f, pixel);
9429 /* Record colors in the image. Free color table and XImage. */
9430 #ifdef COLOR_TABLE_SUPPORT
9431 img->colors = colors_in_color_table (&img->ncolors);
9432 free_color_table ();
9433 #endif
9434 XDestroyImage (ximg);
9436 #if 0 /* This doesn't seem to be the case. If we free the colors
9437 here, we get a BadAccess later in x_clear_image when
9438 freeing the colors. */
9439 /* We have allocated colors once, but Ghostscript has also
9440 allocated colors on behalf of us. So, to get the
9441 reference counts right, free them once. */
9442 if (img->ncolors)
9443 x_free_colors (f, img->colors, img->ncolors);
9444 #endif
9446 else
9447 image_error ("Cannot get X image of `%s'; colors will not be freed",
9448 img->spec, Qnil);
9450 UNBLOCK_INPUT;
9452 #endif /* HAVE_X_WINDOWS */
9454 /* Now that we have the pixmap, compute mask and transform the
9455 image if requested. */
9456 BLOCK_INPUT;
9457 postprocess_image (f, img);
9458 UNBLOCK_INPUT;
9461 #endif /* HAVE_GHOSTSCRIPT */
9464 /***********************************************************************
9465 Tests
9466 ***********************************************************************/
9468 #if GLYPH_DEBUG
9470 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
9471 doc: /* Value is non-nil if SPEC is a valid image specification. */)
9472 (spec)
9473 Lisp_Object spec;
9475 return valid_image_p (spec) ? Qt : Qnil;
9479 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
9480 (spec)
9481 Lisp_Object spec;
9483 int id = -1;
9485 if (valid_image_p (spec))
9486 id = lookup_image (SELECTED_FRAME (), spec);
9488 debug_print (spec);
9489 return make_number (id);
9492 #endif /* GLYPH_DEBUG != 0 */
9495 /***********************************************************************
9496 Initialization
9497 ***********************************************************************/
9499 #ifdef HAVE_NTGUI
9500 /* Image types that rely on external libraries are loaded dynamically
9501 if the library is available. */
9502 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9503 define_image_type (image_type, init_lib_fn (libraries))
9504 #else
9505 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9506 define_image_type (image_type, 1)
9507 #endif /* HAVE_NTGUI */
9509 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
9510 doc: /* Initialize image library implementing image type TYPE.
9511 Return non-nil if TYPE is a supported image type.
9513 Image types pbm and xbm are prebuilt; other types are loaded here.
9514 Libraries to load are specified in alist LIBRARIES (usually, the value
9515 of `image-library-alist', which see). */)
9516 (type, libraries)
9517 Lisp_Object type, libraries;
9519 Lisp_Object tested;
9521 /* Don't try to reload the library. */
9522 tested = Fassq (type, Vimage_type_cache);
9523 if (CONSP (tested))
9524 return XCDR (tested);
9526 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
9527 if (EQ (type, Qxpm))
9528 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
9529 #endif
9531 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9532 if (EQ (type, Qjpeg))
9533 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
9534 #endif
9536 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9537 if (EQ (type, Qtiff))
9538 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
9539 #endif
9541 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9542 if (EQ (type, Qgif))
9543 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
9544 #endif
9546 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9547 if (EQ (type, Qpng))
9548 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
9549 #endif
9551 #if defined (HAVE_RSVG)
9552 if (EQ (type, Qsvg))
9553 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
9554 #endif
9556 #ifdef HAVE_GHOSTSCRIPT
9557 if (EQ (type, Qpostscript))
9558 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
9559 #endif
9561 /* If the type is not recognized, avoid testing it ever again. */
9562 CACHE_IMAGE_TYPE (type, Qnil);
9563 return Qnil;
9566 void
9567 syms_of_image ()
9569 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
9571 /* Initialize this only once, since that's what we do with Vimage_types
9572 and they are supposed to be in sync. Initializing here gives correct
9573 operation on GNU/Linux of calling dump-emacs after loading some images. */
9574 image_types = NULL;
9576 /* Must be defined now becase we're going to update it below, while
9577 defining the supported image types. */
9578 DEFVAR_LISP ("image-types", &Vimage_types,
9579 doc: /* List of potentially supported image types.
9580 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9581 To check whether it is really supported, use `image-type-available-p'. */);
9582 Vimage_types = Qnil;
9584 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
9585 doc: /* Alist of image types vs external libraries needed to display them.
9587 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9588 representing a supported image type, and the rest are strings giving
9589 alternate filenames for the corresponding external libraries.
9591 Emacs tries to load the libraries in the order they appear on the
9592 list; if none is loaded, the running session of Emacs won't
9593 support the image type. Types 'pbm and 'xbm don't need to be
9594 listed; they are always supported. */);
9595 Vimage_library_alist = Qnil;
9596 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
9598 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
9599 doc: /* Maximum size of images.
9600 Emacs will not load an image into memory if its pixel width or
9601 pixel height exceeds this limit.
9603 If the value is an integer, it directly specifies the maximum
9604 image height and width, measured in pixels. If it is a floating
9605 point number, it specifies the maximum image height and width
9606 as a ratio to the frame height and width. If the value is
9607 non-numeric, there is no explicit limit on the size of images. */);
9608 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
9610 Vimage_type_cache = Qnil;
9611 staticpro (&Vimage_type_cache);
9613 Qpbm = intern ("pbm");
9614 staticpro (&Qpbm);
9615 ADD_IMAGE_TYPE (Qpbm);
9617 Qxbm = intern ("xbm");
9618 staticpro (&Qxbm);
9619 ADD_IMAGE_TYPE (Qxbm);
9621 define_image_type (&xbm_type, 1);
9622 define_image_type (&pbm_type, 1);
9624 Qcount = intern ("count");
9625 staticpro (&Qcount);
9627 QCascent = intern (":ascent");
9628 staticpro (&QCascent);
9629 QCmargin = intern (":margin");
9630 staticpro (&QCmargin);
9631 QCrelief = intern (":relief");
9632 staticpro (&QCrelief);
9633 QCconversion = intern (":conversion");
9634 staticpro (&QCconversion);
9635 QCcolor_symbols = intern (":color-symbols");
9636 staticpro (&QCcolor_symbols);
9637 QCheuristic_mask = intern (":heuristic-mask");
9638 staticpro (&QCheuristic_mask);
9639 QCindex = intern (":index");
9640 staticpro (&QCindex);
9641 QCmatrix = intern (":matrix");
9642 staticpro (&QCmatrix);
9643 QCcolor_adjustment = intern (":color-adjustment");
9644 staticpro (&QCcolor_adjustment);
9645 QCmask = intern (":mask");
9646 staticpro (&QCmask);
9648 Qlaplace = intern ("laplace");
9649 staticpro (&Qlaplace);
9650 Qemboss = intern ("emboss");
9651 staticpro (&Qemboss);
9652 Qedge_detection = intern ("edge-detection");
9653 staticpro (&Qedge_detection);
9654 Qheuristic = intern ("heuristic");
9655 staticpro (&Qheuristic);
9657 Qpostscript = intern ("postscript");
9658 staticpro (&Qpostscript);
9659 #ifdef HAVE_GHOSTSCRIPT
9660 ADD_IMAGE_TYPE (Qpostscript);
9661 QCloader = intern (":loader");
9662 staticpro (&QCloader);
9663 QCbounding_box = intern (":bounding-box");
9664 staticpro (&QCbounding_box);
9665 QCpt_width = intern (":pt-width");
9666 staticpro (&QCpt_width);
9667 QCpt_height = intern (":pt-height");
9668 staticpro (&QCpt_height);
9669 #endif /* HAVE_GHOSTSCRIPT */
9671 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
9672 Qxpm = intern ("xpm");
9673 staticpro (&Qxpm);
9674 ADD_IMAGE_TYPE (Qxpm);
9675 #endif
9677 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9678 Qjpeg = intern ("jpeg");
9679 staticpro (&Qjpeg);
9680 ADD_IMAGE_TYPE (Qjpeg);
9681 #endif
9683 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9684 Qtiff = intern ("tiff");
9685 staticpro (&Qtiff);
9686 ADD_IMAGE_TYPE (Qtiff);
9687 #endif
9689 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9690 Qgif = intern ("gif");
9691 staticpro (&Qgif);
9692 ADD_IMAGE_TYPE (Qgif);
9693 #endif
9695 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9696 Qpng = intern ("png");
9697 staticpro (&Qpng);
9698 ADD_IMAGE_TYPE (Qpng);
9699 #endif
9701 #if defined (HAVE_RSVG)
9702 Qsvg = intern ("svg");
9703 staticpro (&Qsvg);
9704 ADD_IMAGE_TYPE (Qsvg);
9705 #ifdef HAVE_NTGUI
9706 Qgdk_pixbuf = intern ("gdk-pixbuf");
9707 staticpro (&Qgdk_pixbuf);
9708 Qglib = intern ("glib");
9709 staticpro (&Qglib);
9710 #endif /* HAVE_NTGUI */
9711 #endif /* HAVE_RSVG */
9713 defsubr (&Sinit_image_library);
9714 defsubr (&Sclear_image_cache);
9715 defsubr (&Simage_refresh);
9716 defsubr (&Simage_size);
9717 defsubr (&Simage_mask_p);
9718 defsubr (&Simage_extension_data);
9720 #if GLYPH_DEBUG
9721 defsubr (&Simagep);
9722 defsubr (&Slookup_image);
9723 #endif
9725 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
9726 doc: /* Non-nil means always draw a cross over disabled images.
9727 Disabled images are those having a `:conversion disabled' property.
9728 A cross is always drawn on black & white displays. */);
9729 cross_disabled_images = 0;
9731 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
9732 doc: /* List of directories to search for window system bitmap files. */);
9733 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
9735 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
9736 doc: /* Time after which cached images are removed from the cache.
9737 When an image has not been displayed this many seconds, remove it
9738 from the image cache. Value must be an integer or nil with nil
9739 meaning don't clear the cache. */);
9740 Vimage_cache_eviction_delay = make_number (30 * 60);
9743 void
9744 init_image ()
9748 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9749 (do not change this comment) */