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) x_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 | kCGBitmapByteOrder32Host
),
385 provider
, NULL
, 0, kCGRenderingIntentDefault
);
386 CGDataProviderRelease (provider
);
392 CGImageRef result
= NULL
;
399 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
400 img
->width
, img
->height
, 1);
407 GetGWorld (&old_port
, &old_gdh
);
408 SetGWorld (mask
, NULL
);
409 BackColor (blackColor
); /* Don't mask. */
410 SetRect (&r
, 0, 0, img
->width
, img
->height
);
412 SetGWorld (old_port
, old_gdh
);
417 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
418 GetGWorldPixMap (mask
), &result
);
419 if (mask
!= img
->mask
)
420 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
427 #endif /* USE_CG_DRAWING */
432 XGetImage (Display
*display
, Pixmap pixmap
, int x
, int y
,
433 unsigned int width
, unsigned int height
,
434 unsigned long plane_mask
, int format
)
436 /* TODO: not sure what this function is supposed to do.. */
437 ns_retain_object(pixmap
);
441 /* use with imgs created by ns_image_for_XPM */
443 XGetPixel (XImagePtr ximage
, int x
, int y
)
445 return ns_get_pixel(ximage
, x
, y
);
448 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
449 pixel is assumed to be in form RGB */
451 XPutPixel (XImagePtr ximage
, int x
, int y
, unsigned long pixel
)
453 ns_put_pixel(ximage
, x
, y
, pixel
);
458 /* Functions to access the contents of a bitmap, given an id. */
461 x_bitmap_height (f
, id
)
465 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
469 x_bitmap_width (f
, id
)
473 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
476 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
478 x_bitmap_pixmap (f
, id
)
482 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
486 #ifdef HAVE_X_WINDOWS
488 x_bitmap_mask (f
, id
)
492 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
496 /* Allocate a new bitmap record. Returns index of new record. */
499 x_allocate_bitmap_record (f
)
502 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
505 if (dpyinfo
->bitmaps
== NULL
)
507 dpyinfo
->bitmaps_size
= 10;
509 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
510 dpyinfo
->bitmaps_last
= 1;
514 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
515 return ++dpyinfo
->bitmaps_last
;
517 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
518 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
521 dpyinfo
->bitmaps_size
*= 2;
523 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
524 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
525 return ++dpyinfo
->bitmaps_last
;
528 /* Add one reference to the reference count of the bitmap with id ID. */
531 x_reference_bitmap (f
, id
)
535 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
538 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
541 x_create_bitmap_from_data (f
, bits
, width
, height
)
544 unsigned int width
, height
;
546 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
549 #ifdef HAVE_X_WINDOWS
551 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
552 bits
, width
, height
);
555 #endif /* HAVE_X_WINDOWS */
559 bitmap
= CreateBitmap (width
, height
,
560 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
561 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
565 #endif /* HAVE_NTGUI */
568 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
574 void *bitmap
= ns_image_from_XBM(bits
, width
, height
);
579 id
= x_allocate_bitmap_record (f
);
581 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
582 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
586 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
587 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
590 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
591 dpyinfo
->bitmaps
[id
- 1].height
= height
;
592 dpyinfo
->bitmaps
[id
- 1].width
= width
;
593 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
595 #ifdef HAVE_X_WINDOWS
596 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
597 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
598 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
599 #endif /* HAVE_X_WINDOWS */
602 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
603 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
604 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
605 #endif /* HAVE_NTGUI */
610 /* Create bitmap from file FILE for frame F. */
613 x_create_bitmap_from_file (f
, file
)
617 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
620 return -1; /* MAC_TODO : bitmap support */
624 return -1; /* W32_TODO : bitmap support */
625 #endif /* HAVE_NTGUI */
629 void *bitmap
= ns_image_from_file(file
);
635 id
= x_allocate_bitmap_record (f
);
636 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
637 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
638 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
639 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
640 dpyinfo
->bitmaps
[id
- 1].height
= ns_image_width(bitmap
);
641 dpyinfo
->bitmaps
[id
- 1].width
= ns_image_height(bitmap
);
642 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
646 #ifdef HAVE_X_WINDOWS
647 unsigned int width
, height
;
649 int xhot
, yhot
, result
, id
;
654 /* Look for an existing bitmap with the same name. */
655 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
657 if (dpyinfo
->bitmaps
[id
].refcount
658 && dpyinfo
->bitmaps
[id
].file
659 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
661 ++dpyinfo
->bitmaps
[id
].refcount
;
666 /* Search bitmap-file-path for the file, if appropriate. */
667 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
672 filename
= (char *) SDATA (found
);
674 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
675 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
676 if (result
!= BitmapSuccess
)
679 id
= x_allocate_bitmap_record (f
);
680 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
681 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
682 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
683 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
684 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
685 dpyinfo
->bitmaps
[id
- 1].height
= height
;
686 dpyinfo
->bitmaps
[id
- 1].width
= width
;
687 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
690 #endif /* HAVE_X_WINDOWS */
696 free_bitmap_record (dpyinfo
, bm
)
697 Display_Info
*dpyinfo
;
700 #ifdef HAVE_X_WINDOWS
701 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
703 XFreePixmap (dpyinfo
->display
, bm
->mask
);
704 #endif /* HAVE_X_WINDOWS */
707 DeleteObject (bm
->pixmap
);
708 #endif /* HAVE_NTGUI */
711 xfree (bm
->bitmap_data
); /* Added ++kfs */
712 bm
->bitmap_data
= NULL
;
716 ns_release_object(bm
->img
);
726 /* Remove reference to bitmap with id number ID. */
729 x_destroy_bitmap (f
, id
)
733 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
737 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
739 if (--bm
->refcount
== 0)
742 free_bitmap_record (dpyinfo
, bm
);
748 /* Free all the bitmaps for the display specified by DPYINFO. */
751 x_destroy_all_bitmaps (dpyinfo
)
752 Display_Info
*dpyinfo
;
755 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
757 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
758 if (bm
->refcount
> 0)
759 free_bitmap_record (dpyinfo
, bm
);
761 dpyinfo
->bitmaps_last
= 0;
765 #ifdef HAVE_X_WINDOWS
767 /* Useful functions defined in the section
768 `Image type independent image structures' below. */
770 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
773 unsigned long height
));
775 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
776 int depth
, XImagePtr
*ximg
,
779 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
782 /* Create a mask of a bitmap. Note is this not a perfect mask.
783 It's nicer with some borders in this context */
786 x_create_bitmap_mask (f
, id
)
791 XImagePtr ximg
, mask_img
;
792 unsigned long width
, height
;
795 unsigned long x
, y
, xp
, xm
, yp
, ym
;
798 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
803 pixmap
= x_bitmap_pixmap (f
, id
);
804 width
= x_bitmap_width (f
, id
);
805 height
= x_bitmap_height (f
, id
);
808 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
817 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
822 XDestroyImage (ximg
);
826 bg
= four_corners_best (ximg
, NULL
, width
, height
);
828 for (y
= 0; y
< ximg
->height
; ++y
)
830 for (x
= 0; x
< ximg
->width
; ++x
)
832 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
833 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
834 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
835 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
836 if (XGetPixel (ximg
, x
, y
) == bg
837 && XGetPixel (ximg
, x
, yp
) == bg
838 && XGetPixel (ximg
, x
, ym
) == bg
839 && XGetPixel (ximg
, xp
, y
) == bg
840 && XGetPixel (ximg
, xp
, yp
) == bg
841 && XGetPixel (ximg
, xp
, ym
) == bg
842 && XGetPixel (ximg
, xm
, y
) == bg
843 && XGetPixel (ximg
, xm
, yp
) == bg
844 && XGetPixel (ximg
, xm
, ym
) == bg
)
845 XPutPixel (mask_img
, x
, y
, 0);
847 XPutPixel (mask_img
, x
, y
, 1);
851 xassert (interrupt_input_blocked
);
852 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
853 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
855 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
857 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
858 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
860 XDestroyImage (ximg
);
861 x_destroy_x_image (mask_img
);
866 #endif /* HAVE_X_WINDOWS */
869 /***********************************************************************
871 ***********************************************************************/
873 /* Value is the number of elements of vector VECTOR. */
875 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
877 /* List of supported image types. Use define_image_type to add new
878 types. Use lookup_image_type to find a type for a given symbol. */
880 static struct image_type
*image_types
;
882 /* A list of symbols, one for each supported image type. */
884 Lisp_Object Vimage_types
;
886 /* An alist of image types and libraries that implement the type. */
888 Lisp_Object Vimage_library_alist
;
890 /* Cache for delayed-loading image types. */
892 static Lisp_Object Vimage_type_cache
;
894 /* The symbol `xbm' which is used as the type symbol for XBM images. */
900 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
901 extern Lisp_Object QCdata
, QCtype
;
902 extern Lisp_Object Qcenter
;
903 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
904 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
905 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
909 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
911 /* Time in seconds after which images should be removed from the cache
914 Lisp_Object Vimage_cache_eviction_delay
;
916 /* Function prototypes. */
918 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
919 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
920 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
921 static void x_laplace
P_ ((struct frame
*, struct image
*));
922 static void x_emboss
P_ ((struct frame
*, struct image
*));
923 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
926 #define CACHE_IMAGE_TYPE(type, status) \
927 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
929 #define ADD_IMAGE_TYPE(type) \
930 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
932 /* Define a new image type from TYPE. This adds a copy of TYPE to
933 image_types and caches the loading status of TYPE. */
936 define_image_type (type
, loaded
)
937 struct image_type
*type
;
946 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
947 The initialized data segment is read-only. */
948 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
949 bcopy (type
, p
, sizeof *p
);
950 p
->next
= image_types
;
955 CACHE_IMAGE_TYPE (*type
->type
, success
);
960 /* Look up image type SYMBOL, and return a pointer to its image_type
961 structure. Value is null if SYMBOL is not a known image type. */
963 static INLINE
struct image_type
*
964 lookup_image_type (symbol
)
967 struct image_type
*type
;
969 /* We must initialize the image-type if it hasn't been already. */
970 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
971 return 0; /* unimplemented */
973 for (type
= image_types
; type
; type
= type
->next
)
974 if (EQ (symbol
, *type
->type
))
981 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
982 valid image specification is a list whose car is the symbol
983 `image', and whose rest is a property list. The property list must
984 contain a value for key `:type'. That value must be the name of a
985 supported image type. The rest of the property list depends on the
989 valid_image_p (object
)
998 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
999 if (EQ (XCAR (tem
), QCtype
))
1002 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
1004 struct image_type
*type
;
1005 type
= lookup_image_type (XCAR (tem
));
1007 valid_p
= type
->valid_p (object
);
1018 /* Log error message with format string FORMAT and argument ARG.
1019 Signaling an error, e.g. when an image cannot be loaded, is not a
1020 good idea because this would interrupt redisplay, and the error
1021 message display would lead to another redisplay. This function
1022 therefore simply displays a message. */
1025 image_error (format
, arg1
, arg2
)
1027 Lisp_Object arg1
, arg2
;
1029 add_to_log (format
, arg1
, arg2
);
1034 /***********************************************************************
1035 Image specifications
1036 ***********************************************************************/
1038 enum image_value_type
1040 IMAGE_DONT_CHECK_VALUE_TYPE
,
1042 IMAGE_STRING_OR_NIL_VALUE
,
1044 IMAGE_POSITIVE_INTEGER_VALUE
,
1045 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
1046 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
1048 IMAGE_INTEGER_VALUE
,
1049 IMAGE_FUNCTION_VALUE
,
1054 /* Structure used when parsing image specifications. */
1056 struct image_keyword
1058 /* Name of keyword. */
1061 /* The type of value allowed. */
1062 enum image_value_type type
;
1064 /* Non-zero means key must be present. */
1067 /* Used to recognize duplicate keywords in a property list. */
1070 /* The value that was found. */
1075 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
1077 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
1080 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1081 has the format (image KEYWORD VALUE ...). One of the keyword/
1082 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1083 image_keywords structures of size NKEYWORDS describing other
1084 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1087 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1089 struct image_keyword
*keywords
;
1099 plist
= XCDR (spec
);
1100 while (CONSP (plist
))
1102 Lisp_Object key
, value
;
1104 /* First element of a pair must be a symbol. */
1106 plist
= XCDR (plist
);
1110 /* There must follow a value. */
1113 value
= XCAR (plist
);
1114 plist
= XCDR (plist
);
1116 /* Find key in KEYWORDS. Error if not found. */
1117 for (i
= 0; i
< nkeywords
; ++i
)
1118 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1124 /* Record that we recognized the keyword. If a keywords
1125 was found more than once, it's an error. */
1126 keywords
[i
].value
= value
;
1127 ++keywords
[i
].count
;
1129 if (keywords
[i
].count
> 1)
1132 /* Check type of value against allowed type. */
1133 switch (keywords
[i
].type
)
1135 case IMAGE_STRING_VALUE
:
1136 if (!STRINGP (value
))
1140 case IMAGE_STRING_OR_NIL_VALUE
:
1141 if (!STRINGP (value
) && !NILP (value
))
1145 case IMAGE_SYMBOL_VALUE
:
1146 if (!SYMBOLP (value
))
1150 case IMAGE_POSITIVE_INTEGER_VALUE
:
1151 if (!INTEGERP (value
) || XINT (value
) <= 0)
1155 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1156 if (INTEGERP (value
) && XINT (value
) >= 0)
1159 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1160 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1164 case IMAGE_ASCENT_VALUE
:
1165 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1167 else if (INTEGERP (value
)
1168 && XINT (value
) >= 0
1169 && XINT (value
) <= 100)
1173 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1174 if (!INTEGERP (value
) || XINT (value
) < 0)
1178 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1181 case IMAGE_FUNCTION_VALUE
:
1182 value
= indirect_function (value
);
1184 || COMPILEDP (value
)
1185 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1189 case IMAGE_NUMBER_VALUE
:
1190 if (!INTEGERP (value
) && !FLOATP (value
))
1194 case IMAGE_INTEGER_VALUE
:
1195 if (!INTEGERP (value
))
1199 case IMAGE_BOOL_VALUE
:
1200 if (!NILP (value
) && !EQ (value
, Qt
))
1209 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1213 /* Check that all mandatory fields are present. */
1214 for (i
= 0; i
< nkeywords
; ++i
)
1215 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1218 return NILP (plist
);
1222 /* Return the value of KEY in image specification SPEC. Value is nil
1223 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1224 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1227 image_spec_value (spec
, key
, found
)
1228 Lisp_Object spec
, key
;
1233 xassert (valid_image_p (spec
));
1235 for (tail
= XCDR (spec
);
1236 CONSP (tail
) && CONSP (XCDR (tail
));
1237 tail
= XCDR (XCDR (tail
)))
1239 if (EQ (XCAR (tail
), key
))
1243 return XCAR (XCDR (tail
));
1253 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1254 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1255 PIXELS non-nil means return the size in pixels, otherwise return the
1256 size in canonical character units.
1257 FRAME is the frame on which the image will be displayed. FRAME nil
1258 or omitted means use the selected frame. */)
1259 (spec
, pixels
, frame
)
1260 Lisp_Object spec
, pixels
, frame
;
1265 if (valid_image_p (spec
))
1267 struct frame
*f
= check_x_frame (frame
);
1268 int id
= lookup_image (f
, spec
);
1269 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1270 int width
= img
->width
+ 2 * img
->hmargin
;
1271 int height
= img
->height
+ 2 * img
->vmargin
;
1274 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1275 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1277 size
= Fcons (make_number (width
), make_number (height
));
1280 error ("Invalid image specification");
1286 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1287 doc
: /* Return t if image SPEC has a mask bitmap.
1288 FRAME is the frame on which the image will be displayed. FRAME nil
1289 or omitted means use the selected frame. */)
1291 Lisp_Object spec
, frame
;
1296 if (valid_image_p (spec
))
1298 struct frame
*f
= check_x_frame (frame
);
1299 int id
= lookup_image (f
, spec
);
1300 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1305 error ("Invalid image specification");
1310 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1311 doc
: /* Return extension data for image SPEC.
1312 FRAME is the frame on which the image will be displayed. FRAME nil
1313 or omitted means use the selected frame. */)
1315 Lisp_Object spec
, frame
;
1320 if (valid_image_p (spec
))
1322 struct frame
*f
= check_x_frame (frame
);
1323 int id
= lookup_image (f
, spec
);
1324 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1325 ext
= img
->data
.lisp_val
;
1332 /***********************************************************************
1333 Image type independent image structures
1334 ***********************************************************************/
1336 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1337 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1338 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1340 #define MAX_IMAGE_SIZE 6.0
1341 Lisp_Object Vmax_image_size
;
1343 /* Allocate and return a new image structure for image specification
1344 SPEC. SPEC has a hash value of HASH. */
1346 static struct image
*
1347 make_image (spec
, hash
)
1351 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1352 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1354 xassert (valid_image_p (spec
));
1355 bzero (img
, sizeof *img
);
1356 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1357 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1358 xassert (img
->type
!= NULL
);
1360 img
->data
.lisp_val
= Qnil
;
1361 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1363 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1368 /* Free image IMG which was used on frame F, including its resources. */
1377 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1379 /* Remove IMG from the hash table of its cache. */
1381 img
->prev
->next
= img
->next
;
1383 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1386 img
->next
->prev
= img
->prev
;
1388 c
->images
[img
->id
] = NULL
;
1390 /* Free resources, then free IMG. */
1391 img
->type
->free (f
, img
);
1396 /* Return 1 if the given widths and heights are valid for display;
1397 otherwise, return 0. */
1400 check_image_size (f
, width
, height
)
1407 if (width
<= 0 || height
<= 0)
1410 if (INTEGERP (Vmax_image_size
))
1411 w
= h
= XINT (Vmax_image_size
);
1412 else if (FLOATP (Vmax_image_size
))
1416 w
= FRAME_PIXEL_WIDTH (f
);
1417 h
= FRAME_PIXEL_HEIGHT (f
);
1420 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1421 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1422 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1427 return (width
<= w
&& height
<= h
);
1430 /* Prepare image IMG for display on frame F. Must be called before
1431 drawing an image. */
1434 prepare_image_for_display (f
, img
)
1440 /* We're about to display IMG, so set its timestamp to `now'. */
1442 img
->timestamp
= EMACS_SECS (t
);
1444 /* If IMG doesn't have a pixmap yet, load it now, using the image
1445 type dependent loader function. */
1446 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1447 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1449 #if defined (MAC_OS) && USE_CG_DRAWING
1450 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1452 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1453 if (img
->data
.ptr_val
== NULL
)
1455 img
->load_failed_p
= 1;
1456 img
->type
->free (f
, img
);
1463 /* Value is the number of pixels for the ascent of image IMG when
1464 drawn in face FACE. */
1467 image_ascent (img
, face
, slice
)
1470 struct glyph_slice
*slice
;
1475 if (slice
->height
== img
->height
)
1476 height
= img
->height
+ img
->vmargin
;
1477 else if (slice
->y
== 0)
1478 height
= slice
->height
+ img
->vmargin
;
1480 height
= slice
->height
;
1482 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1487 /* W32 specific version. Why?. ++kfs */
1488 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1489 - FONT_BASE (face
->font
)) / 2;
1491 /* This expression is arranged so that if the image can't be
1492 exactly centered, it will be moved slightly up. This is
1493 because a typical font is `top-heavy' (due to the presence
1494 uppercase letters), so the image placement should err towards
1495 being top-heavy too. It also just generally looks better. */
1496 ascent
= (height
+ FONT_BASE(face
->font
)
1497 - FONT_DESCENT(face
->font
) + 1) / 2;
1498 #endif /* HAVE_NTGUI */
1501 ascent
= height
/ 2;
1504 ascent
= (int) (height
* img
->ascent
/ 100.0);
1510 /* Image background colors. */
1512 /* Find the "best" corner color of a bitmap.
1513 On W32, XIMG is assumed to a device context with the bitmap selected. */
1515 static RGB_PIXEL_COLOR
1516 four_corners_best (ximg
, corners
, width
, height
)
1517 XImagePtr_or_DC ximg
;
1519 unsigned long width
, height
;
1521 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1524 if (corners
&& corners
[BOT_CORNER
] >= 0)
1526 /* Get the colors at the corner_pixels of ximg. */
1527 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1528 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1529 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1530 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1534 /* Get the colors at the corner_pixels of ximg. */
1535 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1536 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1537 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1538 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1540 /* Choose the most frequently found color as background. */
1541 for (i
= best_count
= 0; i
< 4; ++i
)
1545 for (j
= n
= 0; j
< 4; ++j
)
1546 if (corner_pixels
[i
] == corner_pixels
[j
])
1550 best
= corner_pixels
[i
], best_count
= n
;
1556 /* Portability macros */
1560 #define Destroy_Image(img_dc, prev) \
1561 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1563 #define Free_Pixmap(display, pixmap) \
1564 DeleteObject (pixmap)
1566 #elif defined (HAVE_NS)
1568 #define Destroy_Image(ximg, dummy) \
1569 ns_release_object(ximg)
1571 #define Free_Pixmap(display, pixmap) \
1572 ns_release_object(pixmap)
1576 #define Destroy_Image(ximg, dummy) \
1577 XDestroyImage (ximg)
1579 #define Free_Pixmap(display, pixmap) \
1580 XFreePixmap (display, pixmap)
1582 #endif /* !HAVE_NTGUI && !HAVE_NS */
1585 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1586 it is guessed heuristically. If non-zero, XIMG is an existing
1587 XImage object (or device context with the image selected on W32) to
1588 use for the heuristic. */
1591 image_background (img
, f
, ximg
)
1594 XImagePtr_or_DC ximg
;
1596 if (! img
->background_valid
)
1597 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1599 int free_ximg
= !ximg
;
1602 #endif /* HAVE_NTGUI */
1607 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1608 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1610 HDC frame_dc
= get_frame_dc (f
);
1611 ximg
= CreateCompatibleDC (frame_dc
);
1612 release_frame_dc (f
, frame_dc
);
1613 prev
= SelectObject (ximg
, img
->pixmap
);
1614 #endif /* !HAVE_NTGUI */
1617 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1620 Destroy_Image (ximg
, prev
);
1622 img
->background_valid
= 1;
1625 return img
->background
;
1628 /* Return the `background_transparent' field of IMG. If IMG doesn't
1629 have one yet, it is guessed heuristically. If non-zero, MASK is an
1630 existing XImage object to use for the heuristic. */
1633 image_background_transparent (img
, f
, mask
)
1636 XImagePtr_or_DC mask
;
1638 if (! img
->background_transparent_valid
)
1639 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1643 int free_mask
= !mask
;
1646 #endif /* HAVE_NTGUI */
1651 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1652 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1654 HDC frame_dc
= get_frame_dc (f
);
1655 mask
= CreateCompatibleDC (frame_dc
);
1656 release_frame_dc (f
, frame_dc
);
1657 prev
= SelectObject (mask
, img
->mask
);
1658 #endif /* HAVE_NTGUI */
1661 img
->background_transparent
1662 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1665 Destroy_Image (mask
, prev
);
1668 img
->background_transparent
= 0;
1670 img
->background_transparent_valid
= 1;
1673 return img
->background_transparent
;
1677 /***********************************************************************
1678 Helper functions for X image types
1679 ***********************************************************************/
1681 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1683 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1684 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1686 Lisp_Object color_name
,
1687 unsigned long dflt
));
1690 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1691 free the pixmap if any. MASK_P non-zero means clear the mask
1692 pixmap if any. COLORS_P non-zero means free colors allocated for
1693 the image, if any. */
1696 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1699 int pixmap_p
, mask_p
, colors_p
;
1701 if (pixmap_p
&& img
->pixmap
)
1703 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1704 img
->pixmap
= NO_PIXMAP
;
1706 if (img
->background_valid
)
1707 ns_free_indexed_color(img
->background
);
1709 img
->background_valid
= 0;
1712 if (mask_p
&& img
->mask
)
1714 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1715 img
->mask
= NO_PIXMAP
;
1716 img
->background_transparent_valid
= 0;
1719 if (colors_p
&& img
->ncolors
)
1721 /* MAC_TODO: color table support. */
1722 /* W32_TODO: color table support. */
1723 #ifdef HAVE_X_WINDOWS
1724 x_free_colors (f
, img
->colors
, img
->ncolors
);
1725 #endif /* HAVE_X_WINDOWS */
1726 xfree (img
->colors
);
1731 #if defined (MAC_OS) && USE_CG_DRAWING
1732 if (img
->data
.ptr_val
)
1734 CGImageRelease (img
->data
.ptr_val
);
1735 img
->data
.ptr_val
= NULL
;
1740 /* Free X resources of image IMG which is used on frame F. */
1743 x_clear_image (f
, img
)
1748 x_clear_image_1 (f
, img
, 1, 1, 1);
1753 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1754 cannot be allocated, use DFLT. Add a newly allocated color to
1755 IMG->colors, so that it can be freed again. Value is the pixel
1758 static unsigned long
1759 x_alloc_image_color (f
, img
, color_name
, dflt
)
1762 Lisp_Object color_name
;
1766 unsigned long result
;
1768 xassert (STRINGP (color_name
));
1770 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1772 /* This isn't called frequently so we get away with simply
1773 reallocating the color vector to the needed size, here. */
1776 (unsigned long *) xrealloc (img
->colors
,
1777 img
->ncolors
* sizeof *img
->colors
);
1778 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1779 result
= color
.pixel
;
1789 /***********************************************************************
1791 ***********************************************************************/
1793 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1794 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1795 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1797 /* Return a new, initialized image cache that is allocated from the
1798 heap. Call free_image_cache to free an image cache. */
1800 struct image_cache
*
1803 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1806 bzero (c
, sizeof *c
);
1808 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1809 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1810 c
->buckets
= (struct image
**) xmalloc (size
);
1811 bzero (c
->buckets
, size
);
1816 /* Find an image matching SPEC in the cache, and return it. If no
1817 image is found, return NULL. */
1818 static struct image
*
1819 search_image_cache (f
, spec
, hash
)
1825 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1826 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1828 if (!c
) return NULL
;
1830 /* If the image spec does not specify a background color, the cached
1831 image must have the same background color as the current frame.
1832 The foreground color must also match, for the sake of monochrome
1835 In fact, we could ignore the foreground color matching condition
1836 for color images, or if the image spec specifies :foreground;
1837 similarly we could ignore the background color matching condition
1838 for formats that don't use transparency (such as jpeg), or if the
1839 image spec specifies :background. However, the extra memory
1840 usage is probably negligible in practice, so we don't bother. */
1842 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1843 if (img
->hash
== hash
1844 && !NILP (Fequal (img
->spec
, spec
))
1845 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1846 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1852 /* Search frame F for an image with spec SPEC, and free it. */
1855 uncache_image (f
, spec
)
1859 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1861 free_image (f
, img
);
1865 /* Free image cache of frame F. Be aware that X frames share images
1869 free_image_cache (f
)
1872 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1877 /* Cache should not be referenced by any frame when freed. */
1878 xassert (c
->refcount
== 0);
1880 for (i
= 0; i
< c
->used
; ++i
)
1881 free_image (f
, c
->images
[i
]);
1885 FRAME_IMAGE_CACHE (f
) = NULL
;
1890 /* Clear image cache of frame F. FILTER=t means free all images.
1891 FILTER=nil means clear only images that haven't been
1892 displayed for some time.
1893 Else, only free the images which have FILTER in their `dependencies'.
1894 Should be called from time to time to reduce the number of loaded images.
1895 If image-cache-eviction-delay is non-nil, this frees images in the cache
1896 which weren't displayed for at least that many seconds. */
1899 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1901 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1903 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1910 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1912 /* Block input so that we won't be interrupted by a SIGIO
1913 while being in an inconsistent state. */
1916 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1918 struct image
*img
= c
->images
[i
];
1920 && (NILP (filter
) ? img
->timestamp
< old
1922 || !NILP (Fmember (filter
, img
->dependencies
)))))
1924 free_image (f
, img
);
1929 /* We may be clearing the image cache because, for example,
1930 Emacs was iconified for a longer period of time. In that
1931 case, current matrices may still contain references to
1932 images freed above. So, clear these matrices. */
1935 Lisp_Object tail
, frame
;
1937 FOR_EACH_FRAME (tail
, frame
)
1939 struct frame
*f
= XFRAME (frame
);
1940 if (FRAME_IMAGE_CACHE (f
) == c
)
1941 clear_current_matrices (f
);
1944 ++windows_or_buffers_changed
;
1952 clear_image_caches (Lisp_Object filter
)
1954 /* FIXME: We want to do
1955 * struct terminal *t;
1956 * for (t = terminal_list; t; t = t->next_terminal)
1957 * clear_image_cache (t, filter); */
1958 Lisp_Object tail
, frame
;
1959 FOR_EACH_FRAME (tail
, frame
)
1960 if (FRAME_WINDOW_P (XFRAME (frame
)))
1961 clear_image_cache (XFRAME (frame
), filter
);
1964 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1966 doc
: /* Clear the image cache.
1967 FILTER nil or a frame means clear all images in the selected frame.
1968 FILTER t means clear the image caches of all frames.
1969 Anything else, means only clear those images which refer to FILTER,
1970 which is then usually a filename. */)
1974 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1975 clear_image_caches (filter
);
1977 clear_image_cache (check_x_frame (filter
), Qt
);
1983 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1985 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1986 If SPEC specifies an image file, the displayed image is updated with
1987 the current contents of that file.
1988 FRAME nil or omitted means use the selected frame.
1989 FRAME t means refresh the image on all frames. */)
1991 Lisp_Object spec
, frame
;
1993 if (!valid_image_p (spec
))
1994 error ("Invalid image specification");
1999 FOR_EACH_FRAME (tail
, frame
)
2001 struct frame
*f
= XFRAME (frame
);
2002 if (FRAME_WINDOW_P (f
))
2003 uncache_image (f
, spec
);
2007 uncache_image (check_x_frame (frame
), spec
);
2013 /* Compute masks and transform image IMG on frame F, as specified
2014 by the image's specification, */
2017 postprocess_image (f
, img
)
2021 /* Manipulation of the image's mask. */
2024 Lisp_Object conversion
, spec
;
2029 /* `:heuristic-mask t'
2031 means build a mask heuristically.
2032 `:heuristic-mask (R G B)'
2033 `:mask (heuristic (R G B))'
2034 means build a mask from color (R G B) in the
2037 means remove a mask, if any. */
2039 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
2041 x_build_heuristic_mask (f
, img
, mask
);
2046 mask
= image_spec_value (spec
, QCmask
, &found_p
);
2048 if (EQ (mask
, Qheuristic
))
2049 x_build_heuristic_mask (f
, img
, Qt
);
2050 else if (CONSP (mask
)
2051 && EQ (XCAR (mask
), Qheuristic
))
2053 if (CONSP (XCDR (mask
)))
2054 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
2056 x_build_heuristic_mask (f
, img
, XCDR (mask
));
2058 else if (NILP (mask
) && found_p
&& img
->mask
)
2060 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
2061 img
->mask
= NO_PIXMAP
;
2066 /* Should we apply an image transformation algorithm? */
2067 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
2068 if (EQ (conversion
, Qdisabled
))
2069 x_disable_image (f
, img
);
2070 else if (EQ (conversion
, Qlaplace
))
2072 else if (EQ (conversion
, Qemboss
))
2074 else if (CONSP (conversion
)
2075 && EQ (XCAR (conversion
), Qedge_detection
))
2078 tem
= XCDR (conversion
);
2080 x_edge_detection (f
, img
,
2081 Fplist_get (tem
, QCmatrix
),
2082 Fplist_get (tem
, QCcolor_adjustment
));
2088 /* Return the id of image with Lisp specification SPEC on frame F.
2089 SPEC must be a valid Lisp image specification (see valid_image_p). */
2092 lookup_image (f
, spec
)
2096 struct image_cache
*c
;
2099 struct gcpro gcpro1
;
2102 /* F must be a window-system frame, and SPEC must be a valid image
2104 xassert (FRAME_WINDOW_P (f
));
2105 xassert (valid_image_p (spec
));
2107 c
= FRAME_IMAGE_CACHE (f
);
2111 /* Look up SPEC in the hash table of the image cache. */
2112 hash
= sxhash (spec
, 0);
2113 img
= search_image_cache (f
, spec
, hash
);
2114 if (img
&& img
->load_failed_p
)
2116 free_image (f
, img
);
2120 /* If not found, create a new image and cache it. */
2123 extern Lisp_Object Qpostscript
;
2126 img
= make_image (spec
, hash
);
2127 cache_image (f
, img
);
2128 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2129 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2130 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2132 /* If we can't load the image, and we don't have a width and
2133 height, use some arbitrary width and height so that we can
2134 draw a rectangle for it. */
2135 if (img
->load_failed_p
)
2139 value
= image_spec_value (spec
, QCwidth
, NULL
);
2140 img
->width
= (INTEGERP (value
)
2141 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2142 value
= image_spec_value (spec
, QCheight
, NULL
);
2143 img
->height
= (INTEGERP (value
)
2144 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2148 /* Handle image type independent image attributes
2149 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2150 `:background COLOR'. */
2151 Lisp_Object ascent
, margin
, relief
, bg
;
2153 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2154 if (INTEGERP (ascent
))
2155 img
->ascent
= XFASTINT (ascent
);
2156 else if (EQ (ascent
, Qcenter
))
2157 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2159 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2160 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2161 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2162 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2163 && INTEGERP (XCDR (margin
)))
2165 if (XINT (XCAR (margin
)) > 0)
2166 img
->hmargin
= XFASTINT (XCAR (margin
));
2167 if (XINT (XCDR (margin
)) > 0)
2168 img
->vmargin
= XFASTINT (XCDR (margin
));
2171 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2172 if (INTEGERP (relief
))
2174 img
->relief
= XINT (relief
);
2175 img
->hmargin
+= eabs (img
->relief
);
2176 img
->vmargin
+= eabs (img
->relief
);
2179 if (! img
->background_valid
)
2181 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2185 = x_alloc_image_color (f
, img
, bg
,
2186 FRAME_BACKGROUND_PIXEL (f
));
2187 img
->background_valid
= 1;
2191 /* Do image transformations and compute masks, unless we
2192 don't have the image yet. */
2193 if (!EQ (*img
->type
->type
, Qpostscript
))
2194 postprocess_image (f
, img
);
2200 /* We're using IMG, so set its timestamp to `now'. */
2201 EMACS_GET_TIME (now
);
2202 img
->timestamp
= EMACS_SECS (now
);
2206 /* Value is the image id. */
2211 /* Cache image IMG in the image cache of frame F. */
2214 cache_image (f
, img
)
2218 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2221 /* Find a free slot in c->images. */
2222 for (i
= 0; i
< c
->used
; ++i
)
2223 if (c
->images
[i
] == NULL
)
2226 /* If no free slot found, maybe enlarge c->images. */
2227 if (i
== c
->used
&& c
->used
== c
->size
)
2230 c
->images
= (struct image
**) xrealloc (c
->images
,
2231 c
->size
* sizeof *c
->images
);
2234 /* Add IMG to c->images, and assign IMG an id. */
2240 /* Add IMG to the cache's hash table. */
2241 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2242 img
->next
= c
->buckets
[i
];
2244 img
->next
->prev
= img
;
2246 c
->buckets
[i
] = img
;
2250 /* Call FN on every image in the image cache of frame F. Used to mark
2251 Lisp Objects in the image cache. */
2253 /* Mark Lisp objects in image IMG. */
2259 mark_object (img
->spec
);
2260 mark_object (img
->dependencies
);
2262 if (!NILP (img
->data
.lisp_val
))
2263 mark_object (img
->data
.lisp_val
);
2268 mark_image_cache (struct image_cache
*c
)
2273 for (i
= 0; i
< c
->used
; ++i
)
2275 mark_image (c
->images
[i
]);
2281 /***********************************************************************
2282 X / MAC / W32 support code
2283 ***********************************************************************/
2287 /* Macro for defining functions that will be loaded from image DLLs. */
2288 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2290 /* Macro for loading those image functions from the library. */
2291 #define LOAD_IMGLIB_FN(lib,func) { \
2292 fn_##func = (void *) GetProcAddress (lib, #func); \
2293 if (!fn_##func) return 0; \
2296 /* Load a DLL implementing an image type.
2297 The `image-library-alist' variable associates a symbol,
2298 identifying an image type, to a list of possible filenames.
2299 The function returns NULL if no library could be loaded for
2300 the given image type, or if the library was previously loaded;
2301 else the handle of the DLL. */
2303 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2305 HMODULE library
= NULL
;
2307 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2309 Lisp_Object dlls
= Fassq (type
, libraries
);
2312 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2314 CHECK_STRING_CAR (dlls
);
2315 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2323 #endif /* HAVE_NTGUI */
2325 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2326 XImagePtr
*, Pixmap
*));
2327 static void x_destroy_x_image
P_ ((XImagePtr
));
2328 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2331 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2332 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2333 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2334 via xmalloc. Print error messages via image_error if an error
2335 occurs. Value is non-zero if successful.
2337 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2338 should indicate the bit depth of the image. */
2341 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2343 int width
, height
, depth
;
2347 #ifdef HAVE_X_WINDOWS
2348 Display
*display
= FRAME_X_DISPLAY (f
);
2349 Window window
= FRAME_X_WINDOW (f
);
2350 Screen
*screen
= FRAME_X_SCREEN (f
);
2352 xassert (interrupt_input_blocked
);
2355 depth
= DefaultDepthOfScreen (screen
);
2356 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2357 depth
, ZPixmap
, 0, NULL
, width
, height
,
2358 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2361 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2365 /* Allocate image raster. */
2366 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2368 /* Allocate a pixmap of the same size. */
2369 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2370 if (*pixmap
== NO_PIXMAP
)
2372 x_destroy_x_image (*ximg
);
2374 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2379 #endif /* HAVE_X_WINDOWS */
2383 BITMAPINFOHEADER
*header
;
2385 int scanline_width_bits
;
2387 int palette_colors
= 0;
2392 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2393 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2395 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2399 scanline_width_bits
= width
* depth
;
2400 remainder
= scanline_width_bits
% 32;
2403 scanline_width_bits
+= 32 - remainder
;
2405 /* Bitmaps with a depth less than 16 need a palette. */
2406 /* BITMAPINFO structure already contains the first RGBQUAD. */
2408 palette_colors
= 1 << depth
- 1;
2410 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2413 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2417 header
= &((*ximg
)->info
.bmiHeader
);
2418 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2419 header
->biSize
= sizeof (*header
);
2420 header
->biWidth
= width
;
2421 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2422 header
->biPlanes
= 1;
2423 header
->biBitCount
= depth
;
2424 header
->biCompression
= BI_RGB
;
2425 header
->biClrUsed
= palette_colors
;
2427 /* TODO: fill in palette. */
2430 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2431 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2432 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2433 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2434 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2435 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2436 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2437 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2440 hdc
= get_frame_dc (f
);
2442 /* Create a DIBSection and raster array for the bitmap,
2443 and store its handle in *pixmap. */
2444 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2445 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2446 /* casting avoids a GCC warning */
2447 (void **)&((*ximg
)->data
), NULL
, 0);
2449 /* Realize display palette and garbage all frames. */
2450 release_frame_dc (f
, hdc
);
2452 if (*pixmap
== NULL
)
2454 DWORD err
= GetLastError ();
2455 Lisp_Object errcode
;
2456 /* All system errors are < 10000, so the following is safe. */
2457 XSETINT (errcode
, (int) err
);
2458 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2459 x_destroy_x_image (*ximg
);
2465 #endif /* HAVE_NTGUI */
2468 Display
*display
= FRAME_X_DISPLAY (f
);
2469 Window window
= FRAME_X_WINDOW (f
);
2471 xassert (interrupt_input_blocked
);
2473 /* Allocate a pixmap of the same size. */
2474 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2475 if (*pixmap
== NO_PIXMAP
)
2478 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2482 #if !USE_MAC_IMAGE_IO
2483 LockPixels (GetGWorldPixMap (*pixmap
));
2491 *pixmap
= ns_image_for_XPM(width
, height
, depth
);
2495 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil
, Qnil
);
2504 /* Destroy XImage XIMG. Free XIMG->data. */
2507 x_destroy_x_image (ximg
)
2510 xassert (interrupt_input_blocked
);
2513 #ifdef HAVE_X_WINDOWS
2516 XDestroyImage (ximg
);
2517 #endif /* HAVE_X_WINDOWS */
2519 /* Data will be freed by DestroyObject. */
2522 #endif /* HAVE_NTGUI */
2524 XDestroyImage (ximg
);
2527 ns_release_object(ximg
);
2528 #endif /* HAVE_NS */
2533 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2534 are width and height of both the image and pixmap. */
2537 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2543 #ifdef HAVE_X_WINDOWS
2546 xassert (interrupt_input_blocked
);
2547 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2548 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2549 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2550 #endif /* HAVE_X_WINDOWS */
2553 #if 0 /* I don't think this is necessary looking at where it is used. */
2554 HDC hdc
= get_frame_dc (f
);
2555 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2556 release_frame_dc (f
, hdc
);
2558 #endif /* HAVE_NTGUI */
2561 xassert (ximg
== pixmap
);
2565 xassert (ximg
== pixmap
);
2566 ns_retain_object(ximg
);
2571 /***********************************************************************
2573 ***********************************************************************/
2575 static unsigned char *slurp_file
P_ ((char *, int *));
2578 /* Find image file FILE. Look in data-directory/images, then
2579 x-bitmap-file-path. Value is the encoded full name of the file
2580 found, or nil if not found. */
2583 x_find_image_file (file
)
2586 Lisp_Object file_found
, search_path
;
2587 struct gcpro gcpro1
, gcpro2
;
2591 /* TODO I think this should use something like image-load-path
2592 instead. Unfortunately, that can contain non-string elements. */
2593 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2595 Vx_bitmap_file_path
);
2596 GCPRO2 (file_found
, search_path
);
2598 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2599 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2605 file_found
= ENCODE_FILE (file_found
);
2614 /* Read FILE into memory. Value is a pointer to a buffer allocated
2615 with xmalloc holding FILE's contents. Value is null if an error
2616 occurred. *SIZE is set to the size of the file. */
2618 static unsigned char *
2619 slurp_file (file
, size
)
2624 unsigned char *buf
= NULL
;
2627 if (stat (file
, &st
) == 0
2628 && (fp
= fopen (file
, "rb")) != NULL
2629 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2630 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2653 /***********************************************************************
2654 MAC Image Load Functions
2655 ***********************************************************************/
2657 #if USE_MAC_IMAGE_IO
2659 image_load_image_io (f
, img
, type
)
2664 CFDictionaryRef options
, src_props
= NULL
, props
= NULL
;
2665 CFStringRef keys
[2];
2666 CFTypeRef values
[2];
2667 Lisp_Object specified_file
, specified_data
;
2668 CGImageSourceRef source
= NULL
;
2670 CGImageRef image
= NULL
;
2671 int loop_count
= -1;
2672 double delay_time
= -1.0;
2674 XImagePtr ximg
= NULL
;
2675 CGContextRef context
;
2677 int has_alpha_p
, gif_p
;
2679 gif_p
= UTTypeEqual (type
, kUTTypeGIF
);
2681 keys
[0] = kCGImageSourceTypeIdentifierHint
;
2682 values
[0] = (CFTypeRef
) type
;
2683 keys
[1] = kCGImageSourceShouldCache
;
2684 values
[1] = (CFTypeRef
) kCFBooleanFalse
;
2685 options
= CFDictionaryCreate (NULL
, (const void **) keys
,
2686 (const void **) values
,
2687 sizeof (keys
) / sizeof (keys
[0]),
2688 &kCFTypeDictionaryKeyCallBacks
,
2689 &kCFTypeDictionaryValueCallBacks
);
2690 if (options
== NULL
)
2692 image_error ("Error creating options for image `%s'", img
->spec
, Qnil
);
2696 /* Open the file. */
2697 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2698 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2700 if (NILP (specified_data
))
2706 file
= x_find_image_file (specified_file
);
2707 if (!STRINGP (file
))
2709 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2712 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2715 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2716 kCFURLPOSIXPathStyle
, 0);
2720 source
= CGImageSourceCreateWithURL (url
, NULL
);
2727 CFDataRef data
= CFDataCreate (NULL
, SDATA (specified_data
),
2728 SBYTES (specified_data
));
2732 source
= CGImageSourceCreateWithData (data
, options
);
2736 CFRelease (options
);
2740 CFStringRef real_type
= CGImageSourceGetType (source
);
2742 if (real_type
&& UTTypeEqual (type
, real_type
))
2743 src_props
= CGImageSourceCopyProperties (source
, NULL
);
2748 count
= CGImageSourceGetCount (source
);
2751 Lisp_Object image
= image_spec_value (img
->spec
, QCindex
, NULL
);
2753 if (INTEGERP (image
))
2754 ino
= XFASTINT (image
);
2756 if (ino
>= 0 && ino
< count
)
2758 props
= CGImageSourceCopyPropertiesAtIndex (source
, ino
, NULL
);
2760 image
= CGImageSourceCreateImageAtIndex (source
, ino
, NULL
);
2769 CFRelease (src_props
);
2772 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2777 CFBooleanRef boolean
;
2779 if (CFDictionaryGetValueIfPresent (props
, kCGImagePropertyHasAlpha
,
2780 (const void **) &boolean
))
2781 has_alpha_p
= CFBooleanGetValue (boolean
);
2784 CFDictionaryRef dict
;
2787 dict
= CFDictionaryGetValue (src_props
,
2788 kCGImagePropertyGIFDictionary
);
2790 && CFDictionaryGetValueIfPresent (dict
,
2791 kCGImagePropertyGIFLoopCount
,
2792 (const void **) &number
))
2793 CFNumberGetValue (number
, kCFNumberIntType
, &loop_count
);
2795 dict
= CFDictionaryGetValue (props
, kCGImagePropertyGIFDictionary
);
2797 && CFDictionaryGetValueIfPresent (dict
,
2798 kCGImagePropertyGIFDelayTime
,
2799 (const void **) &number
))
2800 CFNumberGetValue (number
, kCFNumberDoubleType
, &delay_time
);
2802 CFRelease (src_props
);
2806 width
= img
->width
= CGImageGetWidth (image
);
2807 height
= img
->height
= CGImageGetHeight (image
);
2809 if (!check_image_size (f
, width
, height
))
2811 CGImageRelease (image
);
2812 image_error ("Invalid image size", Qnil
, Qnil
);
2816 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2818 CGImageRelease (image
);
2819 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
2822 rectangle
= CGRectMake (0, 0, width
, height
);
2824 context
= CGBitmapContextCreate (ximg
->data
, ximg
->width
, ximg
->height
, 8,
2825 ximg
->bytes_per_line
,
2826 mac_cg_color_space_rgb
,
2827 kCGImageAlphaNoneSkipFirst
2828 | kCGBitmapByteOrder32Host
);
2831 Lisp_Object specified_bg
;
2834 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2835 if (!STRINGP (specified_bg
)
2836 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2838 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2839 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2840 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2841 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2843 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2844 color
.green
/ 65535.0,
2845 color
.blue
/ 65535.0, 1.0);
2846 CGContextFillRect (context
, rectangle
);
2848 CGContextDrawImage (context
, rectangle
, image
);
2849 CGContextRelease (context
);
2850 CGImageRelease (image
);
2852 /* Save GIF image extension data for `image-extension-data'.
2853 Format is (count IMAGES
2854 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2855 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2858 img
->data
.lisp_val
= Qnil
;
2859 if (delay_time
>= 0)
2861 Lisp_Object gce
= make_uninit_string (4);
2862 int centisec
= delay_time
* 100.0 + 0.5;
2864 /* Fill the delay time field. */
2865 SSET (gce
, 1, centisec
& 0xff);
2866 SSET (gce
, 2, (centisec
>> 8) & 0xff);
2867 /* We don't know about other fields. */
2870 img
->data
.lisp_val
= Fcons (make_number (0xf9),
2872 img
->data
.lisp_val
));
2874 if (loop_count
>= 0)
2876 Lisp_Object data_sub_block
= make_uninit_string (3);
2878 SSET (data_sub_block
, 0, 0x01);
2879 SSET (data_sub_block
, 1, loop_count
& 0xff);
2880 SSET (data_sub_block
, 2, (loop_count
>> 8) & 0xff);
2881 img
->data
.lisp_val
= Fcons (make_number (0),
2882 Fcons (data_sub_block
,
2883 img
->data
.lisp_val
));
2884 img
->data
.lisp_val
= Fcons (make_number (0xff),
2885 Fcons (build_string ("NETSCAPE2.0"),
2886 img
->data
.lisp_val
));
2889 img
->data
.lisp_val
= Fcons (Qcount
,
2890 Fcons (make_number (count
),
2891 img
->data
.lisp_val
));
2894 /* Maybe fill in the background field while we have ximg handy. */
2895 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2896 IMAGE_BACKGROUND (img
, f
, ximg
);
2898 /* Put the image into the pixmap. */
2899 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2900 x_destroy_x_image (ximg
);
2903 #else /* !USE_MAC_IMAGE_IO */
2904 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2907 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2911 find_image_fsspec (specified_file
, file
, fss
)
2912 Lisp_Object specified_file
, *file
;
2918 *file
= x_find_image_file (specified_file
);
2919 if (!STRINGP (*file
))
2920 return fnfErr
; /* file or directory not found;
2921 incomplete pathname */
2922 /* Try to open the image file. */
2923 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2924 SBYTES (*file
), typeFSS
, &desc
);
2927 #if TARGET_API_MAC_CARBON
2928 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2930 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2932 AEDisposeDesc (&desc
);
2938 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2945 ComponentResult err
;
2946 GraphicsImportComponent gi
;
2949 ImageDescriptionHandle desc_handle
;
2950 short draw_all_pixels
;
2951 Lisp_Object specified_bg
;
2956 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2959 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2964 /* read from file system spec */
2965 err
= GraphicsImportSetDataFile (gi
, fss
);
2968 image_error ("Cannot set fsspec to graphics importer for '%s'",
2975 /* read from data handle */
2976 err
= GraphicsImportSetDataHandle (gi
, dh
);
2979 image_error ("Cannot set data handle to graphics importer for `%s'",
2984 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2985 if (err
!= noErr
|| desc_handle
== NULL
)
2987 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2990 width
= img
->width
= (*desc_handle
)->width
;
2991 height
= img
->height
= (*desc_handle
)->height
;
2992 DisposeHandle ((Handle
)desc_handle
);
2994 if (!check_image_size (f
, width
, height
))
2996 image_error ("Invalid image size", Qnil
, Qnil
);
3000 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
3002 /* Don't check the error code here. It may have an undocumented
3006 image_error ("Error reading `%s'", img
->spec
, Qnil
);
3010 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
3012 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3013 if (!STRINGP (specified_bg
) ||
3014 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
3016 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
3017 color
.red
= RED16_FROM_ULONG (color
.pixel
);
3018 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
3019 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
3023 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
3025 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
3030 GetGWorld (&old_port
, &old_gdh
);
3031 SetGWorld (ximg
, NULL
);
3032 bg_color
.red
= color
.red
;
3033 bg_color
.green
= color
.green
;
3034 bg_color
.blue
= color
.blue
;
3035 RGBBackColor (&bg_color
);
3036 #if TARGET_API_MAC_CARBON
3037 GetPortBounds (ximg
, &rect
);
3040 EraseRect (&(ximg
->portRect
));
3042 SetGWorld (old_port
, old_gdh
);
3044 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
3045 GraphicsImportDraw (gi
);
3046 CloseComponent (gi
);
3048 /* Maybe fill in the background field while we have ximg handy. */
3049 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
3050 IMAGE_BACKGROUND (img
, f
, ximg
);
3052 /* Put the image into the pixmap. */
3053 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
3054 x_destroy_x_image (ximg
);
3058 CloseComponent (gi
);
3063 /* Load an image using the QuickTime Graphics Importer.
3064 Note: The alpha channel does not work for PNG images. */
3066 image_load_quicktime (f
, img
, type
)
3071 Lisp_Object specified_file
;
3072 Lisp_Object specified_data
;
3075 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3076 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3078 if (NILP (specified_data
))
3080 /* Read from a file */
3084 err
= find_image_fsspec (specified_file
, &file
, &fss
);
3088 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3090 image_error ("Cannot open `%s'", file
, Qnil
);
3093 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
3097 /* Memory source! */
3101 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
3104 image_error ("Cannot allocate data handle for `%s'",
3108 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
3117 image_load_quartz2d (f
, img
, png_p
)
3122 Lisp_Object file
, specified_file
;
3123 Lisp_Object specified_data
, specified_bg
;
3124 struct gcpro gcpro1
;
3125 CGDataProviderRef source
;
3129 XImagePtr ximg
= NULL
;
3130 CGContextRef context
;
3133 /* Open the file. */
3134 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3135 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3140 if (NILP (specified_data
))
3145 file
= x_find_image_file (specified_file
);
3146 if (!STRINGP (file
))
3148 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3152 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
3153 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
3154 kCFURLPOSIXPathStyle
, 0);
3156 source
= CGDataProviderCreateWithURL (url
);
3160 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
3161 SBYTES (specified_data
), NULL
);
3163 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3165 image
= CGImageCreateWithPNGDataProvider (source
, NULL
, false,
3166 kCGRenderingIntentDefault
);
3169 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, false,
3170 kCGRenderingIntentDefault
);
3172 CGDataProviderRelease (source
);
3176 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
3179 width
= img
->width
= CGImageGetWidth (image
);
3180 height
= img
->height
= CGImageGetHeight (image
);
3182 if (!check_image_size (f
, width
, height
))
3184 CGImageRelease (image
);
3186 image_error ("Invalid image size", Qnil
, Qnil
);
3192 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3193 if (!STRINGP (specified_bg
) ||
3194 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
3196 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
3197 color
.red
= RED16_FROM_ULONG (color
.pixel
);
3198 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
3199 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
3203 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
3205 CGImageRelease (image
);
3209 rectangle
= CGRectMake (0, 0, width
, height
);
3210 QDBeginCGContext (ximg
, &context
);
3213 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
3214 color
.green
/ 65535.0,
3215 color
.blue
/ 65535.0, 1.0);
3216 CGContextFillRect (context
, rectangle
);
3218 CGContextDrawImage (context
, rectangle
, image
);
3219 QDEndCGContext (ximg
, &context
);
3220 CGImageRelease (image
);
3222 /* Maybe fill in the background field while we have ximg handy. */
3223 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
3224 IMAGE_BACKGROUND (img
, f
, ximg
);
3226 /* Put the image into the pixmap. */
3227 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
3228 x_destroy_x_image (ximg
);
3233 #endif /* !USE_MAC_IMAGE_IO */
3238 /***********************************************************************
3240 ***********************************************************************/
3242 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
3243 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
3244 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
3245 unsigned char *, unsigned char *));
3246 static int xbm_image_p
P_ ((Lisp_Object object
));
3247 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
3248 unsigned char *, unsigned char *,
3249 int *, int *, unsigned char **));
3250 static int xbm_file_p
P_ ((Lisp_Object
));
3253 /* Indices of image specification fields in xbm_format, below. */
3255 enum xbm_keyword_index
3273 /* Vector of image_keyword structures describing the format
3274 of valid XBM image specifications. */
3276 static struct image_keyword xbm_format
[XBM_LAST
] =
3278 {":type", IMAGE_SYMBOL_VALUE
, 1},
3279 {":file", IMAGE_STRING_VALUE
, 0},
3280 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3281 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3282 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3283 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
3284 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
3285 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3286 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3287 {":relief", IMAGE_INTEGER_VALUE
, 0},
3288 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3289 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3290 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
3293 /* Structure describing the image type XBM. */
3295 static struct image_type xbm_type
=
3304 /* Tokens returned from xbm_scan. */
3313 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3314 A valid specification is a list starting with the symbol `image'
3315 The rest of the list is a property list which must contain an
3318 If the specification specifies a file to load, it must contain
3319 an entry `:file FILENAME' where FILENAME is a string.
3321 If the specification is for a bitmap loaded from memory it must
3322 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3323 WIDTH and HEIGHT are integers > 0. DATA may be:
3325 1. a string large enough to hold the bitmap data, i.e. it must
3326 have a size >= (WIDTH + 7) / 8 * HEIGHT
3328 2. a bool-vector of size >= WIDTH * HEIGHT
3330 3. a vector of strings or bool-vectors, one for each line of the
3333 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3334 may not be specified in this case because they are defined in the
3337 Both the file and data forms may contain the additional entries
3338 `:background COLOR' and `:foreground COLOR'. If not present,
3339 foreground and background of the frame on which the image is
3340 displayed is used. */
3343 xbm_image_p (object
)
3346 struct image_keyword kw
[XBM_LAST
];
3348 bcopy (xbm_format
, kw
, sizeof kw
);
3349 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
3352 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
3354 if (kw
[XBM_FILE
].count
)
3356 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
3359 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
3361 /* In-memory XBM file. */
3362 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
3370 /* Entries for `:width', `:height' and `:data' must be present. */
3371 if (!kw
[XBM_WIDTH
].count
3372 || !kw
[XBM_HEIGHT
].count
3373 || !kw
[XBM_DATA
].count
)
3376 data
= kw
[XBM_DATA
].value
;
3377 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
3378 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
3380 /* Check type of data, and width and height against contents of
3386 /* Number of elements of the vector must be >= height. */
3387 if (XVECTOR (data
)->size
< height
)
3390 /* Each string or bool-vector in data must be large enough
3391 for one line of the image. */
3392 for (i
= 0; i
< height
; ++i
)
3394 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
3399 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
3402 else if (BOOL_VECTOR_P (elt
))
3404 if (XBOOL_VECTOR (elt
)->size
< width
)
3411 else if (STRINGP (data
))
3414 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
3417 else if (BOOL_VECTOR_P (data
))
3419 if (XBOOL_VECTOR (data
)->size
< width
* height
)
3430 /* Scan a bitmap file. FP is the stream to read from. Value is
3431 either an enumerator from enum xbm_token, or a character for a
3432 single-character token, or 0 at end of file. If scanning an
3433 identifier, store the lexeme of the identifier in SVAL. If
3434 scanning a number, store its value in *IVAL. */
3437 xbm_scan (s
, end
, sval
, ival
)
3438 unsigned char **s
, *end
;
3446 /* Skip white space. */
3447 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3452 else if (isdigit (c
))
3454 int value
= 0, digit
;
3456 if (c
== '0' && *s
< end
)
3459 if (c
== 'x' || c
== 'X')
3466 else if (c
>= 'a' && c
<= 'f')
3467 digit
= c
- 'a' + 10;
3468 else if (c
>= 'A' && c
<= 'F')
3469 digit
= c
- 'A' + 10;
3472 value
= 16 * value
+ digit
;
3475 else if (isdigit (c
))
3479 && (c
= *(*s
)++, isdigit (c
)))
3480 value
= 8 * value
+ c
- '0';
3487 && (c
= *(*s
)++, isdigit (c
)))
3488 value
= 10 * value
+ c
- '0';
3496 else if (isalpha (c
) || c
== '_')
3500 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3507 else if (c
== '/' && **s
== '*')
3509 /* C-style comment. */
3511 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3525 /* Create a Windows bitmap from X bitmap data. */
3527 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3529 static unsigned char swap_nibble
[16]
3530 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3531 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3532 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3533 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3535 unsigned char *bits
, *p
;
3538 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3539 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3540 bits
= (unsigned char *) alloca (height
* w2
);
3541 bzero (bits
, height
* w2
);
3542 for (i
= 0; i
< height
; i
++)
3545 for (j
= 0; j
< w1
; j
++)
3547 /* Bitswap XBM bytes to match how Windows does things. */
3548 unsigned char c
= *data
++;
3549 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3550 | (swap_nibble
[(c
>>4) & 0xf]));
3553 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3559 convert_mono_to_color_image (f
, img
, foreground
, background
)
3562 COLORREF foreground
, background
;
3564 HDC hdc
, old_img_dc
, new_img_dc
;
3565 HGDIOBJ old_prev
, new_prev
;
3568 hdc
= get_frame_dc (f
);
3569 old_img_dc
= CreateCompatibleDC (hdc
);
3570 new_img_dc
= CreateCompatibleDC (hdc
);
3571 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3572 release_frame_dc (f
, hdc
);
3573 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3574 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3575 /* Windows convention for mono bitmaps is black = background,
3576 white = foreground. */
3577 SetTextColor (new_img_dc
, background
);
3578 SetBkColor (new_img_dc
, foreground
);
3580 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3583 SelectObject (old_img_dc
, old_prev
);
3584 SelectObject (new_img_dc
, new_prev
);
3585 DeleteDC (old_img_dc
);
3586 DeleteDC (new_img_dc
);
3587 DeleteObject (img
->pixmap
);
3588 if (new_pixmap
== 0)
3589 fprintf (stderr
, "Failed to convert image to color.\n");
3591 img
->pixmap
= new_pixmap
;
3594 #define XBM_BIT_SHUFFLE(b) (~(b))
3598 #define XBM_BIT_SHUFFLE(b) (b)
3600 #endif /* HAVE_NTGUI */
3604 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
3608 RGB_PIXEL_COLOR fg
, bg
;
3609 int non_default_colors
;
3613 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3615 /* If colors were specified, transfer the bitmap to a color one. */
3616 if (non_default_colors
)
3617 convert_mono_to_color_image (f
, img
, fg
, bg
);
3619 #elif defined (HAVE_NS)
3620 img
->pixmap
= ns_image_from_XBM(data
, img
->width
, img
->height
);
3624 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3627 img
->width
, img
->height
,
3629 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3630 #endif /* !HAVE_NTGUI && !HAVE_NS */
3635 /* Replacement for XReadBitmapFileData which isn't available under old
3636 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3637 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3638 the image. Return in *DATA the bitmap data allocated with xmalloc.
3639 Value is non-zero if successful. DATA null means just test if
3640 CONTENTS looks like an in-memory XBM file. */
3643 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3645 unsigned char *contents
, *end
;
3646 int *width
, *height
;
3647 unsigned char **data
;
3649 unsigned char *s
= contents
;
3650 char buffer
[BUFSIZ
];
3653 int bytes_per_line
, i
, nbytes
;
3659 LA1 = xbm_scan (&s, end, buffer, &value)
3661 #define expect(TOKEN) \
3662 if (LA1 != (TOKEN)) \
3667 #define expect_ident(IDENT) \
3668 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3673 *width
= *height
= -1;
3676 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3678 /* Parse defines for width, height and hot-spots. */
3682 expect_ident ("define");
3683 expect (XBM_TK_IDENT
);
3685 if (LA1
== XBM_TK_NUMBER
)
3687 char *p
= strrchr (buffer
, '_');
3688 p
= p
? p
+ 1 : buffer
;
3689 if (strcmp (p
, "width") == 0)
3691 else if (strcmp (p
, "height") == 0)
3694 expect (XBM_TK_NUMBER
);
3697 if (!check_image_size (f
, *width
, *height
))
3699 else if (data
== NULL
)
3702 /* Parse bits. Must start with `static'. */
3703 expect_ident ("static");
3704 if (LA1
== XBM_TK_IDENT
)
3706 if (strcmp (buffer
, "unsigned") == 0)
3709 expect_ident ("char");
3711 else if (strcmp (buffer
, "short") == 0)
3715 if (*width
% 16 && *width
% 16 < 9)
3718 else if (strcmp (buffer
, "char") == 0)
3726 expect (XBM_TK_IDENT
);
3732 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3733 nbytes
= bytes_per_line
* *height
;
3734 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3738 for (i
= 0; i
< nbytes
; i
+= 2)
3741 expect (XBM_TK_NUMBER
);
3743 *p
++ = XBM_BIT_SHUFFLE (val
);
3744 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3745 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3747 if (LA1
== ',' || LA1
== '}')
3755 for (i
= 0; i
< nbytes
; ++i
)
3758 expect (XBM_TK_NUMBER
);
3760 *p
++ = XBM_BIT_SHUFFLE (val
);
3762 if (LA1
== ',' || LA1
== '}')
3787 /* Load XBM image IMG which will be displayed on frame F from buffer
3788 CONTENTS. END is the end of the buffer. Value is non-zero if
3792 xbm_load_image (f
, img
, contents
, end
)
3795 unsigned char *contents
, *end
;
3798 unsigned char *data
;
3801 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3804 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3805 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3806 int non_default_colors
= 0;
3809 xassert (img
->width
> 0 && img
->height
> 0);
3811 /* Get foreground and background colors, maybe allocate colors. */
3812 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3815 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3816 non_default_colors
= 1;
3818 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3821 background
= x_alloc_image_color (f
, img
, value
, background
);
3822 img
->background
= background
;
3823 img
->background_valid
= 1;
3824 non_default_colors
= 1;
3827 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3828 foreground
, background
,
3829 non_default_colors
);
3832 if (img
->pixmap
== NO_PIXMAP
)
3834 x_clear_image (f
, img
);
3835 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3841 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3847 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3854 return (STRINGP (data
)
3855 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3862 /* Fill image IMG which is used on frame F with pixmap data. Value is
3863 non-zero if successful. */
3871 Lisp_Object file_name
;
3873 xassert (xbm_image_p (img
->spec
));
3875 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3876 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3877 if (STRINGP (file_name
))
3880 unsigned char *contents
;
3882 struct gcpro gcpro1
;
3884 file
= x_find_image_file (file_name
);
3886 if (!STRINGP (file
))
3888 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3893 contents
= slurp_file (SDATA (file
), &size
);
3894 if (contents
== NULL
)
3896 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3901 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3906 struct image_keyword fmt
[XBM_LAST
];
3908 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3909 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3910 int non_default_colors
= 0;
3913 int in_memory_file_p
= 0;
3915 /* See if data looks like an in-memory XBM file. */
3916 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3917 in_memory_file_p
= xbm_file_p (data
);
3919 /* Parse the image specification. */
3920 bcopy (xbm_format
, fmt
, sizeof fmt
);
3921 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3924 /* Get specified width, and height. */
3925 if (!in_memory_file_p
)
3927 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3928 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3929 xassert (img
->width
> 0 && img
->height
> 0);
3932 /* Get foreground and background colors, maybe allocate colors. */
3933 if (fmt
[XBM_FOREGROUND
].count
3934 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3936 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3938 non_default_colors
= 1;
3941 if (fmt
[XBM_BACKGROUND
].count
3942 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3944 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3946 non_default_colors
= 1;
3949 if (in_memory_file_p
)
3950 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3959 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3961 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3962 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3964 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3966 bcopy (SDATA (line
), p
, nbytes
);
3968 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3971 else if (STRINGP (data
))
3972 bits
= SDATA (data
);
3974 bits
= XBOOL_VECTOR (data
)->data
;
3980 /* Windows mono bitmaps are reversed compared with X. */
3981 invertedBits
= bits
;
3982 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3984 bits
= (char *) alloca(nbytes
);
3985 for (i
= 0; i
< nbytes
; i
++)
3986 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3989 /* Create the pixmap. */
3991 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3992 foreground
, background
,
3993 non_default_colors
);
3998 image_error ("Unable to create pixmap for XBM image `%s'",
4000 x_clear_image (f
, img
);
4010 /***********************************************************************
4012 ***********************************************************************/
4014 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
4016 static int xpm_image_p
P_ ((Lisp_Object object
));
4017 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
4018 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
4020 #endif /* HAVE_XPM || MAC_OS || HAVE_NS */
4024 /* Indicate to xpm.h that we don't have Xlib. */
4026 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
4027 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
4028 #define XColor xpm_XColor
4029 #define XImage xpm_XImage
4030 #define Display xpm_Display
4031 #define PIXEL_ALREADY_TYPEDEFED
4032 #include "X11/xpm.h"
4037 #undef PIXEL_ALREADY_TYPEDEFED
4039 #include "X11/xpm.h"
4040 #endif /* HAVE_NTGUI */
4041 #endif /* HAVE_XPM */
4043 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
4044 /* The symbol `xpm' identifying XPM-format images. */
4048 /* Indices of image specification fields in xpm_format, below. */
4050 enum xpm_keyword_index
4066 /* Vector of image_keyword structures describing the format
4067 of valid XPM image specifications. */
4069 static struct image_keyword xpm_format
[XPM_LAST
] =
4071 {":type", IMAGE_SYMBOL_VALUE
, 1},
4072 {":file", IMAGE_STRING_VALUE
, 0},
4073 {":data", IMAGE_STRING_VALUE
, 0},
4074 {":ascent", IMAGE_ASCENT_VALUE
, 0},
4075 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
4076 {":relief", IMAGE_INTEGER_VALUE
, 0},
4077 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4078 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4079 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4080 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4081 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
4084 /* Structure describing the image type XPM. */
4086 static struct image_type xpm_type
=
4095 #ifdef HAVE_X_WINDOWS
4097 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
4098 functions for allocating image colors. Our own functions handle
4099 color allocation failures more gracefully than the ones on the XPM
4102 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
4103 #define ALLOC_XPM_COLORS
4105 #endif /* HAVE_X_WINDOWS */
4107 #ifdef ALLOC_XPM_COLORS
4109 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
4110 static void xpm_free_color_cache
P_ ((void));
4111 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
4112 static int xpm_color_bucket
P_ ((char *));
4113 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
4116 /* An entry in a hash table used to cache color definitions of named
4117 colors. This cache is necessary to speed up XPM image loading in
4118 case we do color allocations ourselves. Without it, we would need
4119 a call to XParseColor per pixel in the image. */
4121 struct xpm_cached_color
4123 /* Next in collision chain. */
4124 struct xpm_cached_color
*next
;
4126 /* Color definition (RGB and pixel color). */
4133 /* The hash table used for the color cache, and its bucket vector
4136 #define XPM_COLOR_CACHE_BUCKETS 1001
4137 struct xpm_cached_color
**xpm_color_cache
;
4139 /* Initialize the color cache. */
4142 xpm_init_color_cache (f
, attrs
)
4144 XpmAttributes
*attrs
;
4146 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
4147 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
4148 memset (xpm_color_cache
, 0, nbytes
);
4149 init_color_table ();
4151 if (attrs
->valuemask
& XpmColorSymbols
)
4156 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
4157 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4158 attrs
->colorsymbols
[i
].value
, &color
))
4160 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
4162 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
4167 /* Free the color cache. */
4170 xpm_free_color_cache ()
4172 struct xpm_cached_color
*p
, *next
;
4175 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
4176 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
4182 xfree (xpm_color_cache
);
4183 xpm_color_cache
= NULL
;
4184 free_color_table ();
4187 /* Return the bucket index for color named COLOR_NAME in the color
4191 xpm_color_bucket (color_name
)
4197 for (s
= color_name
; *s
; ++s
)
4199 return h
%= XPM_COLOR_CACHE_BUCKETS
;
4203 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4204 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4207 static struct xpm_cached_color
*
4208 xpm_cache_color (f
, color_name
, color
, bucket
)
4215 struct xpm_cached_color
*p
;
4218 bucket
= xpm_color_bucket (color_name
);
4220 nbytes
= sizeof *p
+ strlen (color_name
);
4221 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
4222 strcpy (p
->name
, color_name
);
4224 p
->next
= xpm_color_cache
[bucket
];
4225 xpm_color_cache
[bucket
] = p
;
4229 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4230 return the cached definition in *COLOR. Otherwise, make a new
4231 entry in the cache and allocate the color. Value is zero if color
4232 allocation failed. */
4235 xpm_lookup_color (f
, color_name
, color
)
4240 struct xpm_cached_color
*p
;
4241 int h
= xpm_color_bucket (color_name
);
4243 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
4244 if (strcmp (p
->name
, color_name
) == 0)
4249 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4252 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
4254 p
= xpm_cache_color (f
, color_name
, color
, h
);
4256 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4257 with transparency, and it's useful. */
4258 else if (strcmp ("opaque", color_name
) == 0)
4260 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
4261 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
4262 p
= xpm_cache_color (f
, color_name
, color
, h
);
4269 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4270 CLOSURE is a pointer to the frame on which we allocate the
4271 color. Return in *COLOR the allocated color. Value is non-zero
4275 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
4282 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
4286 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4287 is a pointer to the frame on which we allocate the color. Value is
4288 non-zero if successful. */
4291 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
4301 #endif /* ALLOC_XPM_COLORS */
4306 /* XPM library details. */
4308 DEF_IMGLIB_FN (XpmFreeAttributes
);
4309 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
4310 DEF_IMGLIB_FN (XpmReadFileToImage
);
4311 DEF_IMGLIB_FN (XImageFree
);
4314 init_xpm_functions (Lisp_Object libraries
)
4318 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
4321 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
4322 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
4323 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
4324 LOAD_IMGLIB_FN (library
, XImageFree
);
4328 #endif /* HAVE_NTGUI */
4331 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4332 for XPM images. Such a list must consist of conses whose car and
4336 xpm_valid_color_symbols_p (color_symbols
)
4337 Lisp_Object color_symbols
;
4339 while (CONSP (color_symbols
))
4341 Lisp_Object sym
= XCAR (color_symbols
);
4343 || !STRINGP (XCAR (sym
))
4344 || !STRINGP (XCDR (sym
)))
4346 color_symbols
= XCDR (color_symbols
);
4349 return NILP (color_symbols
);
4353 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4356 xpm_image_p (object
)
4359 struct image_keyword fmt
[XPM_LAST
];
4360 bcopy (xpm_format
, fmt
, sizeof fmt
);
4361 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
4362 /* Either `:file' or `:data' must be present. */
4363 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
4364 /* Either no `:color-symbols' or it's a list of conses
4365 whose car and cdr are strings. */
4366 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
4367 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
4370 #endif /* HAVE_XPM || MAC_OS || HAVE_NS */
4372 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4374 x_create_bitmap_from_xpm_data (f
, bits
)
4378 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4380 XpmAttributes attrs
;
4381 Pixmap bitmap
, mask
;
4383 bzero (&attrs
, sizeof attrs
);
4385 attrs
.visual
= FRAME_X_VISUAL (f
);
4386 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4387 attrs
.valuemask
|= XpmVisual
;
4388 attrs
.valuemask
|= XpmColormap
;
4390 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4391 bits
, &bitmap
, &mask
, &attrs
);
4392 if (rc
!= XpmSuccess
)
4394 XpmFreeAttributes (&attrs
);
4398 id
= x_allocate_bitmap_record (f
);
4399 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
4400 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
4401 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
4402 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
4403 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
4404 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
4405 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
4406 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
4408 XpmFreeAttributes (&attrs
);
4411 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4413 /* Load image IMG which will be displayed on frame F. Value is
4414 non-zero if successful. */
4424 XpmAttributes attrs
;
4425 Lisp_Object specified_file
, color_symbols
;
4428 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
4429 #endif /* HAVE_NTGUI */
4431 /* Configure the XPM lib. Use the visual of frame F. Allocate
4432 close colors. Return colors allocated. */
4433 bzero (&attrs
, sizeof attrs
);
4436 attrs
.visual
= FRAME_X_VISUAL (f
);
4437 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4438 attrs
.valuemask
|= XpmVisual
;
4439 attrs
.valuemask
|= XpmColormap
;
4440 #endif /* HAVE_NTGUI */
4442 #ifdef ALLOC_XPM_COLORS
4443 /* Allocate colors with our own functions which handle
4444 failing color allocation more gracefully. */
4445 attrs
.color_closure
= f
;
4446 attrs
.alloc_color
= xpm_alloc_color
;
4447 attrs
.free_colors
= xpm_free_colors
;
4448 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
4449 #else /* not ALLOC_XPM_COLORS */
4450 /* Let the XPM lib allocate colors. */
4451 attrs
.valuemask
|= XpmReturnAllocPixels
;
4452 #ifdef XpmAllocCloseColors
4453 attrs
.alloc_close_colors
= 1;
4454 attrs
.valuemask
|= XpmAllocCloseColors
;
4455 #else /* not XpmAllocCloseColors */
4456 attrs
.closeness
= 600;
4457 attrs
.valuemask
|= XpmCloseness
;
4458 #endif /* not XpmAllocCloseColors */
4459 #endif /* ALLOC_XPM_COLORS */
4461 /* If image specification contains symbolic color definitions, add
4462 these to `attrs'. */
4463 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4464 if (CONSP (color_symbols
))
4467 XpmColorSymbol
*xpm_syms
;
4470 attrs
.valuemask
|= XpmColorSymbols
;
4472 /* Count number of symbols. */
4473 attrs
.numsymbols
= 0;
4474 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4477 /* Allocate an XpmColorSymbol array. */
4478 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4479 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4480 bzero (xpm_syms
, size
);
4481 attrs
.colorsymbols
= xpm_syms
;
4483 /* Fill the color symbol array. */
4484 for (tail
= color_symbols
, i
= 0;
4486 ++i
, tail
= XCDR (tail
))
4488 Lisp_Object name
= XCAR (XCAR (tail
));
4489 Lisp_Object color
= XCDR (XCAR (tail
));
4490 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4491 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4492 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4493 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4497 /* Create a pixmap for the image, either from a file, or from a
4498 string buffer containing data in the same format as an XPM file. */
4499 #ifdef ALLOC_XPM_COLORS
4500 xpm_init_color_cache (f
, &attrs
);
4503 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4507 HDC frame_dc
= get_frame_dc (f
);
4508 hdc
= CreateCompatibleDC (frame_dc
);
4509 release_frame_dc (f
, frame_dc
);
4511 #endif /* HAVE_NTGUI */
4513 if (STRINGP (specified_file
))
4515 Lisp_Object file
= x_find_image_file (specified_file
);
4516 if (!STRINGP (file
))
4518 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4523 /* XpmReadFileToPixmap is not available in the Windows port of
4524 libxpm. But XpmReadFileToImage almost does what we want. */
4525 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4526 &xpm_image
, &xpm_mask
,
4529 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4530 SDATA (file
), &img
->pixmap
, &img
->mask
,
4532 #endif /* HAVE_NTGUI */
4536 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4538 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4539 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4540 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4541 &xpm_image
, &xpm_mask
,
4544 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4546 &img
->pixmap
, &img
->mask
,
4548 #endif /* HAVE_NTGUI */
4551 if (rc
== XpmSuccess
)
4553 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4554 img
->colors
= colors_in_color_table (&img
->ncolors
);
4555 #else /* not ALLOC_XPM_COLORS */
4559 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4560 plus some duplicate attributes. */
4561 if (xpm_image
&& xpm_image
->bitmap
)
4563 img
->pixmap
= xpm_image
->bitmap
;
4564 /* XImageFree in libXpm frees XImage struct without destroying
4565 the bitmap, which is what we want. */
4566 fn_XImageFree (xpm_image
);
4568 if (xpm_mask
&& xpm_mask
->bitmap
)
4570 /* The mask appears to be inverted compared with what we expect.
4571 TODO: invert our expectations. See other places where we
4572 have to invert bits because our idea of masks is backwards. */
4574 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4576 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4577 SelectObject (hdc
, old_obj
);
4579 img
->mask
= xpm_mask
->bitmap
;
4580 fn_XImageFree (xpm_mask
);
4585 #endif /* HAVE_NTGUI */
4587 /* Remember allocated colors. */
4588 img
->ncolors
= attrs
.nalloc_pixels
;
4589 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4590 * sizeof *img
->colors
);
4591 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4593 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4594 #ifdef DEBUG_X_COLORS
4595 register_color (img
->colors
[i
]);
4598 #endif /* not ALLOC_XPM_COLORS */
4600 img
->width
= attrs
.width
;
4601 img
->height
= attrs
.height
;
4602 xassert (img
->width
> 0 && img
->height
> 0);
4604 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4606 fn_XpmFreeAttributes (&attrs
);
4608 XpmFreeAttributes (&attrs
);
4609 #endif /* HAVE_NTGUI */
4615 #endif /* HAVE_NTGUI */
4620 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4623 case XpmFileInvalid
:
4624 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4628 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4631 case XpmColorFailed
:
4632 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4636 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4641 #ifdef ALLOC_XPM_COLORS
4642 xpm_free_color_cache ();
4644 return rc
== XpmSuccess
;
4647 #endif /* HAVE_XPM */
4649 #if defined (MAC_OS) || ( defined (HAVE_NS) && !defined (HAVE_XPM) )
4651 /* XPM support functions for Mac OS where libxpm is not available.
4652 Only XPM version 3 (without any extensions) is supported. */
4654 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4655 const unsigned char **, int *));
4656 static Lisp_Object xpm_make_color_table_v
4657 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4658 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4659 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4661 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4662 const unsigned char *, int));
4663 static Lisp_Object xpm_make_color_table_h
4664 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4665 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4666 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4668 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4669 const unsigned char *, int));
4670 static int xpm_str_to_color_key
P_ ((const char *));
4671 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4672 const unsigned char *, const unsigned char *));
4674 /* Tokens returned from xpm_scan. */
4683 /* Scan an XPM data and return a character (< 256) or a token defined
4684 by enum xpm_token above. *S and END are the start (inclusive) and
4685 the end (exclusive) addresses of the data, respectively. Advance
4686 *S while scanning. If token is either XPM_TK_IDENT or
4687 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4688 length of the corresponding token, respectively. */
4691 xpm_scan (s
, end
, beg
, len
)
4692 const unsigned char **s
, *end
, **beg
;
4699 /* Skip white-space. */
4700 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4703 /* gnus-pointer.xpm uses '-' in its identifier.
4704 sb-dir-plus.xpm uses '+' in its identifier. */
4705 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4709 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4712 return XPM_TK_IDENT
;
4717 while (*s
< end
&& **s
!= '"')
4722 return XPM_TK_STRING
;
4726 if (*s
< end
&& **s
== '*')
4728 /* C-style comment. */
4732 while (*s
< end
&& *(*s
)++ != '*')
4735 while (*s
< end
&& **s
!= '/');
4749 /* Functions for color table lookup in XPM data. A key is a string
4750 specifying the color of each pixel in XPM data. A value is either
4751 an integer that specifies a pixel color, Qt that specifies
4752 transparency, or Qnil for the unspecified color. If the length of
4753 the key string is one, a vector is used as a table. Otherwise, a
4754 hash table is used. */
4757 xpm_make_color_table_v (put_func
, get_func
)
4758 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4759 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4761 *put_func
= xpm_put_color_table_v
;
4762 *get_func
= xpm_get_color_table_v
;
4763 return Fmake_vector (make_number (256), Qnil
);
4767 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4768 Lisp_Object color_table
;
4769 const unsigned char *chars_start
;
4773 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4777 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4778 Lisp_Object color_table
;
4779 const unsigned char *chars_start
;
4782 return XVECTOR (color_table
)->contents
[*chars_start
];
4786 xpm_make_color_table_h (put_func
, get_func
)
4787 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4788 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4790 *put_func
= xpm_put_color_table_h
;
4791 *get_func
= xpm_get_color_table_h
;
4792 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4793 make_float (DEFAULT_REHASH_SIZE
),
4794 make_float (DEFAULT_REHASH_THRESHOLD
),
4799 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4800 Lisp_Object color_table
;
4801 const unsigned char *chars_start
;
4805 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4807 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4809 hash_lookup (table
, chars
, &hash_code
);
4810 hash_put (table
, chars
, color
, hash_code
);
4814 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4815 Lisp_Object color_table
;
4816 const unsigned char *chars_start
;
4819 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4820 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4823 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4826 enum xpm_color_key
{
4834 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4837 xpm_str_to_color_key (s
)
4843 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4845 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4851 xpm_load_image (f
, img
, contents
, end
)
4854 const unsigned char *contents
, *end
;
4856 const unsigned char *s
= contents
, *beg
, *str
;
4857 unsigned char buffer
[BUFSIZ
];
4858 int width
, height
, x
, y
;
4859 int num_colors
, chars_per_pixel
;
4861 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4862 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4863 Lisp_Object frame
, color_symbols
, color_table
;
4864 int best_key
, have_mask
= 0;
4865 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4868 LA1 = xpm_scan (&s, end, &beg, &len)
4870 #define expect(TOKEN) \
4871 if (LA1 != (TOKEN)) \
4876 #define expect_ident(IDENT) \
4877 if (LA1 == XPM_TK_IDENT \
4878 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4883 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4887 expect_ident ("static");
4888 expect_ident ("char");
4890 expect (XPM_TK_IDENT
);
4895 expect (XPM_TK_STRING
);
4898 memcpy (buffer
, beg
, len
);
4900 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4901 &num_colors
, &chars_per_pixel
) != 4
4902 || width
<= 0 || height
<= 0
4903 || num_colors
<= 0 || chars_per_pixel
<= 0)
4906 if (!check_image_size (f
, width
, height
))
4908 image_error ("Invalid image size", Qnil
, Qnil
);
4914 XSETFRAME (frame
, f
);
4915 if (!NILP (Fxw_display_color_p (frame
)))
4916 best_key
= XPM_COLOR_KEY_C
;
4917 else if (!NILP (Fx_display_grayscale_p (frame
)))
4918 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4919 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4921 best_key
= XPM_COLOR_KEY_M
;
4923 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4924 if (chars_per_pixel
== 1)
4925 color_table
= xpm_make_color_table_v (&put_color_table
,
4928 color_table
= xpm_make_color_table_h (&put_color_table
,
4931 while (num_colors
-- > 0)
4933 unsigned char *color
, *max_color
;
4934 int key
, next_key
, max_key
= 0;
4935 Lisp_Object symbol_color
= Qnil
, color_val
;
4938 expect (XPM_TK_STRING
);
4939 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4941 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4942 buffer
[len
- chars_per_pixel
] = '\0';
4944 str
= strtok (buffer
, " \t");
4947 key
= xpm_str_to_color_key (str
);
4952 color
= strtok (NULL
, " \t");
4956 while ((str
= strtok (NULL
, " \t")) != NULL
)
4958 next_key
= xpm_str_to_color_key (str
);
4961 color
[strlen (color
)] = ' ';
4964 if (key
== XPM_COLOR_KEY_S
)
4966 if (NILP (symbol_color
))
4967 symbol_color
= build_string (color
);
4969 else if (max_key
< key
&& key
<= best_key
)
4979 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4981 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4983 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4985 if (xstrcasecmp (SDATA (XCDR (specified_color
)), "None") == 0)
4987 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4989 color_val
= make_number (cdef
.pixel
);
4992 if (NILP (color_val
) && max_key
> 0)
4994 if (xstrcasecmp (max_color
, "None") == 0)
4996 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4997 color_val
= make_number (cdef
.pixel
);
4999 if (!NILP (color_val
))
5000 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
5005 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5006 &ximg
, &img
->pixmap
)
5008 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
5009 &mask_img
, &img
->mask
)
5013 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
5017 for (y
= 0; y
< height
; y
++)
5019 expect (XPM_TK_STRING
);
5021 if (len
< width
* chars_per_pixel
)
5023 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
5025 Lisp_Object color_val
=
5026 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
5028 XPutPixel (ximg
, x
, y
,
5029 (INTEGERP (color_val
) ? XINT (color_val
)
5030 : FRAME_FOREGROUND_PIXEL (f
)));
5032 XPutPixel (mask_img
, x
, y
,
5033 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
5034 : (have_mask
= 1, PIX_MASK_RETAIN
)));
5036 if (EQ(color_val
, Qt
))
5037 ns_set_alpha(ximg
, x
, y
, 0);
5045 img
->height
= height
;
5047 /* Maybe fill in the background field while we have ximg handy. */
5048 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5049 IMAGE_BACKGROUND (img
, f
, ximg
);
5051 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5052 x_destroy_x_image (ximg
);
5056 /* Fill in the background_transparent field while we have the
5058 image_background_transparent (img
, f
, mask_img
);
5060 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
5061 x_destroy_x_image (mask_img
);
5065 x_destroy_x_image (mask_img
);
5066 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5067 img
->mask
= NO_PIXMAP
;
5073 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
5075 x_destroy_x_image (ximg
);
5076 x_destroy_x_image (mask_img
);
5077 x_clear_image (f
, img
);
5091 Lisp_Object file_name
;
5093 /* If IMG->spec specifies a file name, create a non-file spec from it. */
5094 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
5095 if (STRINGP (file_name
))
5098 unsigned char *contents
;
5100 struct gcpro gcpro1
;
5102 file
= x_find_image_file (file_name
);
5104 if (!STRINGP (file
))
5106 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
5111 contents
= slurp_file (SDATA (file
), &size
);
5112 if (contents
== NULL
)
5114 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
5119 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
5127 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5128 success_p
= xpm_load_image (f
, img
, SDATA (data
),
5129 SDATA (data
) + SBYTES (data
));
5135 #endif /* MAC_OS || (HAVE_NS && !HAVE_XPM) */
5139 /***********************************************************************
5141 ***********************************************************************/
5143 #ifdef COLOR_TABLE_SUPPORT
5145 /* An entry in the color table mapping an RGB color to a pixel color. */
5150 unsigned long pixel
;
5152 /* Next in color table collision list. */
5153 struct ct_color
*next
;
5156 /* The bucket vector size to use. Must be prime. */
5160 /* Value is a hash of the RGB color given by R, G, and B. */
5162 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5164 /* The color hash table. */
5166 struct ct_color
**ct_table
;
5168 /* Number of entries in the color table. */
5170 int ct_colors_allocated
;
5172 /* Initialize the color table. */
5177 int size
= CT_SIZE
* sizeof (*ct_table
);
5178 ct_table
= (struct ct_color
**) xmalloc (size
);
5179 bzero (ct_table
, size
);
5180 ct_colors_allocated
= 0;
5184 /* Free memory associated with the color table. */
5190 struct ct_color
*p
, *next
;
5192 for (i
= 0; i
< CT_SIZE
; ++i
)
5193 for (p
= ct_table
[i
]; p
; p
= next
)
5204 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5205 entry for that color already is in the color table, return the
5206 pixel color of that entry. Otherwise, allocate a new color for R,
5207 G, B, and make an entry in the color table. */
5209 static unsigned long
5210 lookup_rgb_color (f
, r
, g
, b
)
5214 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
5215 int i
= hash
% CT_SIZE
;
5217 Display_Info
*dpyinfo
;
5219 /* Handle TrueColor visuals specially, which improves performance by
5220 two orders of magnitude. Freeing colors on TrueColor visuals is
5221 a nop, and pixel colors specify RGB values directly. See also
5222 the Xlib spec, chapter 3.1. */
5223 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5224 if (dpyinfo
->red_bits
> 0)
5226 unsigned long pr
, pg
, pb
;
5228 /* Apply gamma-correction like normal color allocation does. */
5232 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
5233 gamma_correct (f
, &color
);
5234 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
5237 /* Scale down RGB values to the visual's bits per RGB, and shift
5238 them to the right position in the pixel color. Note that the
5239 original RGB values are 16-bit values, as usual in X. */
5240 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
5241 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
5242 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
5244 /* Assemble the pixel color. */
5245 return pr
| pg
| pb
;
5248 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5249 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
5255 #ifdef HAVE_X_WINDOWS
5264 cmap
= FRAME_X_COLORMAP (f
);
5265 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5268 ++ct_colors_allocated
;
5269 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5273 p
->pixel
= color
.pixel
;
5274 p
->next
= ct_table
[i
];
5278 return FRAME_FOREGROUND_PIXEL (f
);
5283 color
= PALETTERGB (r
, g
, b
);
5285 color
= RGB_TO_ULONG (r
, g
, b
);
5286 #endif /* HAVE_NTGUI */
5287 ++ct_colors_allocated
;
5288 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5293 p
->next
= ct_table
[i
];
5295 #endif /* HAVE_X_WINDOWS */
5303 /* Look up pixel color PIXEL which is used on frame F in the color
5304 table. If not already present, allocate it. Value is PIXEL. */
5306 static unsigned long
5307 lookup_pixel_color (f
, pixel
)
5309 unsigned long pixel
;
5311 int i
= pixel
% CT_SIZE
;
5314 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5315 if (p
->pixel
== pixel
)
5324 #ifdef HAVE_X_WINDOWS
5325 cmap
= FRAME_X_COLORMAP (f
);
5326 color
.pixel
= pixel
;
5327 x_query_color (f
, &color
);
5328 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5331 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
5332 color
.pixel
= pixel
;
5333 XQueryColor (NULL
, cmap
, &color
);
5334 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5336 #endif /* HAVE_X_WINDOWS */
5340 ++ct_colors_allocated
;
5342 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5347 p
->next
= ct_table
[i
];
5351 return FRAME_FOREGROUND_PIXEL (f
);
5357 /* Value is a vector of all pixel colors contained in the color table,
5358 allocated via xmalloc. Set *N to the number of colors. */
5360 static unsigned long *
5361 colors_in_color_table (n
)
5366 unsigned long *colors
;
5368 if (ct_colors_allocated
== 0)
5375 colors
= (unsigned long *) xmalloc (ct_colors_allocated
5377 *n
= ct_colors_allocated
;
5379 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
5380 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5381 colors
[j
++] = p
->pixel
;
5387 #else /* COLOR_TABLE_SUPPORT */
5389 static unsigned long
5390 lookup_rgb_color (f
, r
, g
, b
)
5394 unsigned long pixel
;
5397 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5398 gamma_correct (f
, &pixel
);
5402 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
5403 #endif /* HAVE_NTGUI */
5406 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5407 #endif /* HAVE_NS */
5415 #endif /* COLOR_TABLE_SUPPORT */
5418 /***********************************************************************
5420 ***********************************************************************/
5422 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
5423 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
5424 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
5427 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
5428 #endif /* HAVE_NTGUI */
5430 /* Non-zero means draw a cross on images having `:conversion
5433 int cross_disabled_images
;
5435 /* Edge detection matrices for different edge-detection
5438 static int emboss_matrix
[9] = {
5440 2, -1, 0, /* y - 1 */
5442 0, 1, -2 /* y + 1 */
5445 static int laplace_matrix
[9] = {
5447 1, 0, 0, /* y - 1 */
5449 0, 0, -1 /* y + 1 */
5452 /* Value is the intensity of the color whose red/green/blue values
5455 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5458 /* On frame F, return an array of XColor structures describing image
5459 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5460 non-zero means also fill the red/green/blue members of the XColor
5461 structures. Value is a pointer to the array of XColors structures,
5462 allocated with xmalloc; it must be freed by the caller. */
5465 x_to_xcolors (f
, img
, rgb_p
)
5472 XImagePtr_or_DC ximg
;
5476 #endif /* HAVE_NTGUI */
5478 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5481 /* Get the X image IMG->pixmap. */
5482 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5483 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5485 /* Load the image into a memory device context. */
5486 hdc
= get_frame_dc (f
);
5487 ximg
= CreateCompatibleDC (hdc
);
5488 release_frame_dc (f
, hdc
);
5489 prev
= SelectObject (ximg
, img
->pixmap
);
5490 #endif /* HAVE_NTGUI */
5492 /* Fill the `pixel' members of the XColor array. I wished there
5493 were an easy and portable way to circumvent XGetPixel. */
5495 for (y
= 0; y
< img
->height
; ++y
)
5499 #ifdef HAVE_X_WINDOWS
5500 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5501 p
->pixel
= XGetPixel (ximg
, x
, y
);
5503 x_query_colors (f
, row
, img
->width
);
5507 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5509 /* W32_TODO: palette support needed here? */
5510 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5513 #if defined (MAC_OS) || defined (HAVE_NS)
5514 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5515 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5516 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5519 p
->red
= 256 * GetRValue (p
->pixel
);
5520 p
->green
= 256 * GetGValue (p
->pixel
);
5521 p
->blue
= 256 * GetBValue (p
->pixel
);
5522 #endif /* HAVE_NTGUI */
5525 #endif /* HAVE_X_WINDOWS */
5528 Destroy_Image (ximg
, prev
);
5535 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5536 created with CreateDIBSection, with the pointer to the bit values
5537 stored in ximg->data. */
5540 XPutPixel (ximg
, x
, y
, color
)
5545 int width
= ximg
->info
.bmiHeader
.biWidth
;
5546 int height
= ximg
->info
.bmiHeader
.biHeight
;
5547 unsigned char * pixel
;
5549 /* True color images. */
5550 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5552 int rowbytes
= width
* 3;
5553 /* Ensure scanlines are aligned on 4 byte boundaries. */
5555 rowbytes
+= 4 - (rowbytes
% 4);
5557 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5558 /* Windows bitmaps are in BGR order. */
5559 *pixel
= GetBValue (color
);
5560 *(pixel
+ 1) = GetGValue (color
);
5561 *(pixel
+ 2) = GetRValue (color
);
5563 /* Monochrome images. */
5564 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5566 int rowbytes
= width
/ 8;
5567 /* Ensure scanlines are aligned on 4 byte boundaries. */
5569 rowbytes
+= 4 - (rowbytes
% 4);
5570 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5571 /* Filter out palette info. */
5572 if (color
& 0x00ffffff)
5573 *pixel
= *pixel
| (1 << x
% 8);
5575 *pixel
= *pixel
& ~(1 << x
% 8);
5578 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5581 #endif /* HAVE_NTGUI */
5583 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5584 RGB members are set. F is the frame on which this all happens.
5585 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5588 x_from_xcolors (f
, img
, colors
)
5594 XImagePtr oimg
= NULL
;
5598 init_color_table ();
5600 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5603 for (y
= 0; y
< img
->height
; ++y
)
5604 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5606 unsigned long pixel
;
5607 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5608 XPutPixel (oimg
, x
, y
, pixel
);
5612 x_clear_image_1 (f
, img
, 1, 0, 1);
5614 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5615 x_destroy_x_image (oimg
);
5616 img
->pixmap
= pixmap
;
5617 #ifdef COLOR_TABLE_SUPPORT
5618 img
->colors
= colors_in_color_table (&img
->ncolors
);
5619 free_color_table ();
5620 #endif /* COLOR_TABLE_SUPPORT */
5624 /* On frame F, perform edge-detection on image IMG.
5626 MATRIX is a nine-element array specifying the transformation
5627 matrix. See emboss_matrix for an example.
5629 COLOR_ADJUST is a color adjustment added to each pixel of the
5633 x_detect_edges (f
, img
, matrix
, color_adjust
)
5636 int matrix
[9], color_adjust
;
5638 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5642 for (i
= sum
= 0; i
< 9; ++i
)
5643 sum
+= eabs (matrix
[i
]);
5645 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5647 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5649 for (y
= 0; y
< img
->height
; ++y
)
5651 p
= COLOR (new, 0, y
);
5652 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5653 p
= COLOR (new, img
->width
- 1, y
);
5654 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5657 for (x
= 1; x
< img
->width
- 1; ++x
)
5659 p
= COLOR (new, x
, 0);
5660 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5661 p
= COLOR (new, x
, img
->height
- 1);
5662 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5665 for (y
= 1; y
< img
->height
- 1; ++y
)
5667 p
= COLOR (new, 1, y
);
5669 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5671 int r
, g
, b
, y1
, x1
;
5674 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5675 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5678 XColor
*t
= COLOR (colors
, x1
, y1
);
5679 r
+= matrix
[i
] * t
->red
;
5680 g
+= matrix
[i
] * t
->green
;
5681 b
+= matrix
[i
] * t
->blue
;
5684 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5685 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5686 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5687 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5692 x_from_xcolors (f
, img
, new);
5698 /* Perform the pre-defined `emboss' edge-detection on image IMG
5706 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5710 /* Transform image IMG which is used on frame F with a Laplace
5711 edge-detection algorithm. The result is an image that can be used
5712 to draw disabled buttons, for example. */
5719 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5723 /* Perform edge-detection on image IMG on frame F, with specified
5724 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5726 MATRIX must be either
5728 - a list of at least 9 numbers in row-major form
5729 - a vector of at least 9 numbers
5731 COLOR_ADJUST nil means use a default; otherwise it must be a
5735 x_edge_detection (f
, img
, matrix
, color_adjust
)
5738 Lisp_Object matrix
, color_adjust
;
5746 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5747 ++i
, matrix
= XCDR (matrix
))
5748 trans
[i
] = XFLOATINT (XCAR (matrix
));
5750 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5752 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5753 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5756 if (NILP (color_adjust
))
5757 color_adjust
= make_number (0xffff / 2);
5759 if (i
== 9 && NUMBERP (color_adjust
))
5760 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5764 /* Transform image IMG on frame F so that it looks disabled. */
5767 x_disable_image (f
, img
)
5771 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5773 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5775 int n_planes
= dpyinfo
->n_planes
;
5776 #endif /* HAVE_NTGUI */
5780 /* Color (or grayscale). Convert to gray, and equalize. Just
5781 drawing such images with a stipple can look very odd, so
5782 we're using this method instead. */
5783 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5785 const int h
= 15000;
5786 const int l
= 30000;
5788 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5792 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5793 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5794 p
->red
= p
->green
= p
->blue
= i2
;
5797 x_from_xcolors (f
, img
, colors
);
5800 /* Draw a cross over the disabled image, if we must or if we
5802 if (n_planes
< 2 || cross_disabled_images
)
5805 Display
*dpy
= FRAME_X_DISPLAY (f
);
5808 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5811 #define MaskForeground(f) PIX_MASK_DRAW
5813 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5816 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5817 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5818 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5819 img
->width
- 1, img
->height
- 1);
5820 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5826 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5827 XSetForeground (dpy
, gc
, MaskForeground (f
));
5828 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5829 img
->width
- 1, img
->height
- 1);
5830 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5834 #endif /* !HAVE_NS */
5839 hdc
= get_frame_dc (f
);
5840 bmpdc
= CreateCompatibleDC (hdc
);
5841 release_frame_dc (f
, hdc
);
5843 prev
= SelectObject (bmpdc
, img
->pixmap
);
5845 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5846 MoveToEx (bmpdc
, 0, 0, NULL
);
5847 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5848 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5849 LineTo (bmpdc
, img
->width
- 1, 0);
5853 SelectObject (bmpdc
, img
->mask
);
5854 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5855 MoveToEx (bmpdc
, 0, 0, NULL
);
5856 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5857 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5858 LineTo (bmpdc
, img
->width
- 1, 0);
5860 SelectObject (bmpdc
, prev
);
5862 #endif /* HAVE_NTGUI */
5867 /* Build a mask for image IMG which is used on frame F. FILE is the
5868 name of an image file, for error messages. HOW determines how to
5869 determine the background color of IMG. If it is a list '(R G B)',
5870 with R, G, and B being integers >= 0, take that as the color of the
5871 background. Otherwise, determine the background color of IMG
5872 heuristically. Value is non-zero if successful. */
5875 x_build_heuristic_mask (f
, img
, how
)
5880 XImagePtr_or_DC ximg
;
5888 #endif /* HAVE_NTGUI */
5889 int x
, y
, rc
, use_img_background
;
5890 unsigned long bg
= 0;
5894 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5895 img
->mask
= NO_PIXMAP
;
5896 img
->background_transparent_valid
= 0;
5901 /* Create an image and pixmap serving as mask. */
5902 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5903 &mask_img
, &img
->mask
);
5906 #endif /* !HAVE_NS */
5908 /* Get the X image of IMG->pixmap. */
5909 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5910 img
->width
, img
->height
,
5913 /* Create the bit array serving as mask. */
5914 row_width
= (img
->width
+ 7) / 8;
5915 mask_img
= xmalloc (row_width
* img
->height
);
5916 bzero (mask_img
, row_width
* img
->height
);
5918 /* Create a memory device context for IMG->pixmap. */
5919 frame_dc
= get_frame_dc (f
);
5920 ximg
= CreateCompatibleDC (frame_dc
);
5921 release_frame_dc (f
, frame_dc
);
5922 prev
= SelectObject (ximg
, img
->pixmap
);
5923 #endif /* HAVE_NTGUI */
5925 /* Determine the background color of ximg. If HOW is `(R G B)'
5926 take that as color. Otherwise, use the image's background color. */
5927 use_img_background
= 1;
5933 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5935 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5939 if (i
== 3 && NILP (how
))
5941 char color_name
[30];
5942 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5945 0x00ffffff & /* Filter out palette info. */
5946 #endif /* HAVE_NTGUI */
5947 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5948 use_img_background
= 0;
5952 if (use_img_background
)
5953 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5955 /* Set all bits in mask_img to 1 whose color in ximg is different
5956 from the background color bg. */
5958 for (y
= 0; y
< img
->height
; ++y
)
5959 for (x
= 0; x
< img
->width
; ++x
)
5961 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5962 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5964 if (XGetPixel (ximg
, x
, y
) == bg
)
5965 ns_set_alpha(ximg
, x
, y
, 0);
5966 #endif /* HAVE_NS */
5968 /* Fill in the background_transparent field while we have the mask handy. */
5969 image_background_transparent (img
, f
, mask_img
);
5971 /* Put mask_img into img->mask. */
5972 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5973 x_destroy_x_image (mask_img
);
5974 #endif /* !HAVE_NS */
5976 for (y
= 0; y
< img
->height
; ++y
)
5977 for (x
= 0; x
< img
->width
; ++x
)
5979 COLORREF p
= GetPixel (ximg
, x
, y
);
5981 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5984 /* Create the mask image. */
5985 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5987 /* Fill in the background_transparent field while we have the mask handy. */
5988 SelectObject (ximg
, img
->mask
);
5989 image_background_transparent (img
, f
, ximg
);
5991 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5993 #endif /* HAVE_NTGUI */
5995 Destroy_Image (ximg
, prev
);
6001 /***********************************************************************
6002 PBM (mono, gray, color)
6003 ***********************************************************************/
6005 static int pbm_image_p
P_ ((Lisp_Object object
));
6006 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
6007 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
6009 /* The symbol `pbm' identifying images of this type. */
6013 /* Indices of image specification fields in gs_format, below. */
6015 enum pbm_keyword_index
6031 /* Vector of image_keyword structures describing the format
6032 of valid user-defined image specifications. */
6034 static struct image_keyword pbm_format
[PBM_LAST
] =
6036 {":type", IMAGE_SYMBOL_VALUE
, 1},
6037 {":file", IMAGE_STRING_VALUE
, 0},
6038 {":data", IMAGE_STRING_VALUE
, 0},
6039 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6040 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6041 {":relief", IMAGE_INTEGER_VALUE
, 0},
6042 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6043 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6044 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6045 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
6046 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6049 /* Structure describing the image type `pbm'. */
6051 static struct image_type pbm_type
=
6061 /* Return non-zero if OBJECT is a valid PBM image specification. */
6064 pbm_image_p (object
)
6067 struct image_keyword fmt
[PBM_LAST
];
6069 bcopy (pbm_format
, fmt
, sizeof fmt
);
6071 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
6074 /* Must specify either :data or :file. */
6075 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
6079 /* Scan a decimal number from *S and return it. Advance *S while
6080 reading the number. END is the end of the string. Value is -1 at
6084 pbm_scan_number (s
, end
)
6085 unsigned char **s
, *end
;
6087 int c
= 0, val
= -1;
6091 /* Skip white-space. */
6092 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
6097 /* Skip comment to end of line. */
6098 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
6101 else if (isdigit (c
))
6103 /* Read decimal number. */
6105 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
6106 val
= 10 * val
+ c
- '0';
6118 #if 0 /* Unused. ++kfs */
6120 /* Read FILE into memory. Value is a pointer to a buffer allocated
6121 with xmalloc holding FILE's contents. Value is null if an error
6122 occurred. *SIZE is set to the size of the file. */
6125 pbm_read_file (file
, size
)
6133 if (stat (SDATA (file
), &st
) == 0
6134 && (fp
= fopen (SDATA (file
), "rb")) != NULL
6135 && (buf
= (char *) xmalloc (st
.st_size
),
6136 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6155 #endif /* HAVE_NTGUI */
6157 /* Load PBM image IMG for use on frame F. */
6165 int width
, height
, max_color_idx
= 0;
6167 Lisp_Object file
, specified_file
;
6168 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
6169 struct gcpro gcpro1
;
6170 unsigned char *contents
= NULL
;
6171 unsigned char *end
, *p
;
6174 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6178 if (STRINGP (specified_file
))
6180 file
= x_find_image_file (specified_file
);
6181 if (!STRINGP (file
))
6183 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6188 contents
= slurp_file (SDATA (file
), &size
);
6189 if (contents
== NULL
)
6191 image_error ("Error reading `%s'", file
, Qnil
);
6197 end
= contents
+ size
;
6202 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6204 end
= p
+ SBYTES (data
);
6207 /* Check magic number. */
6208 if (end
- p
< 2 || *p
++ != 'P')
6210 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6220 raw_p
= 0, type
= PBM_MONO
;
6224 raw_p
= 0, type
= PBM_GRAY
;
6228 raw_p
= 0, type
= PBM_COLOR
;
6232 raw_p
= 1, type
= PBM_MONO
;
6236 raw_p
= 1, type
= PBM_GRAY
;
6240 raw_p
= 1, type
= PBM_COLOR
;
6244 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6248 /* Read width, height, maximum color-component. Characters
6249 starting with `#' up to the end of a line are ignored. */
6250 width
= pbm_scan_number (&p
, end
);
6251 height
= pbm_scan_number (&p
, end
);
6253 if (type
!= PBM_MONO
)
6255 max_color_idx
= pbm_scan_number (&p
, end
);
6256 if (max_color_idx
> 65535 || max_color_idx
< 0)
6258 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
6263 if (!check_image_size (f
, width
, height
))
6265 image_error ("Invalid image size", Qnil
, Qnil
);
6269 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
6270 &ximg
, &img
->pixmap
))
6273 /* Initialize the color hash table. */
6274 init_color_table ();
6276 if (type
== PBM_MONO
)
6279 struct image_keyword fmt
[PBM_LAST
];
6280 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
6281 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
6283 /* Parse the image specification. */
6284 bcopy (pbm_format
, fmt
, sizeof fmt
);
6285 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
6287 /* Get foreground and background colors, maybe allocate colors. */
6288 if (fmt
[PBM_FOREGROUND
].count
6289 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
6290 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
6291 if (fmt
[PBM_BACKGROUND
].count
6292 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
6294 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
6295 img
->background
= bg
;
6296 img
->background_valid
= 1;
6299 for (y
= 0; y
< height
; ++y
)
6300 for (x
= 0; x
< width
; ++x
)
6308 x_destroy_x_image (ximg
);
6309 x_clear_image (f
, img
);
6310 image_error ("Invalid image size in image `%s'",
6320 g
= pbm_scan_number (&p
, end
);
6322 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
6327 int expected_size
= height
* width
;
6328 if (max_color_idx
> 255)
6330 if (type
== PBM_COLOR
)
6333 if (raw_p
&& p
+ expected_size
> end
)
6335 x_destroy_x_image (ximg
);
6336 x_clear_image (f
, img
);
6337 image_error ("Invalid image size in image `%s'",
6342 for (y
= 0; y
< height
; ++y
)
6343 for (x
= 0; x
< width
; ++x
)
6347 if (type
== PBM_GRAY
&& raw_p
)
6350 if (max_color_idx
> 255)
6351 r
= g
= b
= r
* 256 + *p
++;
6353 else if (type
== PBM_GRAY
)
6354 r
= g
= b
= pbm_scan_number (&p
, end
);
6358 if (max_color_idx
> 255)
6361 if (max_color_idx
> 255)
6364 if (max_color_idx
> 255)
6369 r
= pbm_scan_number (&p
, end
);
6370 g
= pbm_scan_number (&p
, end
);
6371 b
= pbm_scan_number (&p
, end
);
6374 if (r
< 0 || g
< 0 || b
< 0)
6376 x_destroy_x_image (ximg
);
6377 image_error ("Invalid pixel value in image `%s'",
6382 /* RGB values are now in the range 0..max_color_idx.
6383 Scale this to the range 0..0xffff supported by X. */
6384 r
= (double) r
* 65535 / max_color_idx
;
6385 g
= (double) g
* 65535 / max_color_idx
;
6386 b
= (double) b
* 65535 / max_color_idx
;
6387 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6391 #ifdef COLOR_TABLE_SUPPORT
6392 /* Store in IMG->colors the colors allocated for the image, and
6393 free the color table. */
6394 img
->colors
= colors_in_color_table (&img
->ncolors
);
6395 free_color_table ();
6396 #endif /* COLOR_TABLE_SUPPORT */
6399 img
->height
= height
;
6401 /* Maybe fill in the background field while we have ximg handy. */
6403 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6404 /* Casting avoids a GCC warning. */
6405 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6407 /* Put the image into a pixmap. */
6408 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6409 x_destroy_x_image (ximg
);
6411 /* X and W32 versions did it here, MAC version above. ++kfs
6413 img->height = height; */
6421 /***********************************************************************
6423 ***********************************************************************/
6425 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
6427 /* Function prototypes. */
6429 static int png_image_p
P_ ((Lisp_Object object
));
6430 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
6432 /* The symbol `png' identifying images of this type. */
6436 /* Indices of image specification fields in png_format, below. */
6438 enum png_keyword_index
6453 /* Vector of image_keyword structures describing the format
6454 of valid user-defined image specifications. */
6456 static struct image_keyword png_format
[PNG_LAST
] =
6458 {":type", IMAGE_SYMBOL_VALUE
, 1},
6459 {":data", IMAGE_STRING_VALUE
, 0},
6460 {":file", IMAGE_STRING_VALUE
, 0},
6461 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6462 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6463 {":relief", IMAGE_INTEGER_VALUE
, 0},
6464 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6465 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6466 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6467 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6470 /* Structure describing the image type `png'. */
6472 static struct image_type png_type
=
6481 /* Return non-zero if OBJECT is a valid PNG image specification. */
6484 png_image_p (object
)
6487 struct image_keyword fmt
[PNG_LAST
];
6488 bcopy (png_format
, fmt
, sizeof fmt
);
6490 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
6493 /* Must specify either the :data or :file keyword. */
6494 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
6497 #endif /* HAVE_PNG || MAC_OS || HAVE_NS */
6502 #if defined HAVE_LIBPNG_PNG_H
6503 # include <libpng/png.h>
6509 /* PNG library details. */
6511 DEF_IMGLIB_FN (png_get_io_ptr
);
6512 DEF_IMGLIB_FN (png_check_sig
);
6513 DEF_IMGLIB_FN (png_create_read_struct
);
6514 DEF_IMGLIB_FN (png_create_info_struct
);
6515 DEF_IMGLIB_FN (png_destroy_read_struct
);
6516 DEF_IMGLIB_FN (png_set_read_fn
);
6517 DEF_IMGLIB_FN (png_set_sig_bytes
);
6518 DEF_IMGLIB_FN (png_read_info
);
6519 DEF_IMGLIB_FN (png_get_IHDR
);
6520 DEF_IMGLIB_FN (png_get_valid
);
6521 DEF_IMGLIB_FN (png_set_strip_16
);
6522 DEF_IMGLIB_FN (png_set_expand
);
6523 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6524 DEF_IMGLIB_FN (png_set_background
);
6525 DEF_IMGLIB_FN (png_get_bKGD
);
6526 DEF_IMGLIB_FN (png_read_update_info
);
6527 DEF_IMGLIB_FN (png_get_channels
);
6528 DEF_IMGLIB_FN (png_get_rowbytes
);
6529 DEF_IMGLIB_FN (png_read_image
);
6530 DEF_IMGLIB_FN (png_read_end
);
6531 DEF_IMGLIB_FN (png_error
);
6534 init_png_functions (Lisp_Object libraries
)
6538 /* Try loading libpng under probable names. */
6539 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6542 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6543 LOAD_IMGLIB_FN (library
, png_check_sig
);
6544 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6545 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6546 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6547 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6548 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6549 LOAD_IMGLIB_FN (library
, png_read_info
);
6550 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6551 LOAD_IMGLIB_FN (library
, png_get_valid
);
6552 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6553 LOAD_IMGLIB_FN (library
, png_set_expand
);
6554 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6555 LOAD_IMGLIB_FN (library
, png_set_background
);
6556 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6557 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6558 LOAD_IMGLIB_FN (library
, png_get_channels
);
6559 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6560 LOAD_IMGLIB_FN (library
, png_read_image
);
6561 LOAD_IMGLIB_FN (library
, png_read_end
);
6562 LOAD_IMGLIB_FN (library
, png_error
);
6567 #define fn_png_get_io_ptr png_get_io_ptr
6568 #define fn_png_check_sig png_check_sig
6569 #define fn_png_create_read_struct png_create_read_struct
6570 #define fn_png_create_info_struct png_create_info_struct
6571 #define fn_png_destroy_read_struct png_destroy_read_struct
6572 #define fn_png_set_read_fn png_set_read_fn
6573 #define fn_png_set_sig_bytes png_set_sig_bytes
6574 #define fn_png_read_info png_read_info
6575 #define fn_png_get_IHDR png_get_IHDR
6576 #define fn_png_get_valid png_get_valid
6577 #define fn_png_set_strip_16 png_set_strip_16
6578 #define fn_png_set_expand png_set_expand
6579 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6580 #define fn_png_set_background png_set_background
6581 #define fn_png_get_bKGD png_get_bKGD
6582 #define fn_png_read_update_info png_read_update_info
6583 #define fn_png_get_channels png_get_channels
6584 #define fn_png_get_rowbytes png_get_rowbytes
6585 #define fn_png_read_image png_read_image
6586 #define fn_png_read_end png_read_end
6587 #define fn_png_error png_error
6589 #endif /* HAVE_NTGUI */
6591 /* Error and warning handlers installed when the PNG library
6595 my_png_error (png_ptr
, msg
)
6596 png_struct
*png_ptr
;
6599 xassert (png_ptr
!= NULL
);
6600 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6601 longjmp (png_ptr
->jmpbuf
, 1);
6606 my_png_warning (png_ptr
, msg
)
6607 png_struct
*png_ptr
;
6610 xassert (png_ptr
!= NULL
);
6611 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6614 /* Memory source for PNG decoding. */
6616 struct png_memory_storage
6618 unsigned char *bytes
; /* The data */
6619 size_t len
; /* How big is it? */
6620 int index
; /* Where are we? */
6624 /* Function set as reader function when reading PNG image from memory.
6625 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6626 bytes from the input to DATA. */
6629 png_read_from_memory (png_ptr
, data
, length
)
6630 png_structp png_ptr
;
6634 struct png_memory_storage
*tbr
6635 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6637 if (length
> tbr
->len
- tbr
->index
)
6638 fn_png_error (png_ptr
, "Read error");
6640 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6641 tbr
->index
= tbr
->index
+ length
;
6645 /* Function set as reader function when reading PNG image from a file.
6646 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6647 bytes from the input to DATA. */
6650 png_read_from_file (png_ptr
, data
, length
)
6651 png_structp png_ptr
;
6655 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6657 if (fread (data
, 1, length
, fp
) < length
)
6658 fn_png_error (png_ptr
, "Read error");
6662 /* Load PNG image IMG for use on frame F. Value is non-zero if
6670 Lisp_Object file
, specified_file
;
6671 Lisp_Object specified_data
;
6673 XImagePtr ximg
, mask_img
= NULL
;
6674 struct gcpro gcpro1
;
6675 png_struct
*png_ptr
= NULL
;
6676 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6677 FILE *volatile fp
= NULL
;
6679 png_byte
* volatile pixels
= NULL
;
6680 png_byte
** volatile rows
= NULL
;
6681 png_uint_32 width
, height
;
6682 int bit_depth
, color_type
, interlace_type
;
6684 png_uint_32 row_bytes
;
6686 struct png_memory_storage tbr
; /* Data to be read */
6688 /* Find out what file to load. */
6689 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6690 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6694 if (NILP (specified_data
))
6696 file
= x_find_image_file (specified_file
);
6697 if (!STRINGP (file
))
6699 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6704 /* Open the image file. */
6705 fp
= fopen (SDATA (file
), "rb");
6708 image_error ("Cannot open image file `%s'", file
, Qnil
);
6713 /* Check PNG signature. */
6714 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6715 || !fn_png_check_sig (sig
, sizeof sig
))
6717 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6725 /* Read from memory. */
6726 tbr
.bytes
= SDATA (specified_data
);
6727 tbr
.len
= SBYTES (specified_data
);
6730 /* Check PNG signature. */
6731 if (tbr
.len
< sizeof sig
6732 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6734 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6739 /* Need to skip past the signature. */
6740 tbr
.bytes
+= sizeof (sig
);
6743 /* Initialize read and info structs for PNG lib. Casting return
6744 value avoids a GCC warning on W32. */
6745 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6750 if (fp
) fclose (fp
);
6755 /* Casting return value avoids a GCC warning on W32. */
6756 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6759 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6760 if (fp
) fclose (fp
);
6765 /* Casting return value avoids a GCC warning on W32. */
6766 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6769 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6770 if (fp
) fclose (fp
);
6775 /* Set error jump-back. We come back here when the PNG library
6776 detects an error. */
6777 if (setjmp (png_ptr
->jmpbuf
))
6781 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6784 if (fp
) fclose (fp
);
6789 /* Read image info. */
6790 if (!NILP (specified_data
))
6791 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6793 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6795 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6796 fn_png_read_info (png_ptr
, info_ptr
);
6797 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6798 &interlace_type
, NULL
, NULL
);
6800 if (!check_image_size (f
, width
, height
))
6803 /* If image contains simply transparency data, we prefer to
6804 construct a clipping mask. */
6805 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6810 /* This function is easier to write if we only have to handle
6811 one data format: RGB or RGBA with 8 bits per channel. Let's
6812 transform other formats into that format. */
6814 /* Strip more than 8 bits per channel. */
6815 if (bit_depth
== 16)
6816 fn_png_set_strip_16 (png_ptr
);
6818 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6820 fn_png_set_expand (png_ptr
);
6822 /* Convert grayscale images to RGB. */
6823 if (color_type
== PNG_COLOR_TYPE_GRAY
6824 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6825 fn_png_set_gray_to_rgb (png_ptr
);
6827 /* Handle alpha channel by combining the image with a background
6828 color. Do this only if a real alpha channel is supplied. For
6829 simple transparency, we prefer a clipping mask. */
6832 /* png_color_16 *image_bg; */
6833 Lisp_Object specified_bg
6834 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6835 int shift
= (bit_depth
== 16) ? 0 : 8;
6837 if (STRINGP (specified_bg
))
6838 /* The user specified `:background', use that. */
6840 /* W32 version incorrectly used COLORREF here!! ++kfs */
6842 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6844 png_color_16 user_bg
;
6846 bzero (&user_bg
, sizeof user_bg
);
6847 user_bg
.red
= color
.red
>> shift
;
6848 user_bg
.green
= color
.green
>> shift
;
6849 user_bg
.blue
= color
.blue
>> shift
;
6851 fn_png_set_background (png_ptr
, &user_bg
,
6852 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6857 /* We use the current frame background, ignoring any default
6858 background color set by the image. */
6859 #ifdef HAVE_X_WINDOWS
6861 png_color_16 frame_background
;
6863 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6864 x_query_color (f
, &color
);
6866 bzero (&frame_background
, sizeof frame_background
);
6867 frame_background
.red
= color
.red
>> shift
;
6868 frame_background
.green
= color
.green
>> shift
;
6869 frame_background
.blue
= color
.blue
>> shift
;
6870 #endif /* HAVE_X_WINDOWS */
6874 png_color_16 frame_background
;
6875 color
= FRAME_BACKGROUND_PIXEL (f
);
6876 #if 0 /* W32 TODO : Colormap support. */
6877 x_query_color (f
, &color
);
6879 bzero (&frame_background
, sizeof frame_background
);
6880 frame_background
.red
= GetRValue (color
);
6881 frame_background
.green
= GetGValue (color
);
6882 frame_background
.blue
= GetBValue (color
);
6883 #endif /* HAVE_NTGUI */
6886 unsigned long color
;
6887 png_color_16 frame_background
;
6888 color
= FRAME_BACKGROUND_PIXEL (f
);
6889 #if 0 /* MAC/W32 TODO : Colormap support. */
6890 x_query_color (f
, &color
);
6892 bzero (&frame_background
, sizeof frame_background
);
6893 frame_background
.red
= RED_FROM_ULONG (color
);
6894 frame_background
.green
= GREEN_FROM_ULONG (color
);
6895 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6898 fn_png_set_background (png_ptr
, &frame_background
,
6899 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6903 /* Update info structure. */
6904 fn_png_read_update_info (png_ptr
, info_ptr
);
6906 /* Get number of channels. Valid values are 1 for grayscale images
6907 and images with a palette, 2 for grayscale images with transparency
6908 information (alpha channel), 3 for RGB images, and 4 for RGB
6909 images with alpha channel, i.e. RGBA. If conversions above were
6910 sufficient we should only have 3 or 4 channels here. */
6911 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6912 xassert (channels
== 3 || channels
== 4);
6914 /* Number of bytes needed for one row of the image. */
6915 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6917 /* Allocate memory for the image. */
6918 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6919 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6920 for (i
= 0; i
< height
; ++i
)
6921 rows
[i
] = pixels
+ i
* row_bytes
;
6923 /* Read the entire image. */
6924 fn_png_read_image (png_ptr
, rows
);
6925 fn_png_read_end (png_ptr
, info_ptr
);
6932 /* Create the X image and pixmap. */
6933 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6937 /* Create an image and pixmap serving as mask if the PNG image
6938 contains an alpha channel. */
6941 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6942 &mask_img
, &img
->mask
))
6944 x_destroy_x_image (ximg
);
6945 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6946 img
->pixmap
= NO_PIXMAP
;
6950 /* Fill the X image and mask from PNG data. */
6951 init_color_table ();
6953 for (y
= 0; y
< height
; ++y
)
6955 png_byte
*p
= rows
[y
];
6957 for (x
= 0; x
< width
; ++x
)
6964 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6965 /* An alpha channel, aka mask channel, associates variable
6966 transparency with an image. Where other image formats
6967 support binary transparency---fully transparent or fully
6968 opaque---PNG allows up to 254 levels of partial transparency.
6969 The PNG library implements partial transparency by combining
6970 the image with a specified background color.
6972 I'm not sure how to handle this here nicely: because the
6973 background on which the image is displayed may change, for
6974 real alpha channel support, it would be necessary to create
6975 a new image for each possible background.
6977 What I'm doing now is that a mask is created if we have
6978 boolean transparency information. Otherwise I'm using
6979 the frame's background color to combine the image with. */
6984 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6990 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6991 /* Set IMG's background color from the PNG image, unless the user
6995 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6997 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6998 img
->background_valid
= 1;
7002 #ifdef COLOR_TABLE_SUPPORT
7003 /* Remember colors allocated for this image. */
7004 img
->colors
= colors_in_color_table (&img
->ncolors
);
7005 free_color_table ();
7006 #endif /* COLOR_TABLE_SUPPORT */
7009 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
7014 img
->height
= height
;
7016 /* Maybe fill in the background field while we have ximg handy.
7017 Casting avoids a GCC warning. */
7018 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7020 /* Put the image into the pixmap, then free the X image and its buffer. */
7021 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7022 x_destroy_x_image (ximg
);
7024 /* Same for the mask. */
7027 /* Fill in the background_transparent field while we have the
7028 mask handy. Casting avoids a GCC warning. */
7029 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
7031 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
7032 x_destroy_x_image (mask_img
);
7039 #else /* HAVE_PNG */
7047 #if USE_MAC_IMAGE_IO
7048 return image_load_image_io (f
, img
, kUTTypePNG
);
7049 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
7050 return image_load_quartz2d (f
, img
, 1);
7052 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
7059 png_load (struct frame
*f
, struct image
*img
)
7061 return ns_load_image(f
, img
,
7062 image_spec_value (img
->spec
, QCfile
, NULL
),
7063 image_spec_value (img
->spec
, QCdata
, NULL
));
7065 #endif /* HAVE_NS */
7068 #endif /* !HAVE_PNG */
7072 /***********************************************************************
7074 ***********************************************************************/
7076 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
7078 static int jpeg_image_p
P_ ((Lisp_Object object
));
7079 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
7081 /* The symbol `jpeg' identifying images of this type. */
7085 /* Indices of image specification fields in gs_format, below. */
7087 enum jpeg_keyword_index
7096 JPEG_HEURISTIC_MASK
,
7102 /* Vector of image_keyword structures describing the format
7103 of valid user-defined image specifications. */
7105 static struct image_keyword jpeg_format
[JPEG_LAST
] =
7107 {":type", IMAGE_SYMBOL_VALUE
, 1},
7108 {":data", IMAGE_STRING_VALUE
, 0},
7109 {":file", IMAGE_STRING_VALUE
, 0},
7110 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7111 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7112 {":relief", IMAGE_INTEGER_VALUE
, 0},
7113 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7114 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7115 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7116 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7119 /* Structure describing the image type `jpeg'. */
7121 static struct image_type jpeg_type
=
7130 /* Return non-zero if OBJECT is a valid JPEG image specification. */
7133 jpeg_image_p (object
)
7136 struct image_keyword fmt
[JPEG_LAST
];
7138 bcopy (jpeg_format
, fmt
, sizeof fmt
);
7140 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
7143 /* Must specify either the :data or :file keyword. */
7144 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
7147 #endif /* HAVE_JPEG || MAC_OS || HAVE_NS */
7151 /* Work around a warning about HAVE_STDLIB_H being redefined in
7153 #ifdef HAVE_STDLIB_H
7154 #define HAVE_STDLIB_H_1
7155 #undef HAVE_STDLIB_H
7156 #endif /* HAVE_STLIB_H */
7158 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
7159 /* In older releases of the jpeg library, jpeglib.h will define boolean
7160 differently depending on __WIN32__, so make sure it is defined. */
7164 #include <jpeglib.h>
7168 #ifdef HAVE_STLIB_H_1
7169 #define HAVE_STDLIB_H 1
7174 /* JPEG library details. */
7175 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
7176 DEF_IMGLIB_FN (jpeg_start_decompress
);
7177 DEF_IMGLIB_FN (jpeg_finish_decompress
);
7178 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
7179 DEF_IMGLIB_FN (jpeg_read_header
);
7180 DEF_IMGLIB_FN (jpeg_read_scanlines
);
7181 DEF_IMGLIB_FN (jpeg_std_error
);
7182 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
7185 init_jpeg_functions (Lisp_Object libraries
)
7189 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
7192 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
7193 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
7194 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
7195 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
7196 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
7197 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
7198 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
7199 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
7203 /* Wrapper since we can't directly assign the function pointer
7204 to another function pointer that was declared more completely easily. */
7206 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
7207 j_decompress_ptr cinfo
;
7210 return fn_jpeg_resync_to_restart (cinfo
, desired
);
7215 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7216 #define fn_jpeg_start_decompress jpeg_start_decompress
7217 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7218 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7219 #define fn_jpeg_read_header jpeg_read_header
7220 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7221 #define fn_jpeg_std_error jpeg_std_error
7222 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7224 #endif /* HAVE_NTGUI */
7226 struct my_jpeg_error_mgr
7228 struct jpeg_error_mgr pub
;
7229 jmp_buf setjmp_buffer
;
7234 my_error_exit (cinfo
)
7237 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
7238 longjmp (mgr
->setjmp_buffer
, 1);
7242 /* Init source method for JPEG data source manager. Called by
7243 jpeg_read_header() before any data is actually read. See
7244 libjpeg.doc from the JPEG lib distribution. */
7247 our_common_init_source (cinfo
)
7248 j_decompress_ptr cinfo
;
7253 /* Method to terminate data source. Called by
7254 jpeg_finish_decompress() after all data has been processed. */
7257 our_common_term_source (cinfo
)
7258 j_decompress_ptr cinfo
;
7263 /* Fill input buffer method for JPEG data source manager. Called
7264 whenever more data is needed. We read the whole image in one step,
7265 so this only adds a fake end of input marker at the end. */
7267 static JOCTET our_memory_buffer
[2];
7270 our_memory_fill_input_buffer (cinfo
)
7271 j_decompress_ptr cinfo
;
7273 /* Insert a fake EOI marker. */
7274 struct jpeg_source_mgr
*src
= cinfo
->src
;
7276 our_memory_buffer
[0] = (JOCTET
) 0xFF;
7277 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
7279 src
->next_input_byte
= our_memory_buffer
;
7280 src
->bytes_in_buffer
= 2;
7285 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7286 is the JPEG data source manager. */
7289 our_memory_skip_input_data (cinfo
, num_bytes
)
7290 j_decompress_ptr cinfo
;
7293 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7297 if (num_bytes
> src
->bytes_in_buffer
)
7298 ERREXIT (cinfo
, JERR_INPUT_EOF
);
7300 src
->bytes_in_buffer
-= num_bytes
;
7301 src
->next_input_byte
+= num_bytes
;
7306 /* Set up the JPEG lib for reading an image from DATA which contains
7307 LEN bytes. CINFO is the decompression info structure created for
7308 reading the image. */
7311 jpeg_memory_src (cinfo
, data
, len
)
7312 j_decompress_ptr cinfo
;
7316 struct jpeg_source_mgr
*src
;
7318 if (cinfo
->src
== NULL
)
7320 /* First time for this JPEG object? */
7321 cinfo
->src
= (struct jpeg_source_mgr
*)
7322 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7323 sizeof (struct jpeg_source_mgr
));
7324 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7325 src
->next_input_byte
= data
;
7328 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7329 src
->init_source
= our_common_init_source
;
7330 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
7331 src
->skip_input_data
= our_memory_skip_input_data
;
7332 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7333 src
->term_source
= our_common_term_source
;
7334 src
->bytes_in_buffer
= len
;
7335 src
->next_input_byte
= data
;
7339 struct jpeg_stdio_mgr
7341 struct jpeg_source_mgr mgr
;
7348 /* Size of buffer to read JPEG from file.
7349 Not too big, as we want to use alloc_small. */
7350 #define JPEG_STDIO_BUFFER_SIZE 8192
7353 /* Fill input buffer method for JPEG data source manager. Called
7354 whenever more data is needed. The data is read from a FILE *. */
7357 our_stdio_fill_input_buffer (cinfo
)
7358 j_decompress_ptr cinfo
;
7360 struct jpeg_stdio_mgr
*src
;
7362 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7367 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
7369 src
->mgr
.bytes_in_buffer
= bytes
;
7372 WARNMS (cinfo
, JWRN_JPEG_EOF
);
7374 src
->buffer
[0] = (JOCTET
) 0xFF;
7375 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
7376 src
->mgr
.bytes_in_buffer
= 2;
7378 src
->mgr
.next_input_byte
= src
->buffer
;
7385 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7386 is the JPEG data source manager. */
7389 our_stdio_skip_input_data (cinfo
, num_bytes
)
7390 j_decompress_ptr cinfo
;
7393 struct jpeg_stdio_mgr
*src
;
7394 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7396 while (num_bytes
> 0 && !src
->finished
)
7398 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
7400 src
->mgr
.bytes_in_buffer
-= num_bytes
;
7401 src
->mgr
.next_input_byte
+= num_bytes
;
7406 num_bytes
-= src
->mgr
.bytes_in_buffer
;
7407 src
->mgr
.bytes_in_buffer
= 0;
7408 src
->mgr
.next_input_byte
= NULL
;
7410 our_stdio_fill_input_buffer (cinfo
);
7416 /* Set up the JPEG lib for reading an image from a FILE *.
7417 CINFO is the decompression info structure created for
7418 reading the image. */
7421 jpeg_file_src (cinfo
, fp
)
7422 j_decompress_ptr cinfo
;
7425 struct jpeg_stdio_mgr
*src
;
7427 if (cinfo
->src
!= NULL
)
7428 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7431 /* First time for this JPEG object? */
7432 cinfo
->src
= (struct jpeg_source_mgr
*)
7433 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7434 sizeof (struct jpeg_stdio_mgr
));
7435 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7436 src
->buffer
= (JOCTET
*)
7437 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7438 JPEG_STDIO_BUFFER_SIZE
);
7443 src
->mgr
.init_source
= our_common_init_source
;
7444 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
7445 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
7446 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7447 src
->mgr
.term_source
= our_common_term_source
;
7448 src
->mgr
.bytes_in_buffer
= 0;
7449 src
->mgr
.next_input_byte
= NULL
;
7453 /* Load image IMG for use on frame F. Patterned after example.c
7454 from the JPEG lib. */
7461 struct jpeg_decompress_struct cinfo
;
7462 struct my_jpeg_error_mgr mgr
;
7463 Lisp_Object file
, specified_file
;
7464 Lisp_Object specified_data
;
7465 FILE * volatile fp
= NULL
;
7467 int row_stride
, x
, y
;
7468 XImagePtr ximg
= NULL
;
7470 unsigned long *colors
;
7472 struct gcpro gcpro1
;
7474 /* Open the JPEG file. */
7475 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7476 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7480 if (NILP (specified_data
))
7482 file
= x_find_image_file (specified_file
);
7483 if (!STRINGP (file
))
7485 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7490 fp
= fopen (SDATA (file
), "rb");
7493 image_error ("Cannot open `%s'", file
, Qnil
);
7499 /* Customize libjpeg's error handling to call my_error_exit when an
7500 error is detected. This function will perform a longjmp.
7501 Casting return value avoids a GCC warning on W32. */
7502 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7503 mgr
.pub
.error_exit
= my_error_exit
;
7505 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7509 /* Called from my_error_exit. Display a JPEG error. */
7510 char buffer
[JMSG_LENGTH_MAX
];
7511 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7512 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7513 build_string (buffer
));
7516 /* Close the input file and destroy the JPEG object. */
7518 fclose ((FILE *) fp
);
7519 fn_jpeg_destroy_decompress (&cinfo
);
7521 /* If we already have an XImage, free that. */
7522 x_destroy_x_image (ximg
);
7524 /* Free pixmap and colors. */
7525 x_clear_image (f
, img
);
7531 /* Create the JPEG decompression object. Let it read from fp.
7532 Read the JPEG image header. */
7533 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7535 if (NILP (specified_data
))
7536 jpeg_file_src (&cinfo
, (FILE *) fp
);
7538 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7539 SBYTES (specified_data
));
7541 fn_jpeg_read_header (&cinfo
, 1);
7543 /* Customize decompression so that color quantization will be used.
7544 Start decompression. */
7545 cinfo
.quantize_colors
= 1;
7546 fn_jpeg_start_decompress (&cinfo
);
7547 width
= img
->width
= cinfo
.output_width
;
7548 height
= img
->height
= cinfo
.output_height
;
7550 if (!check_image_size (f
, width
, height
))
7552 image_error ("Invalid image size", Qnil
, Qnil
);
7553 longjmp (mgr
.setjmp_buffer
, 2);
7556 /* Create X image and pixmap. */
7557 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7558 longjmp (mgr
.setjmp_buffer
, 2);
7560 /* Allocate colors. When color quantization is used,
7561 cinfo.actual_number_of_colors has been set with the number of
7562 colors generated, and cinfo.colormap is a two-dimensional array
7563 of color indices in the range 0..cinfo.actual_number_of_colors.
7564 No more than 255 colors will be generated. */
7568 if (cinfo
.out_color_components
> 2)
7569 ir
= 0, ig
= 1, ib
= 2;
7570 else if (cinfo
.out_color_components
> 1)
7571 ir
= 0, ig
= 1, ib
= 0;
7573 ir
= 0, ig
= 0, ib
= 0;
7575 /* Use the color table mechanism because it handles colors that
7576 cannot be allocated nicely. Such colors will be replaced with
7577 a default color, and we don't have to care about which colors
7578 can be freed safely, and which can't. */
7579 init_color_table ();
7580 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7583 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7585 /* Multiply RGB values with 255 because X expects RGB values
7586 in the range 0..0xffff. */
7587 int r
= cinfo
.colormap
[ir
][i
] << 8;
7588 int g
= cinfo
.colormap
[ig
][i
] << 8;
7589 int b
= cinfo
.colormap
[ib
][i
] << 8;
7590 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7593 #ifdef COLOR_TABLE_SUPPORT
7594 /* Remember those colors actually allocated. */
7595 img
->colors
= colors_in_color_table (&img
->ncolors
);
7596 free_color_table ();
7597 #endif /* COLOR_TABLE_SUPPORT */
7601 row_stride
= width
* cinfo
.output_components
;
7602 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7604 for (y
= 0; y
< height
; ++y
)
7606 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7607 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7608 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7612 fn_jpeg_finish_decompress (&cinfo
);
7613 fn_jpeg_destroy_decompress (&cinfo
);
7615 fclose ((FILE *) fp
);
7617 /* Maybe fill in the background field while we have ximg handy. */
7618 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7619 /* Casting avoids a GCC warning. */
7620 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7622 /* Put the image into the pixmap. */
7623 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7624 x_destroy_x_image (ximg
);
7629 #else /* HAVE_JPEG */
7637 #if USE_MAC_IMAGE_IO
7638 return image_load_image_io (f
, img
, kUTTypeJPEG
);
7639 #elif defined (MAC_OSX)
7640 return image_load_quartz2d (f
, img
, 0);
7642 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7649 jpeg_load (struct frame
*f
, struct image
*img
)
7651 return ns_load_image(f
, img
,
7652 image_spec_value (img
->spec
, QCfile
, NULL
),
7653 image_spec_value (img
->spec
, QCdata
, NULL
));
7655 #endif /* HAVE_NS */
7657 #endif /* !HAVE_JPEG */
7661 /***********************************************************************
7663 ***********************************************************************/
7665 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
7667 static int tiff_image_p
P_ ((Lisp_Object object
));
7668 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7670 /* The symbol `tiff' identifying images of this type. */
7674 /* Indices of image specification fields in tiff_format, below. */
7676 enum tiff_keyword_index
7685 TIFF_HEURISTIC_MASK
,
7691 /* Vector of image_keyword structures describing the format
7692 of valid user-defined image specifications. */
7694 static struct image_keyword tiff_format
[TIFF_LAST
] =
7696 {":type", IMAGE_SYMBOL_VALUE
, 1},
7697 {":data", IMAGE_STRING_VALUE
, 0},
7698 {":file", IMAGE_STRING_VALUE
, 0},
7699 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7700 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7701 {":relief", IMAGE_INTEGER_VALUE
, 0},
7702 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7703 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7704 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7705 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7708 /* Structure describing the image type `tiff'. */
7710 static struct image_type tiff_type
=
7719 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7722 tiff_image_p (object
)
7725 struct image_keyword fmt
[TIFF_LAST
];
7726 bcopy (tiff_format
, fmt
, sizeof fmt
);
7728 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7731 /* Must specify either the :data or :file keyword. */
7732 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7735 #endif /* HAVE_TIFF || MAC_OS || HAVE_NS */
7743 /* TIFF library details. */
7744 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7745 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7746 DEF_IMGLIB_FN (TIFFOpen
);
7747 DEF_IMGLIB_FN (TIFFClientOpen
);
7748 DEF_IMGLIB_FN (TIFFGetField
);
7749 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7750 DEF_IMGLIB_FN (TIFFClose
);
7753 init_tiff_functions (Lisp_Object libraries
)
7757 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7760 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7761 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7762 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7763 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7764 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7765 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7766 LOAD_IMGLIB_FN (library
, TIFFClose
);
7772 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7773 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7774 #define fn_TIFFOpen TIFFOpen
7775 #define fn_TIFFClientOpen TIFFClientOpen
7776 #define fn_TIFFGetField TIFFGetField
7777 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7778 #define fn_TIFFClose TIFFClose
7780 #endif /* HAVE_NTGUI */
7783 /* Reading from a memory buffer for TIFF images Based on the PNG
7784 memory source, but we have to provide a lot of extra functions.
7787 We really only need to implement read and seek, but I am not
7788 convinced that the TIFF library is smart enough not to destroy
7789 itself if we only hand it the function pointers we need to
7794 unsigned char *bytes
;
7801 tiff_read_from_memory (data
, buf
, size
)
7806 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7808 if (size
> src
->len
- src
->index
)
7810 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7816 tiff_write_from_memory (data
, buf
, size
)
7825 tiff_seek_in_memory (data
, off
, whence
)
7830 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7835 case SEEK_SET
: /* Go from beginning of source. */
7839 case SEEK_END
: /* Go from end of source. */
7840 idx
= src
->len
+ off
;
7843 case SEEK_CUR
: /* Go from current position. */
7844 idx
= src
->index
+ off
;
7847 default: /* Invalid `whence'. */
7851 if (idx
> src
->len
|| idx
< 0)
7859 tiff_close_memory (data
)
7867 tiff_mmap_memory (data
, pbase
, psize
)
7872 /* It is already _IN_ memory. */
7877 tiff_unmap_memory (data
, base
, size
)
7882 /* We don't need to do this. */
7886 tiff_size_of_memory (data
)
7889 return ((tiff_memory_source
*) data
)->len
;
7894 tiff_error_handler (title
, format
, ap
)
7895 const char *title
, *format
;
7901 len
= sprintf (buf
, "TIFF error: %s ", title
);
7902 vsprintf (buf
+ len
, format
, ap
);
7903 add_to_log (buf
, Qnil
, Qnil
);
7908 tiff_warning_handler (title
, format
, ap
)
7909 const char *title
, *format
;
7915 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7916 vsprintf (buf
+ len
, format
, ap
);
7917 add_to_log (buf
, Qnil
, Qnil
);
7921 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7929 Lisp_Object file
, specified_file
;
7930 Lisp_Object specified_data
;
7932 int width
, height
, x
, y
;
7936 struct gcpro gcpro1
;
7937 tiff_memory_source memsrc
;
7939 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7940 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7944 fn_TIFFSetErrorHandler (tiff_error_handler
);
7945 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7947 if (NILP (specified_data
))
7949 /* Read from a file */
7950 file
= x_find_image_file (specified_file
);
7951 if (!STRINGP (file
))
7953 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7958 /* Try to open the image file. Casting return value avoids a
7959 GCC warning on W32. */
7960 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7963 image_error ("Cannot open `%s'", file
, Qnil
);
7970 /* Memory source! */
7971 memsrc
.bytes
= SDATA (specified_data
);
7972 memsrc
.len
= SBYTES (specified_data
);
7975 /* Casting return value avoids a GCC warning on W32. */
7976 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7977 (TIFFReadWriteProc
) tiff_read_from_memory
,
7978 (TIFFReadWriteProc
) tiff_write_from_memory
,
7979 tiff_seek_in_memory
,
7981 tiff_size_of_memory
,
7987 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7993 /* Get width and height of the image, and allocate a raster buffer
7994 of width x height 32-bit values. */
7995 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7996 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7998 if (!check_image_size (f
, width
, height
))
8000 image_error ("Invalid image size", Qnil
, Qnil
);
8005 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
8007 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
8008 fn_TIFFClose (tiff
);
8011 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
8017 /* Create the X image and pixmap. */
8018 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8025 /* Initialize the color table. */
8026 init_color_table ();
8028 /* Process the pixel raster. Origin is in the lower-left corner. */
8029 for (y
= 0; y
< height
; ++y
)
8031 uint32
*row
= buf
+ y
* width
;
8033 for (x
= 0; x
< width
; ++x
)
8035 uint32 abgr
= row
[x
];
8036 int r
= TIFFGetR (abgr
) << 8;
8037 int g
= TIFFGetG (abgr
) << 8;
8038 int b
= TIFFGetB (abgr
) << 8;
8039 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
8043 #ifdef COLOR_TABLE_SUPPORT
8044 /* Remember the colors allocated for the image. Free the color table. */
8045 img
->colors
= colors_in_color_table (&img
->ncolors
);
8046 free_color_table ();
8047 #endif /* COLOR_TABLE_SUPPORT */
8050 img
->height
= height
;
8052 /* Maybe fill in the background field while we have ximg handy. */
8053 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8054 /* Casting avoids a GCC warning on W32. */
8055 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8057 /* Put the image into the pixmap, then free the X image and its buffer. */
8058 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8059 x_destroy_x_image (ximg
);
8066 #else /* HAVE_TIFF */
8074 #if USE_MAC_IMAGE_IO
8075 return image_load_image_io (f
, img
, kUTTypeTIFF
);
8077 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
8084 tiff_load (struct frame
*f
, struct image
*img
)
8086 return ns_load_image(f
, img
,
8087 image_spec_value (img
->spec
, QCfile
, NULL
),
8088 image_spec_value (img
->spec
, QCdata
, NULL
));
8090 #endif /* HAVE_NS */
8092 #endif /* !HAVE_TIFF */
8096 /***********************************************************************
8098 ***********************************************************************/
8100 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
8102 static int gif_image_p
P_ ((Lisp_Object object
));
8103 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
8104 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8106 /* The symbol `gif' identifying images of this type. */
8110 /* Indices of image specification fields in gif_format, below. */
8112 enum gif_keyword_index
8128 /* Vector of image_keyword structures describing the format
8129 of valid user-defined image specifications. */
8131 static struct image_keyword gif_format
[GIF_LAST
] =
8133 {":type", IMAGE_SYMBOL_VALUE
, 1},
8134 {":data", IMAGE_STRING_VALUE
, 0},
8135 {":file", IMAGE_STRING_VALUE
, 0},
8136 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8137 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8138 {":relief", IMAGE_INTEGER_VALUE
, 0},
8139 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8140 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8141 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8142 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
8143 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8146 /* Structure describing the image type `gif'. */
8148 static struct image_type gif_type
=
8157 /* Free X resources of GIF image IMG which is used on frame F. */
8160 gif_clear_image (f
, img
)
8164 /* IMG->data.ptr_val may contain extension data. */
8165 img
->data
.lisp_val
= Qnil
;
8166 x_clear_image (f
, img
);
8169 /* Return non-zero if OBJECT is a valid GIF image specification. */
8172 gif_image_p (object
)
8175 struct image_keyword fmt
[GIF_LAST
];
8176 bcopy (gif_format
, fmt
, sizeof fmt
);
8178 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
8181 /* Must specify either the :data or :file keyword. */
8182 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
8185 #endif /* HAVE_GIF || MAC_OS */
8189 #if defined (HAVE_NTGUI) || defined (MAC_OS)
8190 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
8191 Undefine before redefining to avoid a preprocessor warning. */
8195 /* avoid conflict with QuickdrawText.h */
8196 #define DrawText gif_DrawText
8197 #include <gif_lib.h>
8200 #else /* HAVE_NTGUI || MAC_OS */
8202 #include <gif_lib.h>
8204 #endif /* HAVE_NTGUI || MAC_OS */
8209 /* GIF library details. */
8210 DEF_IMGLIB_FN (DGifCloseFile
);
8211 DEF_IMGLIB_FN (DGifSlurp
);
8212 DEF_IMGLIB_FN (DGifOpen
);
8213 DEF_IMGLIB_FN (DGifOpenFileName
);
8216 init_gif_functions (Lisp_Object libraries
)
8220 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
8223 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
8224 LOAD_IMGLIB_FN (library
, DGifSlurp
);
8225 LOAD_IMGLIB_FN (library
, DGifOpen
);
8226 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
8232 #define fn_DGifCloseFile DGifCloseFile
8233 #define fn_DGifSlurp DGifSlurp
8234 #define fn_DGifOpen DGifOpen
8235 #define fn_DGifOpenFileName DGifOpenFileName
8237 #endif /* HAVE_NTGUI */
8239 /* Reading a GIF image from memory
8240 Based on the PNG memory stuff to a certain extent. */
8244 unsigned char *bytes
;
8250 /* Make the current memory source available to gif_read_from_memory.
8251 It's done this way because not all versions of libungif support
8252 a UserData field in the GifFileType structure. */
8253 static gif_memory_source
*current_gif_memory_src
;
8256 gif_read_from_memory (file
, buf
, len
)
8261 gif_memory_source
*src
= current_gif_memory_src
;
8263 if (len
> src
->len
- src
->index
)
8266 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8272 /* Load GIF image IMG for use on frame F. Value is non-zero if
8275 static int interlace_start
[] = {0, 4, 2, 1};
8276 static int interlace_increment
[] = {8, 8, 4, 2};
8283 Lisp_Object file
, specified_file
;
8284 Lisp_Object specified_data
;
8285 int rc
, width
, height
, x
, y
, i
;
8287 ColorMapObject
*gif_color_map
;
8288 unsigned long pixel_colors
[256];
8290 struct gcpro gcpro1
;
8292 int ino
, image_height
, image_width
;
8293 gif_memory_source memsrc
;
8294 unsigned char *raster
;
8296 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8297 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8301 if (NILP (specified_data
))
8303 file
= x_find_image_file (specified_file
);
8304 if (!STRINGP (file
))
8306 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8311 /* Open the GIF file. Casting return value avoids a GCC warning
8313 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
8316 image_error ("Cannot open `%s'", file
, Qnil
);
8323 /* Read from memory! */
8324 current_gif_memory_src
= &memsrc
;
8325 memsrc
.bytes
= SDATA (specified_data
);
8326 memsrc
.len
= SBYTES (specified_data
);
8329 /* Casting return value avoids a GCC warning on W32. */
8330 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
8333 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
8339 /* Before reading entire contents, check the declared image size. */
8340 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
8342 image_error ("Invalid image size", Qnil
, Qnil
);
8343 fn_DGifCloseFile (gif
);
8348 /* Read entire contents. */
8349 rc
= fn_DGifSlurp (gif
);
8350 if (rc
== GIF_ERROR
)
8352 image_error ("Error reading `%s'", img
->spec
, Qnil
);
8353 fn_DGifCloseFile (gif
);
8358 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8359 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8360 if (ino
>= gif
->ImageCount
)
8362 image_error ("Invalid image number `%s' in image `%s'",
8364 fn_DGifCloseFile (gif
);
8369 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
8370 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
8371 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8372 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
8373 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8374 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
8376 width
= img
->width
= max (gif
->SWidth
,
8377 max (gif
->Image
.Left
+ gif
->Image
.Width
,
8378 img
->corners
[RIGHT_CORNER
]));
8379 height
= img
->height
= max (gif
->SHeight
,
8380 max (gif
->Image
.Top
+ gif
->Image
.Height
,
8381 img
->corners
[BOT_CORNER
]));
8383 if (!check_image_size (f
, width
, height
))
8385 image_error ("Invalid image size", Qnil
, Qnil
);
8386 fn_DGifCloseFile (gif
);
8391 /* Create the X image and pixmap. */
8392 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8394 fn_DGifCloseFile (gif
);
8399 /* Allocate colors. */
8400 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8402 gif_color_map
= gif
->SColorMap
;
8403 init_color_table ();
8404 bzero (pixel_colors
, sizeof pixel_colors
);
8407 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8409 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8410 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8411 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8412 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8415 #ifdef COLOR_TABLE_SUPPORT
8416 img
->colors
= colors_in_color_table (&img
->ncolors
);
8417 free_color_table ();
8418 #endif /* COLOR_TABLE_SUPPORT */
8420 /* Clear the part of the screen image that are not covered by
8421 the image from the GIF file. Full animated GIF support
8422 requires more than can be done here (see the gif89 spec,
8423 disposal methods). Let's simply assume that the part
8424 not covered by a sub-image is in the frame's background color. */
8425 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
8426 for (x
= 0; x
< width
; ++x
)
8427 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8429 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
8430 for (x
= 0; x
< width
; ++x
)
8431 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8433 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
8435 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
8436 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8437 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
8438 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8441 /* Read the GIF image into the X image. We use a local variable
8442 `raster' here because RasterBits below is a char *, and invites
8443 problems with bytes >= 0x80. */
8444 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
8446 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8449 int row
= interlace_start
[0];
8453 for (y
= 0; y
< image_height
; y
++)
8455 if (row
>= image_height
)
8457 row
= interlace_start
[++pass
];
8458 while (row
>= image_height
)
8459 row
= interlace_start
[++pass
];
8462 for (x
= 0; x
< image_width
; x
++)
8464 int i
= raster
[(y
* image_width
) + x
];
8465 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8466 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8469 row
+= interlace_increment
[pass
];
8474 for (y
= 0; y
< image_height
; ++y
)
8475 for (x
= 0; x
< image_width
; ++x
)
8477 int i
= raster
[y
* image_width
+ x
];
8478 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8479 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8483 /* Save GIF image extension data for `image-extension-data'.
8484 Format is (count IMAGES FUNCTION "BYTES" ...). */
8485 img
->data
.lisp_val
= Qnil
;
8486 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
8488 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
8489 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
8490 /* Append (... FUNCTION "BYTES") */
8491 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
8492 Fcons (make_number (ext
->Function
),
8493 img
->data
.lisp_val
));
8494 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
8496 if (gif
->ImageCount
> 1)
8497 img
->data
.lisp_val
= Fcons (Qcount
,
8498 Fcons (make_number (gif
->ImageCount
),
8499 img
->data
.lisp_val
));
8501 fn_DGifCloseFile (gif
);
8503 /* Maybe fill in the background field while we have ximg handy. */
8504 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8505 /* Casting avoids a GCC warning. */
8506 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8508 /* Put the image into the pixmap, then free the X image and its buffer. */
8509 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8510 x_destroy_x_image (ximg
);
8516 #else /* !HAVE_GIF */
8524 #if USE_MAC_IMAGE_IO
8525 return image_load_image_io (f
, img
, kUTTypeGIF
);
8526 #else /* !USE_MAC_IMAGE_IO */
8527 Lisp_Object specified_file
, file
;
8528 Lisp_Object specified_data
;
8530 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8538 Lisp_Object specified_bg
;
8543 TimeScale time_scale
;
8544 TimeValue time
, duration
;
8549 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8550 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8552 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8555 if (NILP (specified_data
))
8557 /* Read from a file */
8561 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8565 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8570 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8571 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8575 if (!graphic_p
&& !movie_p
)
8577 if (prefer_graphic_p
)
8578 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8579 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8582 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8583 CloseMovieFile (refnum
);
8586 image_error ("Error reading `%s'", file
, Qnil
);
8592 /* Memory source! */
8594 long file_type_atom
[3];
8596 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8599 image_error ("Cannot allocate data handle for `%s'",
8604 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8605 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8606 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8607 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8610 err
= PtrAndHand ("\p", dref
, 1);
8612 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8615 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8618 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8619 &movie_p
, &prefer_graphic_p
, 0);
8623 if (!graphic_p
&& !movie_p
)
8625 if (prefer_graphic_p
)
8629 DisposeHandle (dref
);
8630 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8634 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8635 HandleDataHandlerSubType
);
8636 DisposeHandle (dref
);
8641 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8642 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8643 track
= GetMovieIndTrack (movie
, 1);
8644 media
= GetTrackMedia (track
);
8645 nsamples
= GetMediaSampleCount (media
);
8646 if (ino
>= nsamples
)
8648 image_error ("Invalid image number `%s' in image `%s'",
8652 time_scale
= GetMediaTimeScale (media
);
8654 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8655 if (!STRINGP (specified_bg
)
8656 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8658 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8659 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8660 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8661 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8663 GetMovieBox (movie
, &rect
);
8664 width
= img
->width
= rect
.right
- rect
.left
;
8665 height
= img
->height
= rect
.bottom
- rect
.top
;
8666 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8669 GetGWorld (&old_port
, &old_gdh
);
8670 SetGWorld (ximg
, NULL
);
8671 bg_color
.red
= color
.red
;
8672 bg_color
.green
= color
.green
;
8673 bg_color
.blue
= color
.blue
;
8674 RGBBackColor (&bg_color
);
8675 SetGWorld (old_port
, old_gdh
);
8676 SetMovieActive (movie
, 1);
8677 SetMovieGWorld (movie
, ximg
, NULL
);
8678 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8679 SetMovieTimeValue (movie
, time
);
8680 MoviesTask (movie
, 0L);
8681 DisposeTrackMedia (media
);
8682 DisposeMovieTrack (track
);
8683 DisposeMovie (movie
);
8687 /* Save GIF image extension data for `image-extension-data'.
8688 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8690 Lisp_Object gce
= make_uninit_string (4);
8691 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8693 /* Fill the delay time field. */
8694 SSET (gce
, 1, centisec
& 0xff);
8695 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8696 /* We don't know about other fields. */
8700 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8701 make_number (0xf9), gce
);
8704 /* Maybe fill in the background field while we have ximg handy. */
8705 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8706 IMAGE_BACKGROUND (img
, f
, ximg
);
8708 /* Put the image into the pixmap. */
8709 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8710 x_destroy_x_image (ximg
);
8714 image_error ("Cannot open `%s'", file
, Qnil
);
8717 DisposeTrackMedia (media
);
8719 DisposeMovieTrack (track
);
8721 DisposeMovie (movie
);
8725 #endif /* !USE_MAC_IMAGE_IO */
8731 gif_load (struct frame
*f
, struct image
*img
)
8733 return ns_load_image(f
, img
,
8734 image_spec_value (img
->spec
, QCfile
, NULL
),
8735 image_spec_value (img
->spec
, QCdata
, NULL
));
8737 #endif /* HAVE_NS */
8739 #endif /* HAVE_GIF */
8743 /***********************************************************************
8745 ***********************************************************************/
8747 #if defined (HAVE_RSVG)
8749 /* Function prototypes. */
8751 static int svg_image_p
P_ ((Lisp_Object object
));
8752 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
8754 static int svg_load_image
P_ ((struct frame
*, struct image
*,
8755 unsigned char *, unsigned int));
8757 /* The symbol `svg' identifying images of this type. */
8761 /* Indices of image specification fields in svg_format, below. */
8763 enum svg_keyword_index
8778 /* Vector of image_keyword structures describing the format
8779 of valid user-defined image specifications. */
8781 static struct image_keyword svg_format
[SVG_LAST
] =
8783 {":type", IMAGE_SYMBOL_VALUE
, 1},
8784 {":data", IMAGE_STRING_VALUE
, 0},
8785 {":file", IMAGE_STRING_VALUE
, 0},
8786 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8787 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8788 {":relief", IMAGE_INTEGER_VALUE
, 0},
8789 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8790 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8791 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8792 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8795 /* Structure describing the image type `svg'. Its the same type of
8796 structure defined for all image formats, handled by emacs image
8797 functions. See struct image_type in dispextern.h. */
8799 static struct image_type svg_type
=
8801 /* An identifier showing that this is an image structure for the SVG format. */
8803 /* Handle to a function that can be used to identify a SVG file. */
8805 /* Handle to function used to load a SVG file. */
8807 /* Handle to function to free sresources for SVG. */
8809 /* An internal field to link to the next image type in a list of
8810 image types, will be filled in when registering the format. */
8815 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8816 this by calling parse_image_spec and supplying the keywords that
8817 identify the SVG format. */
8820 svg_image_p (object
)
8823 struct image_keyword fmt
[SVG_LAST
];
8824 bcopy (svg_format
, fmt
, sizeof fmt
);
8826 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
8829 /* Must specify either the :data or :file keyword. */
8830 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
8833 #include <librsvg/rsvg.h>
8837 /* SVG library functions. */
8838 DEF_IMGLIB_FN (rsvg_handle_new
);
8839 DEF_IMGLIB_FN (rsvg_handle_get_dimensions
);
8840 DEF_IMGLIB_FN (rsvg_handle_write
);
8841 DEF_IMGLIB_FN (rsvg_handle_close
);
8842 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
8843 DEF_IMGLIB_FN (rsvg_handle_free
);
8845 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
8846 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
8847 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
8848 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
8849 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
8850 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
8851 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
8852 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
8854 DEF_IMGLIB_FN (g_type_init
);
8855 DEF_IMGLIB_FN (g_object_unref
);
8856 DEF_IMGLIB_FN (g_error_free
);
8858 Lisp_Object Qgdk_pixbuf
, Qglib
;
8861 init_svg_functions (Lisp_Object libraries
)
8863 HMODULE library
, gdklib
, glib
;
8865 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
8866 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
8867 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
8870 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
8871 LOAD_IMGLIB_FN (library
, rsvg_handle_get_dimensions
);
8872 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
8873 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
8874 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
8875 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
8877 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
8878 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
8879 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
8880 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
8881 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
8882 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
8883 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
8884 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
8886 LOAD_IMGLIB_FN (glib
, g_type_init
);
8887 LOAD_IMGLIB_FN (glib
, g_object_unref
);
8888 LOAD_IMGLIB_FN (glib
, g_error_free
);
8893 /* The following aliases for library functions allow dynamic loading
8894 to be used on some platforms. */
8895 #define fn_rsvg_handle_new rsvg_handle_new
8896 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
8897 #define fn_rsvg_handle_write rsvg_handle_write
8898 #define fn_rsvg_handle_close rsvg_handle_close
8899 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8900 #define fn_rsvg_handle_free rsvg_handle_free
8902 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8903 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8904 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8905 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8906 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8907 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8908 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8909 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8911 #define fn_g_type_init g_type_init
8912 #define fn_g_object_unref g_object_unref
8913 #define fn_g_error_free g_error_free
8914 #endif /* !HAVE_NTGUI */
8916 /* Load SVG image IMG for use on frame F. Value is non-zero if
8917 successful. this function will go into the svg_type structure, and
8918 the prototype thus needs to be compatible with that structure. */
8926 Lisp_Object file_name
;
8928 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8929 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8930 if (STRINGP (file_name
))
8933 unsigned char *contents
;
8935 struct gcpro gcpro1
;
8937 file
= x_find_image_file (file_name
);
8939 if (!STRINGP (file
))
8941 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
8946 /* Read the entire file into memory. */
8947 contents
= slurp_file (SDATA (file
), &size
);
8948 if (contents
== NULL
)
8950 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8954 /* If the file was slurped into memory properly, parse it. */
8955 success_p
= svg_load_image (f
, img
, contents
, size
);
8959 /* Else its not a file, its a lisp object. Load the image from a
8960 lisp object rather than a file. */
8965 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8966 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8972 /* svg_load_image is a helper function for svg_load, which does the
8973 actual loading given contents and size, apart from frame and image
8974 structures, passed from svg_load.
8976 Uses librsvg to do most of the image processing.
8978 Returns non-zero when successful. */
8980 svg_load_image (f
, img
, contents
, size
)
8981 /* Pointer to emacs frame structure. */
8983 /* Pointer to emacs image structure. */
8985 /* String containing the SVG XML data to be parsed. */
8986 unsigned char *contents
;
8987 /* Size of data in bytes. */
8990 RsvgHandle
*rsvg_handle
;
8991 RsvgDimensionData dimension_data
;
8992 GError
*error
= NULL
;
8996 const guint8
*pixels
;
8999 Lisp_Object specified_bg
;
9004 /* g_type_init is a glib function that must be called prior to using
9005 gnome type library functions. */
9007 /* Make a handle to a new rsvg object. */
9008 rsvg_handle
= fn_rsvg_handle_new ();
9010 /* Parse the contents argument and fill in the rsvg_handle. */
9011 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
9012 if (error
) goto rsvg_error
;
9014 /* The parsing is complete, rsvg_handle is ready to used, close it
9015 for further writes. */
9016 fn_rsvg_handle_close (rsvg_handle
, &error
);
9017 if (error
) goto rsvg_error
;
9019 fn_rsvg_handle_get_dimensions (rsvg_handle
, &dimension_data
);
9020 if (! check_image_size (f
, dimension_data
.width
, dimension_data
.height
))
9023 /* We can now get a valid pixel buffer from the svg file, if all
9025 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
9026 if (!pixbuf
) goto rsvg_error
;
9027 fn_g_object_unref (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 fn_g_object_unref (rsvg_handle
);
9149 /* FIXME: Use error->message so the user knows what is the actual
9150 problem with the image. */
9151 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
9152 fn_g_error_free (error
);
9156 #endif /* defined (HAVE_RSVG) */
9161 /***********************************************************************
9163 ***********************************************************************/
9165 #ifdef HAVE_X_WINDOWS
9166 #define HAVE_GHOSTSCRIPT 1
9167 #endif /* HAVE_X_WINDOWS */
9169 /* The symbol `postscript' identifying images of this type. */
9171 Lisp_Object Qpostscript
;
9173 #ifdef HAVE_GHOSTSCRIPT
9175 static int gs_image_p
P_ ((Lisp_Object object
));
9176 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
9177 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
9179 /* Keyword symbols. */
9181 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
9183 /* Indices of image specification fields in gs_format, below. */
9185 enum gs_keyword_index
9203 /* Vector of image_keyword structures describing the format
9204 of valid user-defined image specifications. */
9206 static struct image_keyword gs_format
[GS_LAST
] =
9208 {":type", IMAGE_SYMBOL_VALUE
, 1},
9209 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9210 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9211 {":file", IMAGE_STRING_VALUE
, 1},
9212 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9213 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9214 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9215 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9216 {":relief", IMAGE_INTEGER_VALUE
, 0},
9217 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9218 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9219 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9220 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9223 /* Structure describing the image type `ghostscript'. */
9225 static struct image_type gs_type
=
9235 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9238 gs_clear_image (f
, img
)
9242 /* IMG->data.ptr_val may contain a recorded colormap. */
9243 xfree (img
->data
.ptr_val
);
9244 x_clear_image (f
, img
);
9248 /* Return non-zero if OBJECT is a valid Ghostscript image
9255 struct image_keyword fmt
[GS_LAST
];
9259 bcopy (gs_format
, fmt
, sizeof fmt
);
9261 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9264 /* Bounding box must be a list or vector containing 4 integers. */
9265 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9268 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9269 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9274 else if (VECTORP (tem
))
9276 if (XVECTOR (tem
)->size
!= 4)
9278 for (i
= 0; i
< 4; ++i
)
9279 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9289 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9298 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9299 struct gcpro gcpro1
, gcpro2
;
9301 double in_width
, in_height
;
9302 Lisp_Object pixel_colors
= Qnil
;
9304 /* Compute pixel size of pixmap needed from the given size in the
9305 image specification. Sizes in the specification are in pt. 1 pt
9306 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9308 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9309 in_width
= XFASTINT (pt_width
) / 72.0;
9310 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9311 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9312 in_height
= XFASTINT (pt_height
) / 72.0;
9313 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9315 if (!check_image_size (f
, img
->width
, img
->height
))
9317 image_error ("Invalid image size", Qnil
, Qnil
);
9321 /* Create the pixmap. */
9322 xassert (img
->pixmap
== NO_PIXMAP
);
9324 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9326 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9327 img
->width
, img
->height
,
9328 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9333 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9337 /* Call the loader to fill the pixmap. It returns a process object
9338 if successful. We do not record_unwind_protect here because
9339 other places in redisplay like calling window scroll functions
9340 don't either. Let the Lisp loader use `unwind-protect' instead. */
9341 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9343 sprintf (buffer
, "%lu %lu",
9344 (unsigned long) FRAME_X_WINDOW (f
),
9345 (unsigned long) img
->pixmap
);
9346 window_and_pixmap_id
= build_string (buffer
);
9348 sprintf (buffer
, "%lu %lu",
9349 FRAME_FOREGROUND_PIXEL (f
),
9350 FRAME_BACKGROUND_PIXEL (f
));
9351 pixel_colors
= build_string (buffer
);
9353 XSETFRAME (frame
, f
);
9354 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9356 loader
= intern ("gs-load-image");
9358 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9359 make_number (img
->width
),
9360 make_number (img
->height
),
9361 window_and_pixmap_id
,
9364 return PROCESSP (img
->data
.lisp_val
);
9368 /* Kill the Ghostscript process that was started to fill PIXMAP on
9369 frame F. Called from XTread_socket when receiving an event
9370 telling Emacs that Ghostscript has finished drawing. */
9373 x_kill_gs_process (pixmap
, f
)
9377 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
9381 /* Find the image containing PIXMAP. */
9382 for (i
= 0; i
< c
->used
; ++i
)
9383 if (c
->images
[i
]->pixmap
== pixmap
)
9386 /* Should someone in between have cleared the image cache, for
9387 instance, give up. */
9391 /* Kill the GS process. We should have found PIXMAP in the image
9392 cache and its image should contain a process object. */
9394 xassert (PROCESSP (img
->data
.lisp_val
));
9395 Fkill_process (img
->data
.lisp_val
, Qnil
);
9396 img
->data
.lisp_val
= Qnil
;
9398 #if defined (HAVE_X_WINDOWS)
9400 /* On displays with a mutable colormap, figure out the colors
9401 allocated for the image by looking at the pixels of an XImage for
9403 class = FRAME_X_VISUAL (f
)->class;
9404 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9410 /* Try to get an XImage for img->pixmep. */
9411 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9412 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9417 /* Initialize the color table. */
9418 init_color_table ();
9420 /* For each pixel of the image, look its color up in the
9421 color table. After having done so, the color table will
9422 contain an entry for each color used by the image. */
9423 for (y
= 0; y
< img
->height
; ++y
)
9424 for (x
= 0; x
< img
->width
; ++x
)
9426 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9427 lookup_pixel_color (f
, pixel
);
9430 /* Record colors in the image. Free color table and XImage. */
9431 #ifdef COLOR_TABLE_SUPPORT
9432 img
->colors
= colors_in_color_table (&img
->ncolors
);
9433 free_color_table ();
9435 XDestroyImage (ximg
);
9437 #if 0 /* This doesn't seem to be the case. If we free the colors
9438 here, we get a BadAccess later in x_clear_image when
9439 freeing the colors. */
9440 /* We have allocated colors once, but Ghostscript has also
9441 allocated colors on behalf of us. So, to get the
9442 reference counts right, free them once. */
9444 x_free_colors (f
, img
->colors
, img
->ncolors
);
9448 image_error ("Cannot get X image of `%s'; colors will not be freed",
9453 #endif /* HAVE_X_WINDOWS */
9455 /* Now that we have the pixmap, compute mask and transform the
9456 image if requested. */
9458 postprocess_image (f
, img
);
9462 #endif /* HAVE_GHOSTSCRIPT */
9465 /***********************************************************************
9467 ***********************************************************************/
9471 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9472 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
9476 return valid_image_p (spec
) ? Qt
: Qnil
;
9480 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
9486 if (valid_image_p (spec
))
9487 id
= lookup_image (SELECTED_FRAME (), spec
);
9490 return make_number (id
);
9493 #endif /* GLYPH_DEBUG != 0 */
9496 /***********************************************************************
9498 ***********************************************************************/
9501 /* Image types that rely on external libraries are loaded dynamically
9502 if the library is available. */
9503 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9504 define_image_type (image_type, init_lib_fn (libraries))
9506 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9507 define_image_type (image_type, 1)
9508 #endif /* HAVE_NTGUI */
9510 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
9511 doc
: /* Initialize image library implementing image type TYPE.
9512 Return non-nil if TYPE is a supported image type.
9514 Image types pbm and xbm are prebuilt; other types are loaded here.
9515 Libraries to load are specified in alist LIBRARIES (usually, the value
9516 of `image-library-alist', which see). */)
9518 Lisp_Object type
, libraries
;
9522 /* Don't try to reload the library. */
9523 tested
= Fassq (type
, Vimage_type_cache
);
9525 return XCDR (tested
);
9527 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
9528 if (EQ (type
, Qxpm
))
9529 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
9532 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9533 if (EQ (type
, Qjpeg
))
9534 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
9537 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9538 if (EQ (type
, Qtiff
))
9539 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
9542 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9543 if (EQ (type
, Qgif
))
9544 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
9547 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9548 if (EQ (type
, Qpng
))
9549 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
9552 #if defined (HAVE_RSVG)
9553 if (EQ (type
, Qsvg
))
9554 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
9557 #ifdef HAVE_GHOSTSCRIPT
9558 if (EQ (type
, Qpostscript
))
9559 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
9562 /* If the type is not recognized, avoid testing it ever again. */
9563 CACHE_IMAGE_TYPE (type
, Qnil
);
9570 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
9572 /* Initialize this only once, since that's what we do with Vimage_types
9573 and they are supposed to be in sync. Initializing here gives correct
9574 operation on GNU/Linux of calling dump-emacs after loading some images. */
9577 /* Must be defined now becase we're going to update it below, while
9578 defining the supported image types. */
9579 DEFVAR_LISP ("image-types", &Vimage_types
,
9580 doc
: /* List of potentially supported image types.
9581 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9582 To check whether it is really supported, use `image-type-available-p'. */);
9583 Vimage_types
= Qnil
;
9585 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
9586 doc
: /* Alist of image types vs external libraries needed to display them.
9588 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9589 representing a supported image type, and the rest are strings giving
9590 alternate filenames for the corresponding external libraries.
9592 Emacs tries to load the libraries in the order they appear on the
9593 list; if none is loaded, the running session of Emacs won't
9594 support the image type. Types 'pbm and 'xbm don't need to be
9595 listed; they are always supported. */);
9596 Vimage_library_alist
= Qnil
;
9597 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
9599 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
9600 doc
: /* Maximum size of images.
9601 Emacs will not load an image into memory if its pixel width or
9602 pixel height exceeds this limit.
9604 If the value is an integer, it directly specifies the maximum
9605 image height and width, measured in pixels. If it is a floating
9606 point number, it specifies the maximum image height and width
9607 as a ratio to the frame height and width. If the value is
9608 non-numeric, there is no explicit limit on the size of images. */);
9609 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
9611 Vimage_type_cache
= Qnil
;
9612 staticpro (&Vimage_type_cache
);
9614 Qpbm
= intern ("pbm");
9616 ADD_IMAGE_TYPE (Qpbm
);
9618 Qxbm
= intern ("xbm");
9620 ADD_IMAGE_TYPE (Qxbm
);
9622 define_image_type (&xbm_type
, 1);
9623 define_image_type (&pbm_type
, 1);
9625 Qcount
= intern ("count");
9626 staticpro (&Qcount
);
9628 QCascent
= intern (":ascent");
9629 staticpro (&QCascent
);
9630 QCmargin
= intern (":margin");
9631 staticpro (&QCmargin
);
9632 QCrelief
= intern (":relief");
9633 staticpro (&QCrelief
);
9634 QCconversion
= intern (":conversion");
9635 staticpro (&QCconversion
);
9636 QCcolor_symbols
= intern (":color-symbols");
9637 staticpro (&QCcolor_symbols
);
9638 QCheuristic_mask
= intern (":heuristic-mask");
9639 staticpro (&QCheuristic_mask
);
9640 QCindex
= intern (":index");
9641 staticpro (&QCindex
);
9642 QCmatrix
= intern (":matrix");
9643 staticpro (&QCmatrix
);
9644 QCcolor_adjustment
= intern (":color-adjustment");
9645 staticpro (&QCcolor_adjustment
);
9646 QCmask
= intern (":mask");
9647 staticpro (&QCmask
);
9649 Qlaplace
= intern ("laplace");
9650 staticpro (&Qlaplace
);
9651 Qemboss
= intern ("emboss");
9652 staticpro (&Qemboss
);
9653 Qedge_detection
= intern ("edge-detection");
9654 staticpro (&Qedge_detection
);
9655 Qheuristic
= intern ("heuristic");
9656 staticpro (&Qheuristic
);
9658 Qpostscript
= intern ("postscript");
9659 staticpro (&Qpostscript
);
9660 #ifdef HAVE_GHOSTSCRIPT
9661 ADD_IMAGE_TYPE (Qpostscript
);
9662 QCloader
= intern (":loader");
9663 staticpro (&QCloader
);
9664 QCbounding_box
= intern (":bounding-box");
9665 staticpro (&QCbounding_box
);
9666 QCpt_width
= intern (":pt-width");
9667 staticpro (&QCpt_width
);
9668 QCpt_height
= intern (":pt-height");
9669 staticpro (&QCpt_height
);
9670 #endif /* HAVE_GHOSTSCRIPT */
9672 #if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
9673 Qxpm
= intern ("xpm");
9675 ADD_IMAGE_TYPE (Qxpm
);
9678 #if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9679 Qjpeg
= intern ("jpeg");
9681 ADD_IMAGE_TYPE (Qjpeg
);
9684 #if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9685 Qtiff
= intern ("tiff");
9687 ADD_IMAGE_TYPE (Qtiff
);
9690 #if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9691 Qgif
= intern ("gif");
9693 ADD_IMAGE_TYPE (Qgif
);
9696 #if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9697 Qpng
= intern ("png");
9699 ADD_IMAGE_TYPE (Qpng
);
9702 #if defined (HAVE_RSVG)
9703 Qsvg
= intern ("svg");
9705 ADD_IMAGE_TYPE (Qsvg
);
9707 Qgdk_pixbuf
= intern ("gdk-pixbuf");
9708 staticpro (&Qgdk_pixbuf
);
9709 Qglib
= intern ("glib");
9711 #endif /* HAVE_NTGUI */
9712 #endif /* HAVE_RSVG */
9714 defsubr (&Sinit_image_library
);
9715 defsubr (&Sclear_image_cache
);
9716 defsubr (&Simage_refresh
);
9717 defsubr (&Simage_size
);
9718 defsubr (&Simage_mask_p
);
9719 defsubr (&Simage_extension_data
);
9723 defsubr (&Slookup_image
);
9726 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9727 doc
: /* Non-nil means always draw a cross over disabled images.
9728 Disabled images are those having a `:conversion disabled' property.
9729 A cross is always drawn on black & white displays. */);
9730 cross_disabled_images
= 0;
9732 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9733 doc
: /* List of directories to search for window system bitmap files. */);
9734 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9736 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9737 doc
: /* Time after which cached images are removed from the cache.
9738 When an image has not been displayed this many seconds, remove it
9739 from the image cache. Value must be an integer or nil with nil
9740 meaning don't clear the cache. */);
9741 Vimage_cache_eviction_delay
= make_number (30 * 60);
9749 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9750 (do not change this comment) */