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/>. */
30 /* This makes the fields of a Display accessible, in Xlib header files. */
32 #define XLIB_ILLEGAL_ACCESS
37 #include "dispextern.h"
38 #include "blockinput.h"
41 #include "character.h"
43 #include "termhooks.h"
48 #include <sys/types.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 */
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)
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 */
90 #include <sys/param.h>
92 #if TARGET_API_MAC_CARBON
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 */
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)
115 #define RGB_PIXEL_COLOR unsigned long
118 #define PIX_MASK_DRAW 255
119 #define PIX_MASK_RETAIN 0
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)
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)
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)
146 #define RGB_PIXEL_COLOR unsigned long
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) ns_display_list->n_planes
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
,
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
));
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. */
191 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
192 Display
*display
; /* not used */
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
201 xassert (x
== 0 && y
== 0);
204 SetRect (&ri
, 0, 0, width
, height
);
205 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
207 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
210 LockPixels (GetGWorldPixMap (pixmap
));
217 XPutPixel (ximage
, x
, y
, pixel
)
223 if (ximage
->bits_per_pixel
== 32)
224 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
226 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
228 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
229 short depth
= GetPixDepth (pixmap
);
231 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
234 char *base_addr
= GetPixBaseAddr (pixmap
);
235 short row_bytes
= GetPixRowBytes (pixmap
);
237 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
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);
249 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
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
);
272 XGetPixel (ximage
, x
, y
)
277 if (ximage
->bits_per_pixel
== 32)
278 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
280 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
282 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
283 short depth
= GetPixDepth (pixmap
);
285 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
288 char *base_addr
= GetPixBaseAddr (pixmap
);
289 short row_bytes
= GetPixRowBytes (pixmap
);
291 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
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
;
303 return PIX_MASK_RETAIN
;
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);
326 #if !USE_MAC_IMAGE_IO
327 UnlockPixels (GetGWorldPixMap (ximg
));
334 mac_data_provider_release_data (info
, data
, size
)
339 xfree ((void *)data
);
344 mac_create_cg_image_from_image (f
, img
)
349 XImagePtr ximg
= img
->pixmap
;
350 CGDataProviderRef provider
;
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
;
376 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
377 ximg
->bytes_per_line
* ximg
->height
,
378 mac_data_provider_release_data
);
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
387 , provider
, NULL
, 0, kCGRenderingIntentDefault
);
388 CGDataProviderRelease (provider
);
394 CGImageRef result
= NULL
;
401 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
402 img
->width
, img
->height
, 1);
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
);
414 SetGWorld (old_port
, old_gdh
);
419 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
420 GetGWorldPixMap (mask
), &result
);
421 if (mask
!= img
->mask
)
422 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
429 #endif /* USE_CG_DRAWING */
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
);
443 /* use with imgs created by ns_image_for_XPM */
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 */
453 XPutPixel (XImagePtr ximage
, int x
, int y
, unsigned long pixel
)
455 ns_put_pixel(ximage
, x
, y
, pixel
);
460 /* Functions to access the contents of a bitmap, given an id. */
463 x_bitmap_height (f
, id
)
467 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
471 x_bitmap_width (f
, 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
)
484 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
488 #ifdef HAVE_X_WINDOWS
490 x_bitmap_mask (f
, id
)
494 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
498 /* Allocate a new bitmap record. Returns index of new record. */
501 x_allocate_bitmap_record (f
)
504 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
507 if (dpyinfo
->bitmaps
== NULL
)
509 dpyinfo
->bitmaps_size
= 10;
511 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
512 dpyinfo
->bitmaps_last
= 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)
523 dpyinfo
->bitmaps_size
*= 2;
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. */
533 x_reference_bitmap (f
, 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
)
546 unsigned int width
, height
;
548 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
551 #ifdef HAVE_X_WINDOWS
553 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
554 bits
, width
, height
);
557 #endif /* HAVE_X_WINDOWS */
561 bitmap
= CreateBitmap (width
, height
,
562 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
563 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
567 #endif /* HAVE_NTGUI */
570 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
576 void *bitmap
= ns_image_from_XBM(bits
, width
, height
);
581 id
= x_allocate_bitmap_record (f
);
583 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
584 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
588 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
589 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
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 */
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 */
612 /* Create bitmap from file FILE for frame F. */
615 x_create_bitmap_from_file (f
, file
)
619 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
622 return -1; /* MAC_TODO : bitmap support */
626 return -1; /* W32_TODO : bitmap support */
627 #endif /* HAVE_NTGUI */
631 void *bitmap
= ns_image_from_file(file
);
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
));
648 #ifdef HAVE_X_WINDOWS
649 unsigned int width
, height
;
651 int xhot
, yhot
, result
, id
;
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
;
668 /* Search bitmap-file-path for the file, if appropriate. */
669 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
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
)
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
));
692 #endif /* HAVE_X_WINDOWS */
698 free_bitmap_record (dpyinfo
, bm
)
699 Display_Info
*dpyinfo
;
702 #ifdef HAVE_X_WINDOWS
703 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
705 XFreePixmap (dpyinfo
->display
, bm
->mask
);
706 #endif /* HAVE_X_WINDOWS */
709 DeleteObject (bm
->pixmap
);
710 #endif /* HAVE_NTGUI */
713 xfree (bm
->bitmap_data
); /* Added ++kfs */
714 bm
->bitmap_data
= NULL
;
718 ns_release_object(bm
->img
);
728 /* Remove reference to bitmap with id number ID. */
731 x_destroy_bitmap (f
, id
)
735 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
739 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
741 if (--bm
->refcount
== 0)
744 free_bitmap_record (dpyinfo
, bm
);
750 /* Free all the bitmaps for the display specified by DPYINFO. */
753 x_destroy_all_bitmaps (dpyinfo
)
754 Display_Info
*dpyinfo
;
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
,
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
,
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
)
793 XImagePtr ximg
, mask_img
;
794 unsigned long width
, height
;
797 unsigned long x
, y
, xp
, xm
, yp
, ym
;
800 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
805 pixmap
= x_bitmap_pixmap (f
, id
);
806 width
= x_bitmap_width (f
, id
);
807 height
= x_bitmap_height (f
, id
);
810 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
819 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
824 XDestroyImage (ximg
);
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);
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,
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
);
868 #endif /* HAVE_X_WINDOWS */
871 /***********************************************************************
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. */
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
;
911 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
913 /* Time in seconds after which images should be removed from the cache
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
*,
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. */
938 define_image_type (type
, loaded
)
939 struct image_type
*type
;
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
;
957 CACHE_IMAGE_TYPE (*type
->type
, 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
)
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
))
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
991 valid_image_p (object
)
1000 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
1001 if (EQ (XCAR (tem
), QCtype
))
1004 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
1006 struct image_type
*type
;
1007 type
= lookup_image_type (XCAR (tem
));
1009 valid_p
= type
->valid_p (object
);
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. */
1027 image_error (format
, arg1
, arg2
)
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
,
1044 IMAGE_STRING_OR_NIL_VALUE
,
1046 IMAGE_POSITIVE_INTEGER_VALUE
,
1047 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
1048 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
1050 IMAGE_INTEGER_VALUE
,
1051 IMAGE_FUNCTION_VALUE
,
1056 /* Structure used when parsing image specifications. */
1058 struct image_keyword
1060 /* Name of keyword. */
1063 /* The type of value allowed. */
1064 enum image_value_type type
;
1066 /* Non-zero means key must be present. */
1069 /* Used to recognize duplicate keywords in a property list. */
1072 /* The value that was found. */
1077 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
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. */
1089 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1091 struct image_keyword
*keywords
;
1101 plist
= XCDR (spec
);
1102 while (CONSP (plist
))
1104 Lisp_Object key
, value
;
1106 /* First element of a pair must be a symbol. */
1108 plist
= XCDR (plist
);
1112 /* There must follow a value. */
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)
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)
1134 /* Check type of value against allowed type. */
1135 switch (keywords
[i
].type
)
1137 case IMAGE_STRING_VALUE
:
1138 if (!STRINGP (value
))
1142 case IMAGE_STRING_OR_NIL_VALUE
:
1143 if (!STRINGP (value
) && !NILP (value
))
1147 case IMAGE_SYMBOL_VALUE
:
1148 if (!SYMBOLP (value
))
1152 case IMAGE_POSITIVE_INTEGER_VALUE
:
1153 if (!INTEGERP (value
) || XINT (value
) <= 0)
1157 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1158 if (INTEGERP (value
) && XINT (value
) >= 0)
1161 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1162 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1166 case IMAGE_ASCENT_VALUE
:
1167 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1169 else if (INTEGERP (value
)
1170 && XINT (value
) >= 0
1171 && XINT (value
) <= 100)
1175 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1176 if (!INTEGERP (value
) || XINT (value
) < 0)
1180 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1183 case IMAGE_FUNCTION_VALUE
:
1184 value
= indirect_function (value
);
1186 || COMPILEDP (value
)
1187 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1191 case IMAGE_NUMBER_VALUE
:
1192 if (!INTEGERP (value
) && !FLOATP (value
))
1196 case IMAGE_INTEGER_VALUE
:
1197 if (!INTEGERP (value
))
1201 case IMAGE_BOOL_VALUE
:
1202 if (!NILP (value
) && !EQ (value
, Qt
))
1211 if (EQ (key
, QCtype
) && !EQ (type
, value
))
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)
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. */
1229 image_spec_value (spec
, key
, found
)
1230 Lisp_Object spec
, key
;
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
))
1245 return XCAR (XCDR (tail
));
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
;
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
;
1276 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1277 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1279 size
= Fcons (make_number (width
), make_number (height
));
1282 error ("Invalid image specification");
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. */)
1293 Lisp_Object spec
, frame
;
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
);
1307 error ("Invalid image specification");
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. */)
1317 Lisp_Object spec
, frame
;
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
;
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
)
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
);
1362 img
->data
.lisp_val
= Qnil
;
1363 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1365 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1370 /* Free image IMG which was used on frame F, including its resources. */
1379 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1381 /* Remove IMG from the hash table of its cache. */
1383 img
->prev
->next
= img
->next
;
1385 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = 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
);
1398 /* Return 1 if the given widths and heights are valid for display;
1399 otherwise, return 0. */
1402 check_image_size (f
, width
, height
)
1409 if (width
<= 0 || height
<= 0)
1412 if (INTEGERP (Vmax_image_size
))
1413 w
= h
= XINT (Vmax_image_size
);
1414 else if (FLOATP (Vmax_image_size
))
1418 w
= FRAME_PIXEL_WIDTH (f
);
1419 h
= FRAME_PIXEL_HEIGHT (f
);
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
);
1429 return (width
<= w
&& height
<= h
);
1432 /* Prepare image IMG for display on frame F. Must be called before
1433 drawing an image. */
1436 prepare_image_for_display (f
, img
)
1442 /* We're about to display IMG, so set its timestamp to `now'. */
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
);
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
)
1472 struct glyph_slice
*slice
;
1477 if (slice
->height
== img
->height
)
1478 height
= img
->height
+ img
->vmargin
;
1479 else if (slice
->y
== 0)
1480 height
= slice
->height
+ img
->vmargin
;
1482 height
= slice
->height
;
1484 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1489 /* W32 specific version. Why?. ++kfs */
1490 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1491 - FONT_BASE (face
->font
)) / 2;
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 */
1503 ascent
= height
/ 2;
1506 ascent
= (int) (height
* img
->ascent
/ 100.0);
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
;
1521 unsigned long width
, height
;
1523 RGB_PIXEL_COLOR corner_pixels
[4], best
;
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);
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
)
1547 for (j
= n
= 0; j
< 4; ++j
)
1548 if (corner_pixels
[i
] == corner_pixels
[j
])
1552 best
= corner_pixels
[i
], best_count
= n
;
1558 /* Portability macros */
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)
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. */
1593 image_background (img
, f
, ximg
)
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
;
1604 #endif /* HAVE_NTGUI */
1609 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1610 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
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
);
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
)
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. */
1645 int free_mask
= !mask
;
1648 #endif /* HAVE_NTGUI */
1653 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1654 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
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
);
1667 Destroy_Image (mask
, prev
);
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,
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
,
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. */
1698 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
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
;
1708 if (img
->background_valid
)
1709 ns_free_indexed_color(img
->background
);
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
);
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
;
1742 /* Free X resources of image IMG which is used on frame F. */
1745 x_clear_image (f
, img
)
1750 x_clear_image_1 (f
, img
, 1, 1, 1);
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
1760 static unsigned long
1761 x_alloc_image_color (f
, img
, color_name
, dflt
)
1764 Lisp_Object color_name
;
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. */
1778 (unsigned long *) xrealloc (img
->colors
,
1779 img
->ncolors
* sizeof *img
->colors
);
1780 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1781 result
= color
.pixel
;
1791 /***********************************************************************
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
*
1805 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1808 bzero (c
, sizeof *c
);
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
);
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
)
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
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
))
1854 /* Search frame F for an image with spec SPEC, and free it. */
1857 uncache_image (f
, spec
)
1861 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1863 free_image (f
, img
);
1867 /* Free image cache of frame F. Be aware that X frames share images
1871 free_image_cache (f
)
1874 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
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
]);
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. */
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
)))
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. */
1918 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1920 struct image
*img
= c
->images
[i
];
1922 && (NILP (filter
) ? img
->timestamp
< old
1924 || !NILP (Fmember (filter
, img
->dependencies
)))))
1926 free_image (f
, img
);
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. */
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
;
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
,
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. */)
1976 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1977 clear_image_caches (filter
);
1979 clear_image_cache (check_x_frame (filter
), Qt
);
1985 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
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. */)
1993 Lisp_Object spec
, frame
;
1995 if (!valid_image_p (spec
))
1996 error ("Invalid image specification");
2001 FOR_EACH_FRAME (tail
, frame
)
2003 struct frame
*f
= XFRAME (frame
);
2004 if (FRAME_WINDOW_P (f
))
2005 uncache_image (f
, spec
);
2009 uncache_image (check_x_frame (frame
), spec
);
2015 /* Compute masks and transform image IMG on frame F, as specified
2016 by the image's specification, */
2019 postprocess_image (f
, img
)
2023 /* Manipulation of the image's mask. */
2026 Lisp_Object conversion
, spec
;
2031 /* `:heuristic-mask t'
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
2039 means remove a mask, if any. */
2041 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
2043 x_build_heuristic_mask (f
, img
, mask
);
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
)));
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
))
2074 else if (EQ (conversion
, Qemboss
))
2076 else if (CONSP (conversion
)
2077 && EQ (XCAR (conversion
), Qedge_detection
))
2080 tem
= XCDR (conversion
);
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
)
2098 struct image_cache
*c
;
2101 struct gcpro gcpro1
;
2104 /* F must be a window-system frame, and SPEC must be a valid image
2106 xassert (FRAME_WINDOW_P (f
));
2107 xassert (valid_image_p (spec
));
2109 c
= FRAME_IMAGE_CACHE (f
);
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
);
2122 /* If not found, create a new image and cache it. */
2125 extern Lisp_Object Qpostscript
;
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
)
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
);
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
);
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
);
2202 /* We're using IMG, so set its timestamp to `now'. */
2203 EMACS_GET_TIME (now
);
2204 img
->timestamp
= EMACS_SECS (now
);
2208 /* Value is the image id. */
2213 /* Cache image IMG in the image cache of frame F. */
2216 cache_image (f
, img
)
2220 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2223 /* Find a free slot in c->images. */
2224 for (i
= 0; i
< c
->used
; ++i
)
2225 if (c
->images
[i
] == NULL
)
2228 /* If no free slot found, maybe enlarge c->images. */
2229 if (i
== c
->used
&& c
->used
== c
->size
)
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. */
2242 /* Add IMG to the cache's hash table. */
2243 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2244 img
->next
= c
->buckets
[i
];
2246 img
->next
->prev
= img
;
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. */
2261 mark_object (img
->spec
);
2262 mark_object (img
->dependencies
);
2264 if (!NILP (img
->data
.lisp_val
))
2265 mark_object (img
->data
.lisp_val
);
2270 mark_image_cache (struct image_cache
*c
)
2275 for (i
= 0; i
< c
->used
; ++i
)
2277 mark_image (c
->images
[i
]);
2283 /***********************************************************************
2284 X / MAC / W32 support code
2285 ***********************************************************************/
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. */
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
);
2314 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2316 CHECK_STRING_CAR (dlls
);
2317 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
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. */
2343 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2345 int width
, height
, depth
;
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
);
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);
2363 image_error ("Unable to allocate X image", Qnil
, Qnil
);
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
);
2376 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2381 #endif /* HAVE_X_WINDOWS */
2385 BITMAPINFOHEADER
*header
;
2387 int scanline_width_bits
;
2389 int palette_colors
= 0;
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
);
2401 scanline_width_bits
= width
* depth
;
2402 remainder
= scanline_width_bits
% 32;
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. */
2410 palette_colors
= 1 << depth
- 1;
2412 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2415 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
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. */
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
);
2467 #endif /* HAVE_NTGUI */
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
)
2480 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2484 #if !USE_MAC_IMAGE_IO
2485 LockPixels (GetGWorldPixMap (*pixmap
));
2493 *pixmap
= ns_image_for_XPM(width
, height
, depth
);
2497 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil
, Qnil
);
2506 /* Destroy XImage XIMG. Free XIMG->data. */
2509 x_destroy_x_image (ximg
)
2512 xassert (interrupt_input_blocked
);
2515 #ifdef HAVE_X_WINDOWS
2518 XDestroyImage (ximg
);
2519 #endif /* HAVE_X_WINDOWS */
2521 /* Data will be freed by DestroyObject. */
2524 #endif /* HAVE_NTGUI */
2526 XDestroyImage (ximg
);
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. */
2539 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2545 #ifdef HAVE_X_WINDOWS
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 */
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
);
2560 #endif /* HAVE_NTGUI */
2563 xassert (ximg
== pixmap
);
2567 xassert (ximg
== pixmap
);
2568 ns_retain_object(ximg
);
2573 /***********************************************************************
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. */
2585 x_find_image_file (file
)
2588 Lisp_Object file_found
, search_path
;
2589 struct gcpro gcpro1
, gcpro2
;
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"),
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
);
2607 file_found
= ENCODE_FILE (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
)
2626 unsigned char *buf
= NULL
;
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
))
2655 /***********************************************************************
2656 MAC Image Load Functions
2657 ***********************************************************************/
2659 #if USE_MAC_IMAGE_IO
2661 image_load_image_io (f
, img
, 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
;
2672 CGImageRef image
= NULL
;
2673 int loop_count
= -1;
2674 double delay_time
= -1.0;
2676 XImagePtr ximg
= NULL
;
2677 CGContextRef context
;
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
);
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
))
2708 file
= x_find_image_file (specified_file
);
2709 if (!STRINGP (file
))
2711 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2714 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2717 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2718 kCFURLPOSIXPathStyle
, 0);
2722 source
= CGImageSourceCreateWithURL (url
, NULL
);
2729 CFDataRef data
= CFDataCreate (NULL
, SDATA (specified_data
),
2730 SBYTES (specified_data
));
2734 source
= CGImageSourceCreateWithData (data
, options
);
2738 CFRelease (options
);
2742 CFStringRef real_type
= CGImageSourceGetType (source
);
2744 if (real_type
&& UTTypeEqual (type
, real_type
))
2745 src_props
= CGImageSourceCopyProperties (source
, NULL
);
2750 count
= CGImageSourceGetCount (source
);
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
);
2762 image
= CGImageSourceCreateImageAtIndex (source
, ino
, NULL
);
2771 CFRelease (src_props
);
2774 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2779 CFBooleanRef boolean
;
2781 if (CFDictionaryGetValueIfPresent (props
, kCGImagePropertyHasAlpha
,
2782 (const void **) &boolean
))
2783 has_alpha_p
= CFBooleanGetValue (boolean
);
2786 CFDictionaryRef dict
;
2789 dict
= CFDictionaryGetValue (src_props
,
2790 kCGImagePropertyGIFDictionary
);
2792 && CFDictionaryGetValueIfPresent (dict
,
2793 kCGImagePropertyGIFLoopCount
,
2794 (const void **) &number
))
2795 CFNumberGetValue (number
, kCFNumberIntType
, &loop_count
);
2797 dict
= CFDictionaryGetValue (props
, kCGImagePropertyGIFDictionary
);
2799 && CFDictionaryGetValueIfPresent (dict
,
2800 kCGImagePropertyGIFDelayTime
,
2801 (const void **) &number
))
2802 CFNumberGetValue (number
, kCFNumberDoubleType
, &delay_time
);
2804 CFRelease (src_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
);
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
);
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
2836 Lisp_Object specified_bg
;
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). */
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. */
2875 img
->data
.lisp_val
= Fcons (make_number (0xf9),
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
));
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
);
2908 #else /* !USE_MAC_IMAGE_IO */
2909 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2912 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2916 find_image_fsspec (specified_file
, file
, fss
)
2917 Lisp_Object specified_file
, *file
;
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
);
2932 #if TARGET_API_MAC_CARBON
2933 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2935 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2937 AEDisposeDesc (&desc
);
2943 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2950 ComponentResult err
;
2951 GraphicsImportComponent gi
;
2954 ImageDescriptionHandle desc_handle
;
2955 short draw_all_pixels
;
2956 Lisp_Object specified_bg
;
2961 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2964 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2969 /* read from file system spec */
2970 err
= GraphicsImportSetDataFile (gi
, fss
);
2973 image_error ("Cannot set fsspec to graphics importer for '%s'",
2980 /* read from data handle */
2981 err
= GraphicsImportSetDataHandle (gi
, dh
);
2984 image_error ("Cannot set data handle to graphics importer for `%s'",
2989 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2990 if (err
!= noErr
|| desc_handle
== NULL
)
2992 image_error ("Error reading `%s'", img
->spec
, Qnil
);
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
);
3005 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
3007 /* Don't check the error code here. It may have an undocumented
3011 image_error ("Error reading `%s'", img
->spec
, Qnil
);
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
))
3030 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
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
);
3045 EraseRect (&(ximg
->portRect
));
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
);
3063 CloseComponent (gi
);
3068 /* Load an image using the QuickTime Graphics Importer.
3069 Note: The alpha channel does not work for PNG images. */
3071 image_load_quicktime (f
, img
, type
)
3076 Lisp_Object specified_file
;
3077 Lisp_Object specified_data
;
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 */
3089 err
= find_image_fsspec (specified_file
, &file
, &fss
);
3093 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3095 image_error ("Cannot open `%s'", file
, Qnil
);
3098 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
3102 /* Memory source! */
3106 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
3109 image_error ("Cannot allocate data handle for `%s'",
3113 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
3122 image_load_quartz2d (f
, img
, png_p
)
3127 Lisp_Object file
, specified_file
;
3128 Lisp_Object specified_data
, specified_bg
;
3129 struct gcpro gcpro1
;
3130 CGDataProviderRef source
;
3134 XImagePtr ximg
= NULL
;
3135 CGContextRef context
;
3138 /* Open the file. */
3139 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3140 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3145 if (NILP (specified_data
))
3150 file
= x_find_image_file (specified_file
);
3151 if (!STRINGP (file
))
3153 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3157 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
3158 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
3159 kCFURLPOSIXPathStyle
, 0);
3161 source
= CGDataProviderCreateWithURL (url
);
3165 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
3166 SBYTES (specified_data
), NULL
);
3168 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3170 image
= CGImageCreateWithPNGDataProvider (source
, NULL
, false,
3171 kCGRenderingIntentDefault
);
3174 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, false,
3175 kCGRenderingIntentDefault
);
3177 CGDataProviderRelease (source
);
3181 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
3184 width
= img
->width
= CGImageGetWidth (image
);
3185 height
= img
->height
= CGImageGetHeight (image
);
3187 if (!check_image_size (f
, width
, height
))
3189 CGImageRelease (image
);
3191 image_error ("Invalid image size", Qnil
, Qnil
);
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
);
3214 rectangle
= CGRectMake (0, 0, width
, height
);
3215 QDBeginCGContext (ximg
, &context
);
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
);
3238 #endif /* !USE_MAC_IMAGE_IO */
3243 /***********************************************************************
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
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
=
3309 /* Tokens returned from xbm_scan. */
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
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
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
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. */
3348 xbm_image_p (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
))
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
)
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
)
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
)
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
3391 /* Number of elements of the vector must be >= height. */
3392 if (XVECTOR (data
)->size
< height
)
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
];
3404 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
3407 else if (BOOL_VECTOR_P (elt
))
3409 if (XBOOL_VECTOR (elt
)->size
< width
)
3416 else if (STRINGP (data
))
3419 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
3422 else if (BOOL_VECTOR_P (data
))
3424 if (XBOOL_VECTOR (data
)->size
< width
* height
)
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. */
3442 xbm_scan (s
, end
, sval
, ival
)
3443 unsigned char **s
, *end
;
3451 /* Skip white space. */
3452 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3457 else if (isdigit (c
))
3459 int value
= 0, digit
;
3461 if (c
== '0' && *s
< end
)
3464 if (c
== 'x' || c
== 'X')
3471 else if (c
>= 'a' && c
<= 'f')
3472 digit
= c
- 'a' + 10;
3473 else if (c
>= 'A' && c
<= 'F')
3474 digit
= c
- 'A' + 10;
3477 value
= 16 * value
+ digit
;
3480 else if (isdigit (c
))
3484 && (c
= *(*s
)++, isdigit (c
)))
3485 value
= 8 * value
+ c
- '0';
3492 && (c
= *(*s
)++, isdigit (c
)))
3493 value
= 10 * value
+ c
- '0';
3501 else if (isalpha (c
) || c
== '_')
3505 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3512 else if (c
== '/' && **s
== '*')
3514 /* C-style comment. */
3516 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3530 /* Create a Windows bitmap from X bitmap data. */
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 */
3540 unsigned char *bits
, *p
;
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
++)
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
);
3564 convert_mono_to_color_image (f
, img
, foreground
, background
)
3567 COLORREF foreground
, background
;
3569 HDC hdc
, old_img_dc
, new_img_dc
;
3570 HGDIOBJ old_prev
, new_prev
;
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
,
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");
3596 img
->pixmap
= new_pixmap
;
3599 #define XBM_BIT_SHUFFLE(b) (~(b))
3603 #define XBM_BIT_SHUFFLE(b) (b)
3605 #endif /* HAVE_NTGUI */
3609 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
3613 RGB_PIXEL_COLOR fg
, bg
;
3614 int non_default_colors
;
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
);
3629 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3632 img
->width
, img
->height
,
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. */
3648 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3650 unsigned char *contents
, *end
;
3651 int *width
, *height
;
3652 unsigned char **data
;
3654 unsigned char *s
= contents
;
3655 char buffer
[BUFSIZ
];
3658 int bytes_per_line
, i
, nbytes
;
3664 LA1 = xbm_scan (&s, end, buffer, &value)
3666 #define expect(TOKEN) \
3667 if (LA1 != (TOKEN)) \
3672 #define expect_ident(IDENT) \
3673 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3678 *width
= *height
= -1;
3681 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3683 /* Parse defines for width, height and hot-spots. */
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)
3696 else if (strcmp (p
, "height") == 0)
3699 expect (XBM_TK_NUMBER
);
3702 if (!check_image_size (f
, *width
, *height
))
3704 else if (data
== NULL
)
3707 /* Parse bits. Must start with `static'. */
3708 expect_ident ("static");
3709 if (LA1
== XBM_TK_IDENT
)
3711 if (strcmp (buffer
, "unsigned") == 0)
3714 expect_ident ("char");
3716 else if (strcmp (buffer
, "short") == 0)
3720 if (*width
% 16 && *width
% 16 < 9)
3723 else if (strcmp (buffer
, "char") == 0)
3731 expect (XBM_TK_IDENT
);
3737 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3738 nbytes
= bytes_per_line
* *height
;
3739 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3743 for (i
= 0; i
< nbytes
; i
+= 2)
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
== '}')
3760 for (i
= 0; i
< nbytes
; ++i
)
3763 expect (XBM_TK_NUMBER
);
3765 *p
++ = XBM_BIT_SHUFFLE (val
);
3767 if (LA1
== ',' || LA1
== '}')
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
3797 xbm_load_image (f
, img
, contents
, end
)
3800 unsigned char *contents
, *end
;
3803 unsigned char *data
;
3806 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3809 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3810 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3811 int non_default_colors
= 0;
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
);
3820 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3821 non_default_colors
= 1;
3823 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
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
);
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
);
3846 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3852 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3859 return (STRINGP (data
)
3860 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3867 /* Fill image IMG which is used on frame F with pixmap data. Value is
3868 non-zero if successful. */
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
))
3885 unsigned char *contents
;
3887 struct gcpro gcpro1
;
3889 file
= x_find_image_file (file_name
);
3891 if (!STRINGP (file
))
3893 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3898 contents
= slurp_file (SDATA (file
), &size
);
3899 if (contents
== NULL
)
3901 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3906 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3911 struct image_keyword fmt
[XBM_LAST
];
3913 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3914 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3915 int non_default_colors
= 0;
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
);
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
,
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
,
3951 non_default_colors
= 1;
3954 if (in_memory_file_p
)
3955 success_p
= xbm_load_image (f
, img
, SDATA (data
),
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
];
3971 bcopy (SDATA (line
), p
, nbytes
);
3973 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3976 else if (STRINGP (data
))
3977 bits
= SDATA (data
);
3979 bits
= XBOOL_VECTOR (data
)->data
;
3985 /* Windows mono bitmaps are reversed compared with X. */
3986 invertedBits
= bits
;
3987 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3989 bits
= (char *) alloca(nbytes
);
3990 for (i
= 0; i
< nbytes
; i
++)
3991 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3994 /* Create the pixmap. */
3996 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3997 foreground
, background
,
3998 non_default_colors
);
4003 image_error ("Unable to create pixmap for XBM image `%s'",
4005 x_clear_image (f
, img
);
4015 /***********************************************************************
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 */
4029 /* Indicate to xpm.h that we don't have Xlib. */
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"
4042 #undef PIXEL_ALREADY_TYPEDEFED
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. */
4053 /* Indices of image specification fields in xpm_format, below. */
4055 enum xpm_keyword_index
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
=
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
4107 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
4108 #define ALLOC_XPM_COLORS
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 *,
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). */
4138 /* The hash table used for the color cache, and its bucket vector
4141 #define XPM_COLOR_CACHE_BUCKETS 1001
4142 struct xpm_cached_color
**xpm_color_cache
;
4144 /* Initialize the color cache. */
4147 xpm_init_color_cache (f
, attrs
)
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
)
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
,
4167 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
4172 /* Free the color cache. */
4175 xpm_free_color_cache ()
4177 struct xpm_cached_color
*p
, *next
;
4180 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
4181 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
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
4196 xpm_color_bucket (color_name
)
4202 for (s
= color_name
; *s
; ++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
4212 static struct xpm_cached_color
*
4213 xpm_cache_color (f
, color_name
, color
, bucket
)
4220 struct xpm_cached_color
*p
;
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
);
4229 p
->next
= xpm_color_cache
[bucket
];
4230 xpm_color_cache
[bucket
] = 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. */
4240 xpm_lookup_color (f
, color_name
, 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)
4254 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4257 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
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
);
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
4280 xpm_alloc_color (dpy
, cmap
, color_name
, color
, 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. */
4296 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
4306 #endif /* ALLOC_XPM_COLORS */
4311 /* XPM library details. */
4313 DEF_IMGLIB_FN (XpmFreeAttributes
);
4314 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
4315 DEF_IMGLIB_FN (XpmReadFileToImage
);
4316 DEF_IMGLIB_FN (XImageFree
);
4319 init_xpm_functions (Lisp_Object libraries
)
4323 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
4326 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
4327 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
4328 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
4329 LOAD_IMGLIB_FN (library
, XImageFree
);
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
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
);
4348 || !STRINGP (XCAR (sym
))
4349 || !STRINGP (XCDR (sym
)))
4351 color_symbols
= XCDR (color_symbols
);
4354 return NILP (color_symbols
);
4358 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4361 xpm_image_p (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
)
4383 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
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
);
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
);
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. */
4429 XpmAttributes attrs
;
4430 Lisp_Object specified_file
, color_symbols
;
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
);
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
))
4472 XpmColorSymbol
*xpm_syms
;
4475 attrs
.valuemask
|= XpmColorSymbols
;
4477 /* Count number of symbols. */
4478 attrs
.numsymbols
= 0;
4479 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
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;
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
);
4508 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
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
);
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
,
4534 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4535 SDATA (file
), &img
->pixmap
, &img
->mask
,
4537 #endif /* HAVE_NTGUI */
4541 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
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
,
4549 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4551 &img
->pixmap
, &img
->mask
,
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 */
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. */
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
);
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
]);
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. */
4611 fn_XpmFreeAttributes (&attrs
);
4613 XpmFreeAttributes (&attrs
);
4614 #endif /* HAVE_NTGUI */
4620 #endif /* HAVE_NTGUI */
4625 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4628 case XpmFileInvalid
:
4629 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4633 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4636 case XpmColorFailed
:
4637 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4641 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4646 #ifdef ALLOC_XPM_COLORS
4647 xpm_free_color_cache ();
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 *,
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 *,
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. */
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. */
4696 xpm_scan (s
, end
, beg
, len
)
4697 const unsigned char **s
, *end
, **beg
;
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
== '+')
4714 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4717 return XPM_TK_IDENT
;
4722 while (*s
< end
&& **s
!= '"')
4727 return XPM_TK_STRING
;
4731 if (*s
< end
&& **s
== '*')
4733 /* C-style comment. */
4737 while (*s
< end
&& *(*s
)++ != '*')
4740 while (*s
< end
&& **s
!= '/');
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. */
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
);
4772 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4773 Lisp_Object color_table
;
4774 const unsigned char *chars_start
;
4778 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4782 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4783 Lisp_Object color_table
;
4784 const unsigned char *chars_start
;
4787 return XVECTOR (color_table
)->contents
[*chars_start
];
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
),
4804 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4805 Lisp_Object color_table
;
4806 const unsigned char *chars_start
;
4810 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
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
);
4819 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4820 Lisp_Object color_table
;
4821 const unsigned char *chars_start
;
4824 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4825 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4828 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4831 enum xpm_color_key
{
4839 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4842 xpm_str_to_color_key (s
)
4848 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4850 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4856 xpm_load_image (f
, img
, contents
, end
)
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
;
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
;
4873 LA1 = xpm_scan (&s, end, &beg, &len)
4875 #define expect(TOKEN) \
4876 if (LA1 != (TOKEN)) \
4881 #define expect_ident(IDENT) \
4882 if (LA1 == XPM_TK_IDENT \
4883 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4888 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4892 expect_ident ("static");
4893 expect_ident ("char");
4895 expect (XPM_TK_IDENT
);
4900 expect (XPM_TK_STRING
);
4903 memcpy (buffer
, beg
, len
);
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)
4911 if (!check_image_size (f
, width
, height
))
4913 image_error ("Invalid image size", Qnil
, Qnil
);
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
);
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
,
4933 color_table
= xpm_make_color_table_h (&put_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
;
4943 expect (XPM_TK_STRING
);
4944 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4946 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4947 buffer
[len
- chars_per_pixel
] = '\0';
4949 str
= strtok (buffer
, " \t");
4952 key
= xpm_str_to_color_key (str
);
4957 color
= strtok (NULL
, " \t");
4961 while ((str
= strtok (NULL
, " \t")) != NULL
)
4963 next_key
= xpm_str_to_color_key (str
);
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
)
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)
4992 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4994 color_val
= make_number (cdef
.pixel
);
4997 if (NILP (color_val
) && max_key
> 0)
4999 if (xstrcasecmp (max_color
, "None") == 0)
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
);
5010 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5011 &ximg
, &img
->pixmap
)
5013 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
5014 &mask_img
, &img
->mask
)
5018 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
5022 for (y
= 0; y
< height
; y
++)
5024 expect (XPM_TK_STRING
);
5026 if (len
< width
* chars_per_pixel
)
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
)));
5037 XPutPixel (mask_img
, x
, y
,
5038 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
5039 : (have_mask
= 1, PIX_MASK_RETAIN
)));
5041 if (EQ(color_val
, Qt
))
5042 ns_set_alpha(ximg
, x
, y
, 0);
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
);
5061 /* Fill in the background_transparent field while we have the
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
);
5070 x_destroy_x_image (mask_img
);
5071 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5072 img
->mask
= NO_PIXMAP
;
5078 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
5080 x_destroy_x_image (ximg
);
5081 x_destroy_x_image (mask_img
);
5082 x_clear_image (f
, img
);
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
))
5103 unsigned char *contents
;
5105 struct gcpro gcpro1
;
5107 file
= x_find_image_file (file_name
);
5109 if (!STRINGP (file
))
5111 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
5116 contents
= slurp_file (SDATA (file
), &size
);
5117 if (contents
== NULL
)
5119 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
5124 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
5132 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5133 success_p
= xpm_load_image (f
, img
, SDATA (data
),
5134 SDATA (data
) + SBYTES (data
));
5140 #endif /* MAC_OS || (HAVE_NS && !HAVE_XPM) */
5144 /***********************************************************************
5146 ***********************************************************************/
5148 #ifdef COLOR_TABLE_SUPPORT
5150 /* An entry in the color table mapping an RGB color to a pixel color. */
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. */
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. */
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. */
5195 struct ct_color
*p
, *next
;
5197 for (i
= 0; i
< CT_SIZE
; ++i
)
5198 for (p
= ct_table
[i
]; p
; p
= next
)
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
)
5219 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
5220 int i
= hash
% CT_SIZE
;
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. */
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
)
5260 #ifdef HAVE_X_WINDOWS
5269 cmap
= FRAME_X_COLORMAP (f
);
5270 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5273 ++ct_colors_allocated
;
5274 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5278 p
->pixel
= color
.pixel
;
5279 p
->next
= ct_table
[i
];
5283 return FRAME_FOREGROUND_PIXEL (f
);
5288 color
= PALETTERGB (r
, g
, b
);
5290 color
= RGB_TO_ULONG (r
, g
, b
);
5291 #endif /* HAVE_NTGUI */
5292 ++ct_colors_allocated
;
5293 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5298 p
->next
= ct_table
[i
];
5300 #endif /* HAVE_X_WINDOWS */
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
)
5314 unsigned long pixel
;
5316 int i
= pixel
% CT_SIZE
;
5319 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5320 if (p
->pixel
== pixel
)
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
);
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
);
5341 #endif /* HAVE_X_WINDOWS */
5345 ++ct_colors_allocated
;
5347 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5352 p
->next
= ct_table
[i
];
5356 return FRAME_FOREGROUND_PIXEL (f
);
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
)
5371 unsigned long *colors
;
5373 if (ct_colors_allocated
== 0)
5380 colors
= (unsigned long *) xmalloc (ct_colors_allocated
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
;
5392 #else /* COLOR_TABLE_SUPPORT */
5394 static unsigned long
5395 lookup_rgb_color (f
, r
, g
, b
)
5399 unsigned long pixel
;
5402 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5403 gamma_correct (f
, &pixel
);
5407 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
5408 #endif /* HAVE_NTGUI */
5411 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5412 #endif /* HAVE_NS */
5420 #endif /* COLOR_TABLE_SUPPORT */
5423 /***********************************************************************
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));
5432 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
5433 #endif /* HAVE_NTGUI */
5435 /* Non-zero means draw a cross on images having `:conversion
5438 int cross_disabled_images
;
5440 /* Edge detection matrices for different edge-detection
5443 static int emboss_matrix
[9] = {
5445 2, -1, 0, /* y - 1 */
5447 0, 1, -2 /* y + 1 */
5450 static int laplace_matrix
[9] = {
5452 1, 0, 0, /* y - 1 */
5454 0, 0, -1 /* y + 1 */
5457 /* Value is the intensity of the color whose red/green/blue values
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. */
5470 x_to_xcolors (f
, img
, rgb_p
)
5477 XImagePtr_or_DC ximg
;
5481 #endif /* HAVE_NTGUI */
5483 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
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
);
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. */
5500 for (y
= 0; y
< img
->height
; ++y
)
5504 #ifdef HAVE_X_WINDOWS
5505 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5506 p
->pixel
= XGetPixel (ximg
, x
, y
);
5508 x_query_colors (f
, row
, img
->width
);
5512 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5514 /* W32_TODO: palette support needed here? */
5515 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
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
);
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
);
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. */
5545 XPutPixel (ximg
, x
, y
, 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. */
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. */
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);
5580 *pixel
= *pixel
& ~(1 << x
% 8);
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. */
5593 x_from_xcolors (f
, img
, colors
)
5599 XImagePtr oimg
= NULL
;
5600 Pixmap pixmap
= NULL
;
5603 init_color_table ();
5605 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
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
);
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
5638 x_detect_edges (f
, img
, matrix
, color_adjust
)
5641 int matrix
[9], color_adjust
;
5643 XColor
*colors
= x_to_xcolors (f
, img
, 1);
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
;
5679 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5680 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++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
);
5697 x_from_xcolors (f
, img
, new);
5703 /* Perform the pre-defined `emboss' edge-detection on 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. */
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
5740 x_edge_detection (f
, img
, matrix
, color_adjust
)
5743 Lisp_Object matrix
, color_adjust
;
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. */
5772 x_disable_image (f
, img
)
5776 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5778 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5780 int n_planes
= dpyinfo
->n_planes
;
5781 #endif /* HAVE_NTGUI */
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);
5790 const int h
= 15000;
5791 const int l
= 30000;
5793 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
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
5807 if (n_planes
< 2 || cross_disabled_images
)
5810 Display
*dpy
= FRAME_X_DISPLAY (f
);
5813 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5816 #define MaskForeground(f) PIX_MASK_DRAW
5818 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
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,
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,
5839 #endif /* !HAVE_NS */
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);
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
);
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. */
5880 x_build_heuristic_mask (f
, img
, how
)
5885 XImagePtr_or_DC ximg
;
5893 #endif /* HAVE_NTGUI */
5894 int x
, y
, rc
, use_img_background
;
5895 unsigned long bg
= 0;
5899 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5900 img
->mask
= NO_PIXMAP
;
5901 img
->background_transparent_valid
= 0;
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
);
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
,
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;
5938 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5940 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5944 if (i
== 3 && NILP (how
))
5946 char color_name
[30];
5947 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
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. */
5963 for (y
= 0; y
< img
->height
; ++y
)
5964 for (x
= 0; x
< img
->width
; ++x
)
5966 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5967 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5969 if (XGetPixel (ximg
, x
, y
) == bg
)
5970 ns_set_alpha(ximg
, x
, y
, 0);
5971 #endif /* 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 */
5981 for (y
= 0; y
< img
->height
; ++y
)
5982 for (x
= 0; x
< img
->width
; ++x
)
5984 COLORREF p
= GetPixel (ximg
, x
, y
);
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
,
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 */
5998 #endif /* HAVE_NTGUI */
6000 Destroy_Image (ximg
, prev
);
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. */
6018 /* Indices of image specification fields in gs_format, below. */
6020 enum pbm_keyword_index
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
=
6066 /* Return non-zero if OBJECT is a valid PBM image specification. */
6069 pbm_image_p (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
))
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
6089 pbm_scan_number (s
, end
)
6090 unsigned char **s
, *end
;
6092 int c
= 0, val
= -1;
6096 /* Skip white-space. */
6097 while (*s
< end
&& (c
= *(*s
)++, isspace (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. */
6110 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
6111 val
= 10 * val
+ c
- '0';
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. */
6130 pbm_read_file (file
, size
)
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
))
6160 #endif /* HAVE_NTGUI */
6162 /* Load PBM image IMG for use on frame F. */
6170 int width
, height
, max_color_idx
= 0;
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
;
6179 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
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
);
6193 contents
= slurp_file (SDATA (file
), &size
);
6194 if (contents
== NULL
)
6196 image_error ("Error reading `%s'", file
, Qnil
);
6202 end
= contents
+ size
;
6207 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
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
);
6225 raw_p
= 0, type
= PBM_MONO
;
6229 raw_p
= 0, type
= PBM_GRAY
;
6233 raw_p
= 0, type
= PBM_COLOR
;
6237 raw_p
= 1, type
= PBM_MONO
;
6241 raw_p
= 1, type
= PBM_GRAY
;
6245 raw_p
= 1, type
= PBM_COLOR
;
6249 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
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
);
6268 if (!check_image_size (f
, width
, height
))
6270 image_error ("Invalid image size", Qnil
, Qnil
);
6274 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
6275 &ximg
, &img
->pixmap
))
6278 /* Initialize the color hash table. */
6279 init_color_table ();
6281 if (type
== PBM_MONO
)
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
)
6313 x_destroy_x_image (ximg
);
6314 x_clear_image (f
, img
);
6315 image_error ("Invalid image size in image `%s'",
6325 g
= pbm_scan_number (&p
, end
);
6327 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
6332 int expected_size
= height
* width
;
6333 if (max_color_idx
> 255)
6335 if (type
== PBM_COLOR
)
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'",
6347 for (y
= 0; y
< height
; ++y
)
6348 for (x
= 0; x
< width
; ++x
)
6352 if (type
== PBM_GRAY
&& raw_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
);
6363 if (max_color_idx
> 255)
6366 if (max_color_idx
> 255)
6369 if (max_color_idx
> 255)
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'",
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 */
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
6418 img->height = height; */
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. */
6441 /* Indices of image specification fields in png_format, below. */
6443 enum png_keyword_index
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
=
6486 /* Return non-zero if OBJECT is a valid PNG image specification. */
6489 png_image_p (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
))
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 */
6507 #if defined HAVE_LIBPNG_PNG_H
6508 # include <libpng/png.h>
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
);
6539 init_png_functions (Lisp_Object libraries
)
6543 /* Try loading libpng under probable names. */
6544 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
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
);
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
6600 my_png_error (png_ptr
, msg
)
6601 png_struct
*png_ptr
;
6604 xassert (png_ptr
!= NULL
);
6605 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6606 longjmp (png_ptr
->jmpbuf
, 1);
6611 my_png_warning (png_ptr
, msg
)
6612 png_struct
*png_ptr
;
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. */
6634 png_read_from_memory (png_ptr
, data
, length
)
6635 png_structp png_ptr
;
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. */
6655 png_read_from_file (png_ptr
, data
, length
)
6656 png_structp png_ptr
;
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
6675 Lisp_Object file
, specified_file
;
6676 Lisp_Object specified_data
;
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
;
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
;
6689 png_uint_32 row_bytes
;
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
);
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
);
6709 /* Open the image file. */
6710 fp
= fopen (SDATA (file
), "rb");
6713 image_error ("Cannot open image file `%s'", file
, Qnil
);
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
);
6730 /* Read from memory. */
6731 tbr
.bytes
= SDATA (specified_data
);
6732 tbr
.len
= SBYTES (specified_data
);
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
);
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
,
6755 if (fp
) fclose (fp
);
6760 /* Casting return value avoids a GCC warning on W32. */
6761 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6764 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6765 if (fp
) fclose (fp
);
6770 /* Casting return value avoids a GCC warning on W32. */
6771 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6774 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6775 if (fp
) fclose (fp
);
6780 /* Set error jump-back. We come back here when the PNG library
6781 detects an error. */
6782 if (setjmp (png_ptr
->jmpbuf
))
6786 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6789 if (fp
) fclose (fp
);
6794 /* Read image info. */
6795 if (!NILP (specified_data
))
6796 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
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
))
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
))
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
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. */
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 */
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);
6862 /* We use the current frame background, ignoring any default
6863 background color set by the image. */
6864 #ifdef HAVE_X_WINDOWS
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 */
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
);
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 */
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
);
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
);
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
);
6937 /* Create the X image and pixmap. */
6938 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6942 /* Create an image and pixmap serving as mask if the PNG image
6943 contains an alpha channel. */
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
;
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
)
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. */
6989 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6995 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6996 /* Set IMG's background color from the PNG image, unless the user
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 */
7014 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
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. */
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
);
7044 #else /* HAVE_PNG */
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);
7057 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
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 /***********************************************************************
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. */
7090 /* Indices of image specification fields in gs_format, below. */
7092 enum jpeg_keyword_index
7101 JPEG_HEURISTIC_MASK
,
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
=
7135 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7138 jpeg_image_p (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
))
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 */
7156 /* Work around a warning about HAVE_STDLIB_H being redefined in
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. */
7169 #include <jpeglib.h>
7173 #ifdef HAVE_STLIB_H_1
7174 #define HAVE_STDLIB_H 1
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
);
7190 init_jpeg_functions (Lisp_Object libraries
)
7194 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
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
);
7208 /* Wrapper since we can't directly assign the function pointer
7209 to another function pointer that was declared more completely easily. */
7211 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
7212 j_decompress_ptr cinfo
;
7215 return fn_jpeg_resync_to_restart (cinfo
, desired
);
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
;
7239 my_error_exit (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. */
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. */
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];
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;
7290 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7291 is the JPEG data source manager. */
7294 our_memory_skip_input_data (cinfo
, num_bytes
)
7295 j_decompress_ptr cinfo
;
7298 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->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. */
7316 jpeg_memory_src (cinfo
, data
, len
)
7317 j_decompress_ptr cinfo
;
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
;
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 *. */
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
;
7372 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
7374 src
->mgr
.bytes_in_buffer
= bytes
;
7377 WARNMS (cinfo
, JWRN_JPEG_EOF
);
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
;
7390 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7391 is the JPEG data source manager. */
7394 our_stdio_skip_input_data (cinfo
, num_bytes
)
7395 j_decompress_ptr cinfo
;
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
;
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. */
7426 jpeg_file_src (cinfo
, fp
)
7427 j_decompress_ptr cinfo
;
7430 struct jpeg_stdio_mgr
*src
;
7432 if (cinfo
->src
!= NULL
)
7433 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
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
);
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. */
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
;
7472 int row_stride
, x
, y
;
7473 XImagePtr ximg
= NULL
;
7475 unsigned long *colors
;
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
);
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
);
7495 fp
= fopen (SDATA (file
), "rb");
7498 image_error ("Cannot open `%s'", file
, Qnil
);
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)
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. */
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
);
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
);
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. */
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;
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
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 */
7606 row_stride
= width
* cinfo
.output_components
;
7607 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
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
]]);
7617 fn_jpeg_finish_decompress (&cinfo
);
7618 fn_jpeg_destroy_decompress (&cinfo
);
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
);
7634 #else /* HAVE_JPEG */
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);
7647 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
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 /***********************************************************************
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. */
7679 /* Indices of image specification fields in tiff_format, below. */
7681 enum tiff_keyword_index
7690 TIFF_HEURISTIC_MASK
,
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
=
7724 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7727 tiff_image_p (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
))
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 */
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
);
7758 init_tiff_functions (Lisp_Object libraries
)
7762 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
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
);
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.
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
7799 unsigned char *bytes
;
7806 tiff_read_from_memory (data
, buf
, size
)
7811 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7813 if (size
> src
->len
- src
->index
)
7815 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7821 tiff_write_from_memory (data
, buf
, size
)
7830 tiff_seek_in_memory (data
, off
, whence
)
7835 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7840 case SEEK_SET
: /* Go from beginning of source. */
7844 case SEEK_END
: /* Go from end of source. */
7845 idx
= src
->len
+ off
;
7848 case SEEK_CUR
: /* Go from current position. */
7849 idx
= src
->index
+ off
;
7852 default: /* Invalid `whence'. */
7856 if (idx
> src
->len
|| idx
< 0)
7864 tiff_close_memory (data
)
7872 tiff_mmap_memory (data
, pbase
, psize
)
7877 /* It is already _IN_ memory. */
7882 tiff_unmap_memory (data
, base
, size
)
7887 /* We don't need to do this. */
7891 tiff_size_of_memory (data
)
7894 return ((tiff_memory_source
*) data
)->len
;
7899 tiff_error_handler (title
, format
, ap
)
7900 const char *title
, *format
;
7906 len
= sprintf (buf
, "TIFF error: %s ", title
);
7907 vsprintf (buf
+ len
, format
, ap
);
7908 add_to_log (buf
, Qnil
, Qnil
);
7913 tiff_warning_handler (title
, format
, ap
)
7914 const char *title
, *format
;
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
7934 Lisp_Object file
, specified_file
;
7935 Lisp_Object specified_data
;
7937 int width
, height
, x
, y
;
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
);
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
);
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");
7968 image_error ("Cannot open `%s'", file
, Qnil
);
7975 /* Memory source! */
7976 memsrc
.bytes
= SDATA (specified_data
);
7977 memsrc
.len
= SBYTES (specified_data
);
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
,
7986 tiff_size_of_memory
,
7992 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
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
);
8010 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
8012 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
8013 fn_TIFFClose (tiff
);
8016 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
8022 /* Create the X image and pixmap. */
8023 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
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 */
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
);
8071 #else /* HAVE_TIFF */
8079 #if USE_MAC_IMAGE_IO
8080 return image_load_image_io (f
, img
, kUTTypeTIFF
);
8082 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
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. */
8115 /* Indices of image specification fields in gif_format, below. */
8117 enum gif_keyword_index
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
=
8162 /* Free X resources of GIF image IMG which is used on frame F. */
8165 gif_clear_image (f
, 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. */
8177 gif_image_p (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
))
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 */
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. */
8200 /* avoid conflict with QuickdrawText.h */
8201 #define DrawText gif_DrawText
8202 #include <gif_lib.h>
8205 #else /* HAVE_NTGUI || MAC_OS */
8207 #include <gif_lib.h>
8209 #endif /* HAVE_NTGUI || MAC_OS */
8214 /* GIF library details. */
8215 DEF_IMGLIB_FN (DGifCloseFile
);
8216 DEF_IMGLIB_FN (DGifSlurp
);
8217 DEF_IMGLIB_FN (DGifOpen
);
8218 DEF_IMGLIB_FN (DGifOpenFileName
);
8221 init_gif_functions (Lisp_Object libraries
)
8225 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
8228 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
8229 LOAD_IMGLIB_FN (library
, DGifSlurp
);
8230 LOAD_IMGLIB_FN (library
, DGifOpen
);
8231 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
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. */
8249 unsigned char *bytes
;
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
;
8261 gif_read_from_memory (file
, buf
, len
)
8266 gif_memory_source
*src
= current_gif_memory_src
;
8268 if (len
> src
->len
- src
->index
)
8271 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8277 /* Load GIF image IMG for use on frame F. Value is non-zero if
8280 static int interlace_start
[] = {0, 4, 2, 1};
8281 static int interlace_increment
[] = {8, 8, 4, 2};
8288 Lisp_Object file
, specified_file
;
8289 Lisp_Object specified_data
;
8290 int rc
, width
, height
, x
, y
, i
;
8292 ColorMapObject
*gif_color_map
;
8293 unsigned long pixel_colors
[256];
8295 struct gcpro gcpro1
;
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
);
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
);
8316 /* Open the GIF file. Casting return value avoids a GCC warning
8318 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
8321 image_error ("Cannot open `%s'", file
, Qnil
);
8328 /* Read from memory! */
8329 current_gif_memory_src
= &memsrc
;
8330 memsrc
.bytes
= SDATA (specified_data
);
8331 memsrc
.len
= SBYTES (specified_data
);
8334 /* Casting return value avoids a GCC warning on W32. */
8335 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
8338 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
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
);
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
);
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'",
8369 fn_DGifCloseFile (gif
);
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
);
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
);
8404 /* Allocate colors. */
8405 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8407 gif_color_map
= gif
->SColorMap
;
8408 init_color_table ();
8409 bzero (pixel_colors
, sizeof pixel_colors
);
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
)
8454 int row
= interlace_start
[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
];
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
);
8521 #else /* !HAVE_GIF */
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
;
8535 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8543 Lisp_Object specified_bg
;
8548 TimeScale time_scale
;
8549 TimeValue time
, duration
;
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. */
8560 if (NILP (specified_data
))
8562 /* Read from a file */
8566 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8570 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8575 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8576 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8580 if (!graphic_p
&& !movie_p
)
8582 if (prefer_graphic_p
)
8583 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8584 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8587 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8588 CloseMovieFile (refnum
);
8591 image_error ("Error reading `%s'", file
, Qnil
);
8597 /* Memory source! */
8599 long file_type_atom
[3];
8601 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8604 image_error ("Cannot allocate data handle for `%s'",
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
));
8615 err
= PtrAndHand ("\p", dref
, 1);
8617 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8620 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8623 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8624 &movie_p
, &prefer_graphic_p
, 0);
8628 if (!graphic_p
&& !movie_p
)
8630 if (prefer_graphic_p
)
8634 DisposeHandle (dref
);
8635 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8639 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8640 HandleDataHandlerSubType
);
8641 DisposeHandle (dref
);
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'",
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
))
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
);
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. */
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
);
8719 image_error ("Cannot open `%s'", file
, Qnil
);
8722 DisposeTrackMedia (media
);
8724 DisposeMovieTrack (track
);
8726 DisposeMovie (movie
);
8730 #endif /* !USE_MAC_IMAGE_IO */
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. */
8766 /* Indices of image specification fields in svg_format, below. */
8768 enum svg_keyword_index
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. */
8808 /* Handle to a function that can be used to identify a SVG file. */
8810 /* Handle to function used to load a SVG file. */
8812 /* Handle to function to free sresources for SVG. */
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. */
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. */
8825 svg_image_p (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
))
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>
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
;
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
)))
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
);
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. */
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
))
8938 unsigned char *contents
;
8940 struct gcpro gcpro1
;
8942 file
= x_find_image_file (file_name
);
8944 if (!STRINGP (file
))
8946 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
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
);
8959 /* If the file was slurped into memory properly, parse it. */
8960 success_p
= svg_load_image (f
, img
, contents
, size
);
8964 /* Else its not a file, its a lisp object. Load the image from a
8965 lisp object rather than a file. */
8970 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8971 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
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. */
8985 svg_load_image (f
, img
, contents
, size
)
8986 /* Pointer to emacs frame structure. */
8988 /* Pointer to emacs image structure. */
8990 /* String containing the SVG XML data to be parsed. */
8991 unsigned char *contents
;
8992 /* Size of data in bytes. */
8995 RsvgHandle
*rsvg_handle
;
8996 GError
*error
= NULL
;
9000 const guint8
*pixels
;
9003 Lisp_Object specified_bg
;
9008 /* g_type_init is a glib function that must be called prior to using
9009 gnome type library functions. */
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
);
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
);
9024 /* We can now get a valid pixel buffer from the svg file, if all
9026 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
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
);
9048 init_color_table ();
9050 /* Handle alpha channel by combining the image with a background
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;
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
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
);
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
9086 background
.red
>>= 8;
9087 background
.green
>>= 8;
9088 background
.blue
>>= 8;
9089 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
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
)
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
);
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
9142 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
9143 x_destroy_x_image (ximg
);
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
);
9155 #endif /* defined (HAVE_RSVG) */
9160 /***********************************************************************
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
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
=
9234 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9237 gs_clear_image (f
, 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
9254 struct image_keyword fmt
[GS_LAST
];
9258 bcopy (gs_format
, fmt
, sizeof fmt
);
9260 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9263 /* Bounding box must be a list or vector containing 4 integers. */
9264 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9267 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9268 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9273 else if (VECTORP (tem
))
9275 if (XVECTOR (tem
)->size
!= 4)
9277 for (i
= 0; i
< 4; ++i
)
9278 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9288 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9297 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9298 struct gcpro gcpro1
, gcpro2
;
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
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
);
9320 /* Create the pixmap. */
9321 xassert (img
->pixmap
== NO_PIXMAP
);
9323 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9325 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9326 img
->width
, img
->height
,
9327 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9332 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
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
);
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
,
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. */
9372 x_kill_gs_process (pixmap
, f
)
9376 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
9380 /* Find the image containing PIXMAP. */
9381 for (i
= 0; i
< c
->used
; ++i
)
9382 if (c
->images
[i
]->pixmap
== pixmap
)
9385 /* Should someone in between have cleared the image cache, for
9386 instance, give up. */
9390 /* Kill the GS process. We should have found PIXMAP in the image
9391 cache and its image should contain a process object. */
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
9402 class = FRAME_X_VISUAL (f
)->class;
9403 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
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
);
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 ();
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. */
9443 x_free_colors (f
, img
->colors
, img
->ncolors
);
9447 image_error ("Cannot get X image of `%s'; colors will not be freed",
9452 #endif /* HAVE_X_WINDOWS */
9454 /* Now that we have the pixmap, compute mask and transform the
9455 image if requested. */
9457 postprocess_image (f
, img
);
9461 #endif /* HAVE_GHOSTSCRIPT */
9464 /***********************************************************************
9466 ***********************************************************************/
9470 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9471 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
9475 return valid_image_p (spec
) ? Qt
: Qnil
;
9479 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
9485 if (valid_image_p (spec
))
9486 id
= lookup_image (SELECTED_FRAME (), spec
);
9489 return make_number (id
);
9492 #endif /* GLYPH_DEBUG != 0 */
9495 /***********************************************************************
9497 ***********************************************************************/
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))
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). */)
9517 Lisp_Object type
, libraries
;
9521 /* Don't try to reload the library. */
9522 tested
= Fassq (type
, Vimage_type_cache
);
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
);
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
);
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
);
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
);
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
);
9551 #if defined (HAVE_RSVG)
9552 if (EQ (type
, Qsvg
))
9553 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
9556 #ifdef HAVE_GHOSTSCRIPT
9557 if (EQ (type
, Qpostscript
))
9558 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
9561 /* If the type is not recognized, avoid testing it ever again. */
9562 CACHE_IMAGE_TYPE (type
, Qnil
);
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. */
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");
9615 ADD_IMAGE_TYPE (Qpbm
);
9617 Qxbm
= intern ("xbm");
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");
9674 ADD_IMAGE_TYPE (Qxpm
);
9677 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9678 Qjpeg
= intern ("jpeg");
9680 ADD_IMAGE_TYPE (Qjpeg
);
9683 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9684 Qtiff
= intern ("tiff");
9686 ADD_IMAGE_TYPE (Qtiff
);
9689 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9690 Qgif
= intern ("gif");
9692 ADD_IMAGE_TYPE (Qgif
);
9695 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9696 Qpng
= intern ("png");
9698 ADD_IMAGE_TYPE (Qpng
);
9701 #if defined (HAVE_RSVG)
9702 Qsvg
= intern ("svg");
9704 ADD_IMAGE_TYPE (Qsvg
);
9706 Qgdk_pixbuf
= intern ("gdk-pixbuf");
9707 staticpro (&Qgdk_pixbuf
);
9708 Qglib
= intern ("glib");
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
);
9722 defsubr (&Slookup_image
);
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);
9748 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9749 (do not change this comment) */