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)
134 /* Search path for bitmap files. */
136 Lisp_Object Vx_bitmap_file_path
;
139 static void x_disable_image
P_ ((struct frame
*, struct image
*));
140 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
143 static void init_color_table
P_ ((void));
144 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
145 #ifdef COLOR_TABLE_SUPPORT
146 static void free_color_table
P_ ((void));
147 static unsigned long *colors_in_color_table
P_ ((int *n
));
148 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
151 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
152 id, which is just an int that this section returns. Bitmaps are
153 reference counted so they can be shared among frames.
155 Bitmap indices are guaranteed to be > 0, so a negative number can
156 be used to indicate no bitmap.
158 If you use x_create_bitmap_from_data, then you must keep track of
159 the bitmaps yourself. That is, creating a bitmap from the same
160 data more than once will not be caught. */
165 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
166 Display
*display
; /* not used */
168 int x
, y
; /* not used */
169 unsigned int width
, height
; /* not used */
170 unsigned long plane_mask
; /* not used */
171 int format
; /* not used */
173 #if !USE_MAC_IMAGE_IO
175 xassert (x
== 0 && y
== 0);
178 SetRect (&ri
, 0, 0, width
, height
);
179 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
181 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
184 LockPixels (GetGWorldPixMap (pixmap
));
191 XPutPixel (ximage
, x
, y
, pixel
)
197 if (ximage
->bits_per_pixel
== 32)
198 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
200 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
202 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
203 short depth
= GetPixDepth (pixmap
);
205 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
208 char *base_addr
= GetPixBaseAddr (pixmap
);
209 short row_bytes
= GetPixRowBytes (pixmap
);
211 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
217 char *base_addr
= GetPixBaseAddr (pixmap
);
218 short row_bytes
= GetPixRowBytes (pixmap
);
220 if (pixel
== PIX_MASK_DRAW
)
221 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
223 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
231 GetGWorld (&old_port
, &old_gdh
);
232 SetGWorld (ximage
, NULL
);
234 color
.red
= RED16_FROM_ULONG (pixel
);
235 color
.green
= GREEN16_FROM_ULONG (pixel
);
236 color
.blue
= BLUE16_FROM_ULONG (pixel
);
238 SetCPixel (x
, y
, &color
);
240 SetGWorld (old_port
, old_gdh
);
246 XGetPixel (ximage
, x
, y
)
251 if (ximage
->bits_per_pixel
== 32)
252 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
254 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
256 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
257 short depth
= GetPixDepth (pixmap
);
259 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
262 char *base_addr
= GetPixBaseAddr (pixmap
);
263 short row_bytes
= GetPixRowBytes (pixmap
);
265 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
271 char *base_addr
= GetPixBaseAddr (pixmap
);
272 short row_bytes
= GetPixRowBytes (pixmap
);
274 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
275 return PIX_MASK_DRAW
;
277 return PIX_MASK_RETAIN
;
285 GetGWorld (&old_port
, &old_gdh
);
286 SetGWorld (ximage
, NULL
);
288 GetCPixel (x
, y
, &color
);
290 SetGWorld (old_port
, old_gdh
);
291 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
300 #if !USE_MAC_IMAGE_IO
301 UnlockPixels (GetGWorldPixMap (ximg
));
308 mac_data_provider_release_data (info
, data
, size
)
313 xfree ((void *)data
);
318 mac_create_cg_image_from_image (f
, img
)
323 XImagePtr ximg
= img
->pixmap
;
324 CGDataProviderRef provider
;
330 unsigned long color
, alpha
;
332 for (y
= 0; y
< ximg
->height
; y
++)
333 for (x
= 0; x
< ximg
->width
; x
++)
335 color
= XGetPixel (ximg
, x
, y
);
336 alpha
= XGetPixel (img
->mask
, x
, y
);
337 XPutPixel (ximg
, x
, y
,
338 ARGB_TO_ULONG (alpha
,
339 RED_FROM_ULONG (color
)
340 * alpha
/ PIX_MASK_DRAW
,
341 GREEN_FROM_ULONG (color
)
342 * alpha
/ PIX_MASK_DRAW
,
343 BLUE_FROM_ULONG (color
)
344 * alpha
/ PIX_MASK_DRAW
));
346 xfree (img
->mask
->data
);
347 img
->mask
->data
= NULL
;
350 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
351 ximg
->bytes_per_line
* ximg
->height
,
352 mac_data_provider_release_data
);
354 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
355 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
356 (img
->mask
? kCGImageAlphaPremultipliedFirst
357 : kCGImageAlphaNoneSkipFirst
)
358 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
359 | kCGBitmapByteOrder32Host
361 , provider
, NULL
, 0, kCGRenderingIntentDefault
);
362 CGDataProviderRelease (provider
);
368 CGImageRef result
= NULL
;
375 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
376 img
->width
, img
->height
, 1);
383 GetGWorld (&old_port
, &old_gdh
);
384 SetGWorld (mask
, NULL
);
385 BackColor (blackColor
); /* Don't mask. */
386 SetRect (&r
, 0, 0, img
->width
, img
->height
);
388 SetGWorld (old_port
, old_gdh
);
393 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
394 GetGWorldPixMap (mask
), &result
);
395 if (mask
!= img
->mask
)
396 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
403 #endif /* USE_CG_DRAWING */
407 /* Functions to access the contents of a bitmap, given an id. */
410 x_bitmap_height (f
, id
)
414 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
418 x_bitmap_width (f
, id
)
422 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
425 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
427 x_bitmap_pixmap (f
, id
)
431 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
435 #ifdef HAVE_X_WINDOWS
437 x_bitmap_mask (f
, id
)
441 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
445 /* Allocate a new bitmap record. Returns index of new record. */
448 x_allocate_bitmap_record (f
)
451 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
454 if (dpyinfo
->bitmaps
== NULL
)
456 dpyinfo
->bitmaps_size
= 10;
458 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
459 dpyinfo
->bitmaps_last
= 1;
463 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
464 return ++dpyinfo
->bitmaps_last
;
466 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
467 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
470 dpyinfo
->bitmaps_size
*= 2;
472 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
473 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
474 return ++dpyinfo
->bitmaps_last
;
477 /* Add one reference to the reference count of the bitmap with id ID. */
480 x_reference_bitmap (f
, id
)
484 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
487 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
490 x_create_bitmap_from_data (f
, bits
, width
, height
)
493 unsigned int width
, height
;
495 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
498 #ifdef HAVE_X_WINDOWS
500 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
501 bits
, width
, height
);
504 #endif /* HAVE_X_WINDOWS */
508 bitmap
= CreateBitmap (width
, height
,
509 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
510 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
514 #endif /* HAVE_NTGUI */
517 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
522 id
= x_allocate_bitmap_record (f
);
524 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
525 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
528 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
529 dpyinfo
->bitmaps
[id
- 1].height
= height
;
530 dpyinfo
->bitmaps
[id
- 1].width
= width
;
531 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
533 #ifdef HAVE_X_WINDOWS
534 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
535 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
536 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
537 #endif /* HAVE_X_WINDOWS */
540 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
541 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
542 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
543 #endif /* HAVE_NTGUI */
548 /* Create bitmap from file FILE for frame F. */
551 x_create_bitmap_from_file (f
, file
)
556 return -1; /* MAC_TODO : bitmap support */
560 return -1; /* W32_TODO : bitmap support */
561 #endif /* HAVE_NTGUI */
563 #ifdef HAVE_X_WINDOWS
564 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
565 unsigned int width
, height
;
567 int xhot
, yhot
, result
, id
;
572 /* Look for an existing bitmap with the same name. */
573 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
575 if (dpyinfo
->bitmaps
[id
].refcount
576 && dpyinfo
->bitmaps
[id
].file
577 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
579 ++dpyinfo
->bitmaps
[id
].refcount
;
584 /* Search bitmap-file-path for the file, if appropriate. */
585 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
590 filename
= (char *) SDATA (found
);
592 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
593 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
594 if (result
!= BitmapSuccess
)
597 id
= x_allocate_bitmap_record (f
);
598 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
599 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
600 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
601 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
602 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
603 dpyinfo
->bitmaps
[id
- 1].height
= height
;
604 dpyinfo
->bitmaps
[id
- 1].width
= width
;
605 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
608 #endif /* HAVE_X_WINDOWS */
614 free_bitmap_record (dpyinfo
, bm
)
615 Display_Info
*dpyinfo
;
618 #ifdef HAVE_X_WINDOWS
619 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
621 XFreePixmap (dpyinfo
->display
, bm
->mask
);
622 #endif /* HAVE_X_WINDOWS */
625 DeleteObject (bm
->pixmap
);
626 #endif /* HAVE_NTGUI */
629 xfree (bm
->bitmap_data
); /* Added ++kfs */
630 bm
->bitmap_data
= NULL
;
640 /* Remove reference to bitmap with id number ID. */
643 x_destroy_bitmap (f
, id
)
647 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
651 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
653 if (--bm
->refcount
== 0)
656 free_bitmap_record (dpyinfo
, bm
);
662 /* Free all the bitmaps for the display specified by DPYINFO. */
665 x_destroy_all_bitmaps (dpyinfo
)
666 Display_Info
*dpyinfo
;
669 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
671 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
672 if (bm
->refcount
> 0)
673 free_bitmap_record (dpyinfo
, bm
);
675 dpyinfo
->bitmaps_last
= 0;
679 #ifdef HAVE_X_WINDOWS
681 /* Useful functions defined in the section
682 `Image type independent image structures' below. */
684 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
687 unsigned long height
));
689 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
690 int depth
, XImagePtr
*ximg
,
693 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
696 /* Create a mask of a bitmap. Note is this not a perfect mask.
697 It's nicer with some borders in this context */
700 x_create_bitmap_mask (f
, id
)
705 XImagePtr ximg
, mask_img
;
706 unsigned long width
, height
;
709 unsigned long x
, y
, xp
, xm
, yp
, ym
;
712 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
717 pixmap
= x_bitmap_pixmap (f
, id
);
718 width
= x_bitmap_width (f
, id
);
719 height
= x_bitmap_height (f
, id
);
722 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
731 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
736 XDestroyImage (ximg
);
740 bg
= four_corners_best (ximg
, NULL
, width
, height
);
742 for (y
= 0; y
< ximg
->height
; ++y
)
744 for (x
= 0; x
< ximg
->width
; ++x
)
746 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
747 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
748 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
749 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
750 if (XGetPixel (ximg
, x
, y
) == bg
751 && XGetPixel (ximg
, x
, yp
) == bg
752 && XGetPixel (ximg
, x
, ym
) == bg
753 && XGetPixel (ximg
, xp
, y
) == bg
754 && XGetPixel (ximg
, xp
, yp
) == bg
755 && XGetPixel (ximg
, xp
, ym
) == bg
756 && XGetPixel (ximg
, xm
, y
) == bg
757 && XGetPixel (ximg
, xm
, yp
) == bg
758 && XGetPixel (ximg
, xm
, ym
) == bg
)
759 XPutPixel (mask_img
, x
, y
, 0);
761 XPutPixel (mask_img
, x
, y
, 1);
765 xassert (interrupt_input_blocked
);
766 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
767 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
769 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
771 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
772 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
774 XDestroyImage (ximg
);
775 x_destroy_x_image (mask_img
);
780 #endif /* HAVE_X_WINDOWS */
783 /***********************************************************************
785 ***********************************************************************/
787 /* Value is the number of elements of vector VECTOR. */
789 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
791 /* List of supported image types. Use define_image_type to add new
792 types. Use lookup_image_type to find a type for a given symbol. */
794 static struct image_type
*image_types
;
796 /* A list of symbols, one for each supported image type. */
798 Lisp_Object Vimage_types
;
800 /* An alist of image types and libraries that implement the type. */
802 Lisp_Object Vimage_library_alist
;
804 /* Cache for delayed-loading image types. */
806 static Lisp_Object Vimage_type_cache
;
808 /* The symbol `xbm' which is used as the type symbol for XBM images. */
814 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
815 extern Lisp_Object QCdata
, QCtype
;
816 extern Lisp_Object Qcenter
;
817 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
818 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
819 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
823 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
825 /* Time in seconds after which images should be removed from the cache
828 Lisp_Object Vimage_cache_eviction_delay
;
830 /* Function prototypes. */
832 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
833 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
834 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
835 static void x_laplace
P_ ((struct frame
*, struct image
*));
836 static void x_emboss
P_ ((struct frame
*, struct image
*));
837 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
840 #define CACHE_IMAGE_TYPE(type, status) \
841 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
843 #define ADD_IMAGE_TYPE(type) \
844 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
846 /* Define a new image type from TYPE. This adds a copy of TYPE to
847 image_types and caches the loading status of TYPE. */
850 define_image_type (type
, loaded
)
851 struct image_type
*type
;
860 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
861 The initialized data segment is read-only. */
862 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
863 bcopy (type
, p
, sizeof *p
);
864 p
->next
= image_types
;
869 CACHE_IMAGE_TYPE (*type
->type
, success
);
874 /* Look up image type SYMBOL, and return a pointer to its image_type
875 structure. Value is null if SYMBOL is not a known image type. */
877 static INLINE
struct image_type
*
878 lookup_image_type (symbol
)
881 struct image_type
*type
;
883 /* We must initialize the image-type if it hasn't been already. */
884 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
885 return 0; /* unimplemented */
887 for (type
= image_types
; type
; type
= type
->next
)
888 if (EQ (symbol
, *type
->type
))
895 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
896 valid image specification is a list whose car is the symbol
897 `image', and whose rest is a property list. The property list must
898 contain a value for key `:type'. That value must be the name of a
899 supported image type. The rest of the property list depends on the
903 valid_image_p (object
)
912 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
913 if (EQ (XCAR (tem
), QCtype
))
916 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
918 struct image_type
*type
;
919 type
= lookup_image_type (XCAR (tem
));
921 valid_p
= type
->valid_p (object
);
932 /* Log error message with format string FORMAT and argument ARG.
933 Signaling an error, e.g. when an image cannot be loaded, is not a
934 good idea because this would interrupt redisplay, and the error
935 message display would lead to another redisplay. This function
936 therefore simply displays a message. */
939 image_error (format
, arg1
, arg2
)
941 Lisp_Object arg1
, arg2
;
943 add_to_log (format
, arg1
, arg2
);
948 /***********************************************************************
950 ***********************************************************************/
952 enum image_value_type
954 IMAGE_DONT_CHECK_VALUE_TYPE
,
956 IMAGE_STRING_OR_NIL_VALUE
,
958 IMAGE_POSITIVE_INTEGER_VALUE
,
959 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
960 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
963 IMAGE_FUNCTION_VALUE
,
968 /* Structure used when parsing image specifications. */
972 /* Name of keyword. */
975 /* The type of value allowed. */
976 enum image_value_type type
;
978 /* Non-zero means key must be present. */
981 /* Used to recognize duplicate keywords in a property list. */
984 /* The value that was found. */
989 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
991 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
994 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
995 has the format (image KEYWORD VALUE ...). One of the keyword/
996 value pairs must be `:type TYPE'. KEYWORDS is a vector of
997 image_keywords structures of size NKEYWORDS describing other
998 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1001 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1003 struct image_keyword
*keywords
;
1013 plist
= XCDR (spec
);
1014 while (CONSP (plist
))
1016 Lisp_Object key
, value
;
1018 /* First element of a pair must be a symbol. */
1020 plist
= XCDR (plist
);
1024 /* There must follow a value. */
1027 value
= XCAR (plist
);
1028 plist
= XCDR (plist
);
1030 /* Find key in KEYWORDS. Error if not found. */
1031 for (i
= 0; i
< nkeywords
; ++i
)
1032 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1038 /* Record that we recognized the keyword. If a keywords
1039 was found more than once, it's an error. */
1040 keywords
[i
].value
= value
;
1041 ++keywords
[i
].count
;
1043 if (keywords
[i
].count
> 1)
1046 /* Check type of value against allowed type. */
1047 switch (keywords
[i
].type
)
1049 case IMAGE_STRING_VALUE
:
1050 if (!STRINGP (value
))
1054 case IMAGE_STRING_OR_NIL_VALUE
:
1055 if (!STRINGP (value
) && !NILP (value
))
1059 case IMAGE_SYMBOL_VALUE
:
1060 if (!SYMBOLP (value
))
1064 case IMAGE_POSITIVE_INTEGER_VALUE
:
1065 if (!INTEGERP (value
) || XINT (value
) <= 0)
1069 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1070 if (INTEGERP (value
) && XINT (value
) >= 0)
1073 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1074 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1078 case IMAGE_ASCENT_VALUE
:
1079 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1081 else if (INTEGERP (value
)
1082 && XINT (value
) >= 0
1083 && XINT (value
) <= 100)
1087 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1088 if (!INTEGERP (value
) || XINT (value
) < 0)
1092 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1095 case IMAGE_FUNCTION_VALUE
:
1096 value
= indirect_function (value
);
1098 || COMPILEDP (value
)
1099 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1103 case IMAGE_NUMBER_VALUE
:
1104 if (!INTEGERP (value
) && !FLOATP (value
))
1108 case IMAGE_INTEGER_VALUE
:
1109 if (!INTEGERP (value
))
1113 case IMAGE_BOOL_VALUE
:
1114 if (!NILP (value
) && !EQ (value
, Qt
))
1123 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1127 /* Check that all mandatory fields are present. */
1128 for (i
= 0; i
< nkeywords
; ++i
)
1129 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1132 return NILP (plist
);
1136 /* Return the value of KEY in image specification SPEC. Value is nil
1137 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1138 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1141 image_spec_value (spec
, key
, found
)
1142 Lisp_Object spec
, key
;
1147 xassert (valid_image_p (spec
));
1149 for (tail
= XCDR (spec
);
1150 CONSP (tail
) && CONSP (XCDR (tail
));
1151 tail
= XCDR (XCDR (tail
)))
1153 if (EQ (XCAR (tail
), key
))
1157 return XCAR (XCDR (tail
));
1167 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1168 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1169 PIXELS non-nil means return the size in pixels, otherwise return the
1170 size in canonical character units.
1171 FRAME is the frame on which the image will be displayed. FRAME nil
1172 or omitted means use the selected frame. */)
1173 (spec
, pixels
, frame
)
1174 Lisp_Object spec
, pixels
, frame
;
1179 if (valid_image_p (spec
))
1181 struct frame
*f
= check_x_frame (frame
);
1182 int id
= lookup_image (f
, spec
);
1183 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1184 int width
= img
->width
+ 2 * img
->hmargin
;
1185 int height
= img
->height
+ 2 * img
->vmargin
;
1188 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1189 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1191 size
= Fcons (make_number (width
), make_number (height
));
1194 error ("Invalid image specification");
1200 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1201 doc
: /* Return t if image SPEC has a mask bitmap.
1202 FRAME is the frame on which the image will be displayed. FRAME nil
1203 or omitted means use the selected frame. */)
1205 Lisp_Object spec
, frame
;
1210 if (valid_image_p (spec
))
1212 struct frame
*f
= check_x_frame (frame
);
1213 int id
= lookup_image (f
, spec
);
1214 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1219 error ("Invalid image specification");
1224 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1225 doc
: /* Return extension data for image SPEC.
1226 FRAME is the frame on which the image will be displayed. FRAME nil
1227 or omitted means use the selected frame. */)
1229 Lisp_Object spec
, frame
;
1234 if (valid_image_p (spec
))
1236 struct frame
*f
= check_x_frame (frame
);
1237 int id
= lookup_image (f
, spec
);
1238 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1239 ext
= img
->data
.lisp_val
;
1246 /***********************************************************************
1247 Image type independent image structures
1248 ***********************************************************************/
1250 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1251 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1252 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1254 #define MAX_IMAGE_SIZE 6.0
1255 Lisp_Object Vmax_image_size
;
1257 /* Allocate and return a new image structure for image specification
1258 SPEC. SPEC has a hash value of HASH. */
1260 static struct image
*
1261 make_image (spec
, hash
)
1265 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1266 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1268 xassert (valid_image_p (spec
));
1269 bzero (img
, sizeof *img
);
1270 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1271 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1272 xassert (img
->type
!= NULL
);
1274 img
->data
.lisp_val
= Qnil
;
1275 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1277 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1282 /* Free image IMG which was used on frame F, including its resources. */
1291 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1293 /* Remove IMG from the hash table of its cache. */
1295 img
->prev
->next
= img
->next
;
1297 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1300 img
->next
->prev
= img
->prev
;
1302 c
->images
[img
->id
] = NULL
;
1304 /* Free resources, then free IMG. */
1305 img
->type
->free (f
, img
);
1310 /* Return 1 if the given widths and heights are valid for display;
1311 otherwise, return 0. */
1314 check_image_size (f
, width
, height
)
1321 if (width
<= 0 || height
<= 0)
1324 if (INTEGERP (Vmax_image_size
))
1325 w
= h
= XINT (Vmax_image_size
);
1326 else if (FLOATP (Vmax_image_size
))
1330 w
= FRAME_PIXEL_WIDTH (f
);
1331 h
= FRAME_PIXEL_HEIGHT (f
);
1334 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1335 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1336 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1341 return (width
<= w
&& height
<= h
);
1344 /* Prepare image IMG for display on frame F. Must be called before
1345 drawing an image. */
1348 prepare_image_for_display (f
, img
)
1354 /* We're about to display IMG, so set its timestamp to `now'. */
1356 img
->timestamp
= EMACS_SECS (t
);
1358 /* If IMG doesn't have a pixmap yet, load it now, using the image
1359 type dependent loader function. */
1360 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1361 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1363 #if defined (MAC_OS) && USE_CG_DRAWING
1364 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1366 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1367 if (img
->data
.ptr_val
== NULL
)
1369 img
->load_failed_p
= 1;
1370 img
->type
->free (f
, img
);
1377 /* Value is the number of pixels for the ascent of image IMG when
1378 drawn in face FACE. */
1381 image_ascent (img
, face
, slice
)
1384 struct glyph_slice
*slice
;
1389 if (slice
->height
== img
->height
)
1390 height
= img
->height
+ img
->vmargin
;
1391 else if (slice
->y
== 0)
1392 height
= slice
->height
+ img
->vmargin
;
1394 height
= slice
->height
;
1396 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1401 /* W32 specific version. Why?. ++kfs */
1402 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1403 - FONT_BASE (face
->font
)) / 2;
1405 /* This expression is arranged so that if the image can't be
1406 exactly centered, it will be moved slightly up. This is
1407 because a typical font is `top-heavy' (due to the presence
1408 uppercase letters), so the image placement should err towards
1409 being top-heavy too. It also just generally looks better. */
1410 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1411 #endif /* HAVE_NTGUI */
1414 ascent
= height
/ 2;
1417 ascent
= (int) (height
* img
->ascent
/ 100.0);
1423 /* Image background colors. */
1425 /* Find the "best" corner color of a bitmap.
1426 On W32, XIMG is assumed to a device context with the bitmap selected. */
1428 static RGB_PIXEL_COLOR
1429 four_corners_best (ximg
, corners
, width
, height
)
1430 XImagePtr_or_DC ximg
;
1432 unsigned long width
, height
;
1434 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1437 if (corners
&& corners
[BOT_CORNER
] >= 0)
1439 /* Get the colors at the corner_pixels of ximg. */
1440 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1441 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1442 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1443 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1447 /* Get the colors at the corner_pixels of ximg. */
1448 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1449 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1450 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1451 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1453 /* Choose the most frequently found color as background. */
1454 for (i
= best_count
= 0; i
< 4; ++i
)
1458 for (j
= n
= 0; j
< 4; ++j
)
1459 if (corner_pixels
[i
] == corner_pixels
[j
])
1463 best
= corner_pixels
[i
], best_count
= n
;
1469 /* Portability macros */
1473 #define Destroy_Image(img_dc, prev) \
1474 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1476 #define Free_Pixmap(display, pixmap) \
1477 DeleteObject (pixmap)
1481 #define Destroy_Image(ximg, dummy) \
1482 XDestroyImage (ximg)
1484 #define Free_Pixmap(display, pixmap) \
1485 XFreePixmap (display, pixmap)
1487 #endif /* HAVE_NTGUI */
1490 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1491 it is guessed heuristically. If non-zero, XIMG is an existing
1492 XImage object (or device context with the image selected on W32) to
1493 use for the heuristic. */
1496 image_background (img
, f
, ximg
)
1499 XImagePtr_or_DC ximg
;
1501 if (! img
->background_valid
)
1502 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1504 int free_ximg
= !ximg
;
1507 #endif /* HAVE_NTGUI */
1512 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1513 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1515 HDC frame_dc
= get_frame_dc (f
);
1516 ximg
= CreateCompatibleDC (frame_dc
);
1517 release_frame_dc (f
, frame_dc
);
1518 prev
= SelectObject (ximg
, img
->pixmap
);
1519 #endif /* !HAVE_NTGUI */
1522 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1525 Destroy_Image (ximg
, prev
);
1527 img
->background_valid
= 1;
1530 return img
->background
;
1533 /* Return the `background_transparent' field of IMG. If IMG doesn't
1534 have one yet, it is guessed heuristically. If non-zero, MASK is an
1535 existing XImage object to use for the heuristic. */
1538 image_background_transparent (img
, f
, mask
)
1541 XImagePtr_or_DC mask
;
1543 if (! img
->background_transparent_valid
)
1544 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1548 int free_mask
= !mask
;
1551 #endif /* HAVE_NTGUI */
1556 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1557 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1559 HDC frame_dc
= get_frame_dc (f
);
1560 mask
= CreateCompatibleDC (frame_dc
);
1561 release_frame_dc (f
, frame_dc
);
1562 prev
= SelectObject (mask
, img
->mask
);
1563 #endif /* HAVE_NTGUI */
1566 img
->background_transparent
1567 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1570 Destroy_Image (mask
, prev
);
1573 img
->background_transparent
= 0;
1575 img
->background_transparent_valid
= 1;
1578 return img
->background_transparent
;
1582 /***********************************************************************
1583 Helper functions for X image types
1584 ***********************************************************************/
1586 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1588 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1589 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1591 Lisp_Object color_name
,
1592 unsigned long dflt
));
1595 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1596 free the pixmap if any. MASK_P non-zero means clear the mask
1597 pixmap if any. COLORS_P non-zero means free colors allocated for
1598 the image, if any. */
1601 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1604 int pixmap_p
, mask_p
, colors_p
;
1606 if (pixmap_p
&& img
->pixmap
)
1608 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1609 img
->pixmap
= NO_PIXMAP
;
1610 img
->background_valid
= 0;
1613 if (mask_p
&& img
->mask
)
1615 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1616 img
->mask
= NO_PIXMAP
;
1617 img
->background_transparent_valid
= 0;
1620 if (colors_p
&& img
->ncolors
)
1622 /* MAC_TODO: color table support. */
1623 /* W32_TODO: color table support. */
1624 #ifdef HAVE_X_WINDOWS
1625 x_free_colors (f
, img
->colors
, img
->ncolors
);
1626 #endif /* HAVE_X_WINDOWS */
1627 xfree (img
->colors
);
1632 #if defined (MAC_OS) && USE_CG_DRAWING
1633 if (img
->data
.ptr_val
)
1635 CGImageRelease (img
->data
.ptr_val
);
1636 img
->data
.ptr_val
= NULL
;
1641 /* Free X resources of image IMG which is used on frame F. */
1644 x_clear_image (f
, img
)
1649 x_clear_image_1 (f
, img
, 1, 1, 1);
1654 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1655 cannot be allocated, use DFLT. Add a newly allocated color to
1656 IMG->colors, so that it can be freed again. Value is the pixel
1659 static unsigned long
1660 x_alloc_image_color (f
, img
, color_name
, dflt
)
1663 Lisp_Object color_name
;
1667 unsigned long result
;
1669 xassert (STRINGP (color_name
));
1671 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1673 /* This isn't called frequently so we get away with simply
1674 reallocating the color vector to the needed size, here. */
1677 (unsigned long *) xrealloc (img
->colors
,
1678 img
->ncolors
* sizeof *img
->colors
);
1679 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1680 result
= color
.pixel
;
1690 /***********************************************************************
1692 ***********************************************************************/
1694 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1695 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1696 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1698 /* Return a new, initialized image cache that is allocated from the
1699 heap. Call free_image_cache to free an image cache. */
1701 struct image_cache
*
1704 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1707 bzero (c
, sizeof *c
);
1709 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1710 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1711 c
->buckets
= (struct image
**) xmalloc (size
);
1712 bzero (c
->buckets
, size
);
1717 /* Find an image matching SPEC in the cache, and return it. If no
1718 image is found, return NULL. */
1719 static struct image
*
1720 search_image_cache (f
, spec
, hash
)
1726 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1727 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1729 if (!c
) return NULL
;
1731 /* If the image spec does not specify a background color, the cached
1732 image must have the same background color as the current frame.
1733 The foreground color must also match, for the sake of monochrome
1736 In fact, we could ignore the foreground color matching condition
1737 for color images, or if the image spec specifies :foreground;
1738 similarly we could ignore the background color matching condition
1739 for formats that don't use transparency (such as jpeg), or if the
1740 image spec specifies :background. However, the extra memory
1741 usage is probably negligible in practice, so we don't bother. */
1743 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1744 if (img
->hash
== hash
1745 && !NILP (Fequal (img
->spec
, spec
))
1746 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1747 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1753 /* Search frame F for an image with spec SPEC, and free it. */
1756 uncache_image (f
, spec
)
1760 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1762 free_image (f
, img
);
1766 /* Free image cache of frame F. Be aware that X frames share images
1770 free_image_cache (f
)
1773 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1778 /* Cache should not be referenced by any frame when freed. */
1779 xassert (c
->refcount
== 0);
1781 for (i
= 0; i
< c
->used
; ++i
)
1782 free_image (f
, c
->images
[i
]);
1786 FRAME_IMAGE_CACHE (f
) = NULL
;
1791 /* Clear image cache of frame F. FILTER=t means free all images.
1792 FILTER=nil means clear only images that haven't been
1793 displayed for some time.
1794 Else, only free the images which have FILTER in their `dependencies'.
1795 Should be called from time to time to reduce the number of loaded images.
1796 If image-cache-eviction-delay is non-nil, this frees images in the cache
1797 which weren't displayed for at least that many seconds. */
1800 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1802 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1804 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1811 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1813 /* Block input so that we won't be interrupted by a SIGIO
1814 while being in an inconsistent state. */
1817 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1819 struct image
*img
= c
->images
[i
];
1821 && (NILP (filter
) ? img
->timestamp
< old
1823 || !NILP (Fmember (filter
, img
->dependencies
)))))
1825 free_image (f
, img
);
1830 /* We may be clearing the image cache because, for example,
1831 Emacs was iconified for a longer period of time. In that
1832 case, current matrices may still contain references to
1833 images freed above. So, clear these matrices. */
1836 Lisp_Object tail
, frame
;
1838 FOR_EACH_FRAME (tail
, frame
)
1840 struct frame
*f
= XFRAME (frame
);
1841 if (FRAME_IMAGE_CACHE (f
) == c
)
1842 clear_current_matrices (f
);
1845 ++windows_or_buffers_changed
;
1853 clear_image_caches (Lisp_Object filter
)
1855 /* FIXME: We want to do
1856 * struct terminal *t;
1857 * for (t = terminal_list; t; t = t->next_terminal)
1858 * clear_image_cache (t, filter); */
1859 Lisp_Object tail
, frame
;
1860 FOR_EACH_FRAME (tail
, frame
)
1861 if (FRAME_WINDOW_P (XFRAME (frame
)))
1862 clear_image_cache (XFRAME (frame
), filter
);
1865 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1867 doc
: /* Clear the image cache.
1868 FILTER nil or a frame means clear all images in the selected frame.
1869 FILTER t means clear the image caches of all frames.
1870 Anything else, means only clear those images which refer to FILTER,
1871 which is then usually a filename. */)
1875 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1876 clear_image_caches (filter
);
1878 clear_image_cache (check_x_frame (filter
), Qt
);
1884 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1886 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1887 If SPEC specifies an image file, the displayed image is updated with
1888 the current contents of that file.
1889 FRAME nil or omitted means use the selected frame.
1890 FRAME t means refresh the image on all frames. */)
1892 Lisp_Object spec
, frame
;
1894 if (!valid_image_p (spec
))
1895 error ("Invalid image specification");
1900 FOR_EACH_FRAME (tail
, frame
)
1902 struct frame
*f
= XFRAME (frame
);
1903 if (FRAME_WINDOW_P (f
))
1904 uncache_image (f
, spec
);
1908 uncache_image (check_x_frame (frame
), spec
);
1914 /* Compute masks and transform image IMG on frame F, as specified
1915 by the image's specification, */
1918 postprocess_image (f
, img
)
1922 /* Manipulation of the image's mask. */
1925 Lisp_Object conversion
, spec
;
1930 /* `:heuristic-mask t'
1932 means build a mask heuristically.
1933 `:heuristic-mask (R G B)'
1934 `:mask (heuristic (R G B))'
1935 means build a mask from color (R G B) in the
1938 means remove a mask, if any. */
1940 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1942 x_build_heuristic_mask (f
, img
, mask
);
1947 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1949 if (EQ (mask
, Qheuristic
))
1950 x_build_heuristic_mask (f
, img
, Qt
);
1951 else if (CONSP (mask
)
1952 && EQ (XCAR (mask
), Qheuristic
))
1954 if (CONSP (XCDR (mask
)))
1955 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1957 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1959 else if (NILP (mask
) && found_p
&& img
->mask
)
1961 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1962 img
->mask
= NO_PIXMAP
;
1967 /* Should we apply an image transformation algorithm? */
1968 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1969 if (EQ (conversion
, Qdisabled
))
1970 x_disable_image (f
, img
);
1971 else if (EQ (conversion
, Qlaplace
))
1973 else if (EQ (conversion
, Qemboss
))
1975 else if (CONSP (conversion
)
1976 && EQ (XCAR (conversion
), Qedge_detection
))
1979 tem
= XCDR (conversion
);
1981 x_edge_detection (f
, img
,
1982 Fplist_get (tem
, QCmatrix
),
1983 Fplist_get (tem
, QCcolor_adjustment
));
1989 /* Return the id of image with Lisp specification SPEC on frame F.
1990 SPEC must be a valid Lisp image specification (see valid_image_p). */
1993 lookup_image (f
, spec
)
1997 struct image_cache
*c
;
2000 struct gcpro gcpro1
;
2003 /* F must be a window-system frame, and SPEC must be a valid image
2005 xassert (FRAME_WINDOW_P (f
));
2006 xassert (valid_image_p (spec
));
2008 c
= FRAME_IMAGE_CACHE (f
);
2012 /* Look up SPEC in the hash table of the image cache. */
2013 hash
= sxhash (spec
, 0);
2014 img
= search_image_cache (f
, spec
, hash
);
2015 if (img
&& img
->load_failed_p
)
2017 free_image (f
, img
);
2021 /* If not found, create a new image and cache it. */
2024 extern Lisp_Object Qpostscript
;
2027 img
= make_image (spec
, hash
);
2028 cache_image (f
, img
);
2029 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2030 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2031 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2033 /* If we can't load the image, and we don't have a width and
2034 height, use some arbitrary width and height so that we can
2035 draw a rectangle for it. */
2036 if (img
->load_failed_p
)
2040 value
= image_spec_value (spec
, QCwidth
, NULL
);
2041 img
->width
= (INTEGERP (value
)
2042 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2043 value
= image_spec_value (spec
, QCheight
, NULL
);
2044 img
->height
= (INTEGERP (value
)
2045 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2049 /* Handle image type independent image attributes
2050 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2051 `:background COLOR'. */
2052 Lisp_Object ascent
, margin
, relief
, bg
;
2054 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2055 if (INTEGERP (ascent
))
2056 img
->ascent
= XFASTINT (ascent
);
2057 else if (EQ (ascent
, Qcenter
))
2058 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2060 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2061 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2062 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2063 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2064 && INTEGERP (XCDR (margin
)))
2066 if (XINT (XCAR (margin
)) > 0)
2067 img
->hmargin
= XFASTINT (XCAR (margin
));
2068 if (XINT (XCDR (margin
)) > 0)
2069 img
->vmargin
= XFASTINT (XCDR (margin
));
2072 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2073 if (INTEGERP (relief
))
2075 img
->relief
= XINT (relief
);
2076 img
->hmargin
+= eabs (img
->relief
);
2077 img
->vmargin
+= eabs (img
->relief
);
2080 if (! img
->background_valid
)
2082 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2086 = x_alloc_image_color (f
, img
, bg
,
2087 FRAME_BACKGROUND_PIXEL (f
));
2088 img
->background_valid
= 1;
2092 /* Do image transformations and compute masks, unless we
2093 don't have the image yet. */
2094 if (!EQ (*img
->type
->type
, Qpostscript
))
2095 postprocess_image (f
, img
);
2101 /* We're using IMG, so set its timestamp to `now'. */
2102 EMACS_GET_TIME (now
);
2103 img
->timestamp
= EMACS_SECS (now
);
2107 /* Value is the image id. */
2112 /* Cache image IMG in the image cache of frame F. */
2115 cache_image (f
, img
)
2119 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2122 /* Find a free slot in c->images. */
2123 for (i
= 0; i
< c
->used
; ++i
)
2124 if (c
->images
[i
] == NULL
)
2127 /* If no free slot found, maybe enlarge c->images. */
2128 if (i
== c
->used
&& c
->used
== c
->size
)
2131 c
->images
= (struct image
**) xrealloc (c
->images
,
2132 c
->size
* sizeof *c
->images
);
2135 /* Add IMG to c->images, and assign IMG an id. */
2141 /* Add IMG to the cache's hash table. */
2142 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2143 img
->next
= c
->buckets
[i
];
2145 img
->next
->prev
= img
;
2147 c
->buckets
[i
] = img
;
2151 /* Call FN on every image in the image cache of frame F. Used to mark
2152 Lisp Objects in the image cache. */
2154 /* Mark Lisp objects in image IMG. */
2160 mark_object (img
->spec
);
2161 mark_object (img
->dependencies
);
2163 if (!NILP (img
->data
.lisp_val
))
2164 mark_object (img
->data
.lisp_val
);
2169 mark_image_cache (struct image_cache
*c
)
2174 for (i
= 0; i
< c
->used
; ++i
)
2176 mark_image (c
->images
[i
]);
2182 /***********************************************************************
2183 X / MAC / W32 support code
2184 ***********************************************************************/
2188 /* Macro for defining functions that will be loaded from image DLLs. */
2189 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2191 /* Macro for loading those image functions from the library. */
2192 #define LOAD_IMGLIB_FN(lib,func) { \
2193 fn_##func = (void *) GetProcAddress (lib, #func); \
2194 if (!fn_##func) return 0; \
2197 /* Load a DLL implementing an image type.
2198 The `image-library-alist' variable associates a symbol,
2199 identifying an image type, to a list of possible filenames.
2200 The function returns NULL if no library could be loaded for
2201 the given image type, or if the library was previously loaded;
2202 else the handle of the DLL. */
2204 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2206 HMODULE library
= NULL
;
2208 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2210 Lisp_Object dlls
= Fassq (type
, libraries
);
2213 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2215 CHECK_STRING_CAR (dlls
);
2216 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2224 #endif /* HAVE_NTGUI */
2226 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2227 XImagePtr
*, Pixmap
*));
2228 static void x_destroy_x_image
P_ ((XImagePtr
));
2229 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2232 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2233 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2234 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2235 via xmalloc. Print error messages via image_error if an error
2236 occurs. Value is non-zero if successful.
2238 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2239 should indicate the bit depth of the image. */
2242 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2244 int width
, height
, depth
;
2248 #ifdef HAVE_X_WINDOWS
2249 Display
*display
= FRAME_X_DISPLAY (f
);
2250 Window window
= FRAME_X_WINDOW (f
);
2251 Screen
*screen
= FRAME_X_SCREEN (f
);
2253 xassert (interrupt_input_blocked
);
2256 depth
= DefaultDepthOfScreen (screen
);
2257 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2258 depth
, ZPixmap
, 0, NULL
, width
, height
,
2259 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2262 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2266 /* Allocate image raster. */
2267 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2269 /* Allocate a pixmap of the same size. */
2270 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2271 if (*pixmap
== NO_PIXMAP
)
2273 x_destroy_x_image (*ximg
);
2275 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2280 #endif /* HAVE_X_WINDOWS */
2284 BITMAPINFOHEADER
*header
;
2286 int scanline_width_bits
;
2288 int palette_colors
= 0;
2293 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2294 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2296 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2300 scanline_width_bits
= width
* depth
;
2301 remainder
= scanline_width_bits
% 32;
2304 scanline_width_bits
+= 32 - remainder
;
2306 /* Bitmaps with a depth less than 16 need a palette. */
2307 /* BITMAPINFO structure already contains the first RGBQUAD. */
2309 palette_colors
= 1 << depth
- 1;
2311 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2314 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2318 header
= &((*ximg
)->info
.bmiHeader
);
2319 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2320 header
->biSize
= sizeof (*header
);
2321 header
->biWidth
= width
;
2322 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2323 header
->biPlanes
= 1;
2324 header
->biBitCount
= depth
;
2325 header
->biCompression
= BI_RGB
;
2326 header
->biClrUsed
= palette_colors
;
2328 /* TODO: fill in palette. */
2331 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2332 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2333 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2334 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2335 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2336 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2337 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2338 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2341 hdc
= get_frame_dc (f
);
2343 /* Create a DIBSection and raster array for the bitmap,
2344 and store its handle in *pixmap. */
2345 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2346 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2347 /* casting avoids a GCC warning */
2348 (void **)&((*ximg
)->data
), NULL
, 0);
2350 /* Realize display palette and garbage all frames. */
2351 release_frame_dc (f
, hdc
);
2353 if (*pixmap
== NULL
)
2355 DWORD err
= GetLastError ();
2356 Lisp_Object errcode
;
2357 /* All system errors are < 10000, so the following is safe. */
2358 XSETINT (errcode
, (int) err
);
2359 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2360 x_destroy_x_image (*ximg
);
2366 #endif /* HAVE_NTGUI */
2369 Display
*display
= FRAME_X_DISPLAY (f
);
2370 Window window
= FRAME_X_WINDOW (f
);
2372 xassert (interrupt_input_blocked
);
2374 /* Allocate a pixmap of the same size. */
2375 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2376 if (*pixmap
== NO_PIXMAP
)
2379 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2383 #if !USE_MAC_IMAGE_IO
2384 LockPixels (GetGWorldPixMap (*pixmap
));
2393 /* Destroy XImage XIMG. Free XIMG->data. */
2396 x_destroy_x_image (ximg
)
2399 xassert (interrupt_input_blocked
);
2402 #ifdef HAVE_X_WINDOWS
2405 XDestroyImage (ximg
);
2406 #endif /* HAVE_X_WINDOWS */
2408 /* Data will be freed by DestroyObject. */
2411 #endif /* HAVE_NTGUI */
2413 XDestroyImage (ximg
);
2419 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2420 are width and height of both the image and pixmap. */
2423 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2429 #ifdef HAVE_X_WINDOWS
2432 xassert (interrupt_input_blocked
);
2433 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2434 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2435 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2436 #endif /* HAVE_X_WINDOWS */
2439 #if 0 /* I don't think this is necessary looking at where it is used. */
2440 HDC hdc
= get_frame_dc (f
);
2441 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2442 release_frame_dc (f
, hdc
);
2444 #endif /* HAVE_NTGUI */
2447 xassert (ximg
== pixmap
);
2452 /***********************************************************************
2454 ***********************************************************************/
2456 static unsigned char *slurp_file
P_ ((char *, int *));
2459 /* Find image file FILE. Look in data-directory/images, then
2460 x-bitmap-file-path. Value is the encoded full name of the file
2461 found, or nil if not found. */
2464 x_find_image_file (file
)
2467 Lisp_Object file_found
, search_path
;
2468 struct gcpro gcpro1
, gcpro2
;
2472 /* TODO I think this should use something like image-load-path
2473 instead. Unfortunately, that can contain non-string elements. */
2474 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2476 Vx_bitmap_file_path
);
2477 GCPRO2 (file_found
, search_path
);
2479 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2480 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2486 file_found
= ENCODE_FILE (file_found
);
2495 /* Read FILE into memory. Value is a pointer to a buffer allocated
2496 with xmalloc holding FILE's contents. Value is null if an error
2497 occurred. *SIZE is set to the size of the file. */
2499 static unsigned char *
2500 slurp_file (file
, size
)
2505 unsigned char *buf
= NULL
;
2508 if (stat (file
, &st
) == 0
2509 && (fp
= fopen (file
, "rb")) != NULL
2510 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2511 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2534 /***********************************************************************
2535 MAC Image Load Functions
2536 ***********************************************************************/
2538 #if USE_MAC_IMAGE_IO
2540 image_load_image_io (f
, img
, type
)
2545 CFDictionaryRef options
, src_props
= NULL
, props
= NULL
;
2546 CFStringRef keys
[2];
2547 CFTypeRef values
[2];
2548 Lisp_Object specified_file
, specified_data
;
2549 CGImageSourceRef source
= NULL
;
2551 CGImageRef image
= NULL
;
2552 int loop_count
= -1;
2553 double delay_time
= -1.0;
2555 XImagePtr ximg
= NULL
;
2556 CGContextRef context
;
2558 int has_alpha_p
, gif_p
;
2560 gif_p
= UTTypeEqual (type
, kUTTypeGIF
);
2562 keys
[0] = kCGImageSourceTypeIdentifierHint
;
2563 values
[0] = (CFTypeRef
) type
;
2564 keys
[1] = kCGImageSourceShouldCache
;
2565 values
[1] = (CFTypeRef
) kCFBooleanFalse
;
2566 options
= CFDictionaryCreate (NULL
, (const void **) keys
,
2567 (const void **) values
,
2568 sizeof (keys
) / sizeof (keys
[0]),
2569 &kCFTypeDictionaryKeyCallBacks
,
2570 &kCFTypeDictionaryValueCallBacks
);
2571 if (options
== NULL
)
2573 image_error ("Error creating options for image `%s'", img
->spec
, Qnil
);
2577 /* Open the file. */
2578 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2579 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2581 if (NILP (specified_data
))
2587 file
= x_find_image_file (specified_file
);
2588 if (!STRINGP (file
))
2590 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2593 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2596 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2597 kCFURLPOSIXPathStyle
, 0);
2601 source
= CGImageSourceCreateWithURL (url
, NULL
);
2608 CFDataRef data
= CFDataCreate (NULL
, SDATA (specified_data
),
2609 SBYTES (specified_data
));
2613 source
= CGImageSourceCreateWithData (data
, options
);
2617 CFRelease (options
);
2621 CFStringRef real_type
= CGImageSourceGetType (source
);
2623 if (real_type
&& UTTypeEqual (type
, real_type
))
2624 src_props
= CGImageSourceCopyProperties (source
, NULL
);
2629 count
= CGImageSourceGetCount (source
);
2632 Lisp_Object image
= image_spec_value (img
->spec
, QCindex
, NULL
);
2634 if (INTEGERP (image
))
2635 ino
= XFASTINT (image
);
2637 if (ino
>= 0 && ino
< count
)
2639 props
= CGImageSourceCopyPropertiesAtIndex (source
, ino
, NULL
);
2641 image
= CGImageSourceCreateImageAtIndex (source
, ino
, NULL
);
2650 CFRelease (src_props
);
2653 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2658 CFBooleanRef boolean
;
2660 if (CFDictionaryGetValueIfPresent (props
, kCGImagePropertyHasAlpha
,
2661 (const void **) &boolean
))
2662 has_alpha_p
= CFBooleanGetValue (boolean
);
2665 CFDictionaryRef dict
;
2668 dict
= CFDictionaryGetValue (src_props
,
2669 kCGImagePropertyGIFDictionary
);
2671 && CFDictionaryGetValueIfPresent (dict
,
2672 kCGImagePropertyGIFLoopCount
,
2673 (const void **) &number
))
2674 CFNumberGetValue (number
, kCFNumberIntType
, &loop_count
);
2676 dict
= CFDictionaryGetValue (props
, kCGImagePropertyGIFDictionary
);
2678 && CFDictionaryGetValueIfPresent (dict
,
2679 kCGImagePropertyGIFDelayTime
,
2680 (const void **) &number
))
2681 CFNumberGetValue (number
, kCFNumberDoubleType
, &delay_time
);
2683 CFRelease (src_props
);
2687 width
= img
->width
= CGImageGetWidth (image
);
2688 height
= img
->height
= CGImageGetHeight (image
);
2690 if (!check_image_size (f
, width
, height
))
2692 CGImageRelease (image
);
2693 image_error ("Invalid image size", Qnil
, Qnil
);
2697 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2699 CGImageRelease (image
);
2700 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
2703 rectangle
= CGRectMake (0, 0, width
, height
);
2705 context
= CGBitmapContextCreate (ximg
->data
, ximg
->width
, ximg
->height
, 8,
2706 ximg
->bytes_per_line
,
2707 mac_cg_color_space_rgb
,
2708 kCGImageAlphaNoneSkipFirst
2709 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
2710 | kCGBitmapByteOrder32Host
2715 Lisp_Object specified_bg
;
2718 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2719 if (!STRINGP (specified_bg
)
2720 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2722 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2723 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2724 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2725 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2727 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2728 color
.green
/ 65535.0,
2729 color
.blue
/ 65535.0, 1.0);
2730 CGContextFillRect (context
, rectangle
);
2732 CGContextDrawImage (context
, rectangle
, image
);
2733 CGContextRelease (context
);
2734 CGImageRelease (image
);
2736 /* Save GIF image extension data for `image-extension-data'.
2737 Format is (count IMAGES
2738 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2739 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2742 img
->data
.lisp_val
= Qnil
;
2743 if (delay_time
>= 0)
2745 Lisp_Object gce
= make_uninit_string (4);
2746 int centisec
= delay_time
* 100.0 + 0.5;
2748 /* Fill the delay time field. */
2749 SSET (gce
, 1, centisec
& 0xff);
2750 SSET (gce
, 2, (centisec
>> 8) & 0xff);
2751 /* We don't know about other fields. */
2754 img
->data
.lisp_val
= Fcons (make_number (0xf9),
2756 img
->data
.lisp_val
));
2758 if (loop_count
>= 0)
2760 Lisp_Object data_sub_block
= make_uninit_string (3);
2762 SSET (data_sub_block
, 0, 0x01);
2763 SSET (data_sub_block
, 1, loop_count
& 0xff);
2764 SSET (data_sub_block
, 2, (loop_count
>> 8) & 0xff);
2765 img
->data
.lisp_val
= Fcons (make_number (0),
2766 Fcons (data_sub_block
,
2767 img
->data
.lisp_val
));
2768 img
->data
.lisp_val
= Fcons (make_number (0xff),
2769 Fcons (build_string ("NETSCAPE2.0"),
2770 img
->data
.lisp_val
));
2773 img
->data
.lisp_val
= Fcons (Qcount
,
2774 Fcons (make_number (count
),
2775 img
->data
.lisp_val
));
2778 /* Maybe fill in the background field while we have ximg handy. */
2779 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2780 IMAGE_BACKGROUND (img
, f
, ximg
);
2782 /* Put the image into the pixmap. */
2783 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2784 x_destroy_x_image (ximg
);
2787 #else /* !USE_MAC_IMAGE_IO */
2788 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2791 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2795 find_image_fsspec (specified_file
, file
, fss
)
2796 Lisp_Object specified_file
, *file
;
2802 *file
= x_find_image_file (specified_file
);
2803 if (!STRINGP (*file
))
2804 return fnfErr
; /* file or directory not found;
2805 incomplete pathname */
2806 /* Try to open the image file. */
2807 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2808 SBYTES (*file
), typeFSS
, &desc
);
2811 #if TARGET_API_MAC_CARBON
2812 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2814 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2816 AEDisposeDesc (&desc
);
2822 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2829 ComponentResult err
;
2830 GraphicsImportComponent gi
;
2833 ImageDescriptionHandle desc_handle
;
2834 short draw_all_pixels
;
2835 Lisp_Object specified_bg
;
2840 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2843 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2848 /* read from file system spec */
2849 err
= GraphicsImportSetDataFile (gi
, fss
);
2852 image_error ("Cannot set fsspec to graphics importer for '%s'",
2859 /* read from data handle */
2860 err
= GraphicsImportSetDataHandle (gi
, dh
);
2863 image_error ("Cannot set data handle to graphics importer for `%s'",
2868 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2869 if (err
!= noErr
|| desc_handle
== NULL
)
2871 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2874 width
= img
->width
= (*desc_handle
)->width
;
2875 height
= img
->height
= (*desc_handle
)->height
;
2876 DisposeHandle ((Handle
)desc_handle
);
2878 if (!check_image_size (f
, width
, height
))
2880 image_error ("Invalid image size", Qnil
, Qnil
);
2884 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2886 /* Don't check the error code here. It may have an undocumented
2890 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2894 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2896 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2897 if (!STRINGP (specified_bg
) ||
2898 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2900 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2901 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2902 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2903 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2907 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2909 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2914 GetGWorld (&old_port
, &old_gdh
);
2915 SetGWorld (ximg
, NULL
);
2916 bg_color
.red
= color
.red
;
2917 bg_color
.green
= color
.green
;
2918 bg_color
.blue
= color
.blue
;
2919 RGBBackColor (&bg_color
);
2920 #if TARGET_API_MAC_CARBON
2921 GetPortBounds (ximg
, &rect
);
2924 EraseRect (&(ximg
->portRect
));
2926 SetGWorld (old_port
, old_gdh
);
2928 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2929 GraphicsImportDraw (gi
);
2930 CloseComponent (gi
);
2932 /* Maybe fill in the background field while we have ximg handy. */
2933 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2934 IMAGE_BACKGROUND (img
, f
, ximg
);
2936 /* Put the image into the pixmap. */
2937 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2938 x_destroy_x_image (ximg
);
2942 CloseComponent (gi
);
2947 /* Load an image using the QuickTime Graphics Importer.
2948 Note: The alpha channel does not work for PNG images. */
2950 image_load_quicktime (f
, img
, type
)
2955 Lisp_Object specified_file
;
2956 Lisp_Object specified_data
;
2959 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2960 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2962 if (NILP (specified_data
))
2964 /* Read from a file */
2968 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2972 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2974 image_error ("Cannot open `%s'", file
, Qnil
);
2977 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2981 /* Memory source! */
2985 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2988 image_error ("Cannot allocate data handle for `%s'",
2992 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
3001 image_load_quartz2d (f
, img
, png_p
)
3006 Lisp_Object file
, specified_file
;
3007 Lisp_Object specified_data
, specified_bg
;
3008 struct gcpro gcpro1
;
3009 CGDataProviderRef source
;
3013 XImagePtr ximg
= NULL
;
3014 CGContextRef context
;
3017 /* Open the file. */
3018 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3019 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3024 if (NILP (specified_data
))
3029 file
= x_find_image_file (specified_file
);
3030 if (!STRINGP (file
))
3032 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3036 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
3037 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
3038 kCFURLPOSIXPathStyle
, 0);
3040 source
= CGDataProviderCreateWithURL (url
);
3044 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
3045 SBYTES (specified_data
), NULL
);
3047 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3049 image
= CGImageCreateWithPNGDataProvider (source
, NULL
, false,
3050 kCGRenderingIntentDefault
);
3053 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, false,
3054 kCGRenderingIntentDefault
);
3056 CGDataProviderRelease (source
);
3060 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
3063 width
= img
->width
= CGImageGetWidth (image
);
3064 height
= img
->height
= CGImageGetHeight (image
);
3066 if (!check_image_size (f
, width
, height
))
3068 CGImageRelease (image
);
3070 image_error ("Invalid image size", Qnil
, Qnil
);
3076 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3077 if (!STRINGP (specified_bg
) ||
3078 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
3080 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
3081 color
.red
= RED16_FROM_ULONG (color
.pixel
);
3082 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
3083 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
3087 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
3089 CGImageRelease (image
);
3093 rectangle
= CGRectMake (0, 0, width
, height
);
3094 QDBeginCGContext (ximg
, &context
);
3097 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
3098 color
.green
/ 65535.0,
3099 color
.blue
/ 65535.0, 1.0);
3100 CGContextFillRect (context
, rectangle
);
3102 CGContextDrawImage (context
, rectangle
, image
);
3103 QDEndCGContext (ximg
, &context
);
3104 CGImageRelease (image
);
3106 /* Maybe fill in the background field while we have ximg handy. */
3107 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
3108 IMAGE_BACKGROUND (img
, f
, ximg
);
3110 /* Put the image into the pixmap. */
3111 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
3112 x_destroy_x_image (ximg
);
3117 #endif /* !USE_MAC_IMAGE_IO */
3122 /***********************************************************************
3124 ***********************************************************************/
3126 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
3127 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
3128 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
3129 unsigned char *, unsigned char *));
3130 static int xbm_image_p
P_ ((Lisp_Object object
));
3131 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
3132 unsigned char *, unsigned char *,
3133 int *, int *, unsigned char **));
3134 static int xbm_file_p
P_ ((Lisp_Object
));
3137 /* Indices of image specification fields in xbm_format, below. */
3139 enum xbm_keyword_index
3157 /* Vector of image_keyword structures describing the format
3158 of valid XBM image specifications. */
3160 static struct image_keyword xbm_format
[XBM_LAST
] =
3162 {":type", IMAGE_SYMBOL_VALUE
, 1},
3163 {":file", IMAGE_STRING_VALUE
, 0},
3164 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3165 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3166 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3167 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
3168 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
3169 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3170 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3171 {":relief", IMAGE_INTEGER_VALUE
, 0},
3172 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3173 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3174 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
3177 /* Structure describing the image type XBM. */
3179 static struct image_type xbm_type
=
3188 /* Tokens returned from xbm_scan. */
3197 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3198 A valid specification is a list starting with the symbol `image'
3199 The rest of the list is a property list which must contain an
3202 If the specification specifies a file to load, it must contain
3203 an entry `:file FILENAME' where FILENAME is a string.
3205 If the specification is for a bitmap loaded from memory it must
3206 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3207 WIDTH and HEIGHT are integers > 0. DATA may be:
3209 1. a string large enough to hold the bitmap data, i.e. it must
3210 have a size >= (WIDTH + 7) / 8 * HEIGHT
3212 2. a bool-vector of size >= WIDTH * HEIGHT
3214 3. a vector of strings or bool-vectors, one for each line of the
3217 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3218 may not be specified in this case because they are defined in the
3221 Both the file and data forms may contain the additional entries
3222 `:background COLOR' and `:foreground COLOR'. If not present,
3223 foreground and background of the frame on which the image is
3224 displayed is used. */
3227 xbm_image_p (object
)
3230 struct image_keyword kw
[XBM_LAST
];
3232 bcopy (xbm_format
, kw
, sizeof kw
);
3233 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
3236 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
3238 if (kw
[XBM_FILE
].count
)
3240 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
3243 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
3245 /* In-memory XBM file. */
3246 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
3254 /* Entries for `:width', `:height' and `:data' must be present. */
3255 if (!kw
[XBM_WIDTH
].count
3256 || !kw
[XBM_HEIGHT
].count
3257 || !kw
[XBM_DATA
].count
)
3260 data
= kw
[XBM_DATA
].value
;
3261 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
3262 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
3264 /* Check type of data, and width and height against contents of
3270 /* Number of elements of the vector must be >= height. */
3271 if (XVECTOR (data
)->size
< height
)
3274 /* Each string or bool-vector in data must be large enough
3275 for one line of the image. */
3276 for (i
= 0; i
< height
; ++i
)
3278 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
3283 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
3286 else if (BOOL_VECTOR_P (elt
))
3288 if (XBOOL_VECTOR (elt
)->size
< width
)
3295 else if (STRINGP (data
))
3298 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
3301 else if (BOOL_VECTOR_P (data
))
3303 if (XBOOL_VECTOR (data
)->size
< width
* height
)
3314 /* Scan a bitmap file. FP is the stream to read from. Value is
3315 either an enumerator from enum xbm_token, or a character for a
3316 single-character token, or 0 at end of file. If scanning an
3317 identifier, store the lexeme of the identifier in SVAL. If
3318 scanning a number, store its value in *IVAL. */
3321 xbm_scan (s
, end
, sval
, ival
)
3322 unsigned char **s
, *end
;
3330 /* Skip white space. */
3331 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3336 else if (isdigit (c
))
3338 int value
= 0, digit
;
3340 if (c
== '0' && *s
< end
)
3343 if (c
== 'x' || c
== 'X')
3350 else if (c
>= 'a' && c
<= 'f')
3351 digit
= c
- 'a' + 10;
3352 else if (c
>= 'A' && c
<= 'F')
3353 digit
= c
- 'A' + 10;
3356 value
= 16 * value
+ digit
;
3359 else if (isdigit (c
))
3363 && (c
= *(*s
)++, isdigit (c
)))
3364 value
= 8 * value
+ c
- '0';
3371 && (c
= *(*s
)++, isdigit (c
)))
3372 value
= 10 * value
+ c
- '0';
3380 else if (isalpha (c
) || c
== '_')
3384 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3391 else if (c
== '/' && **s
== '*')
3393 /* C-style comment. */
3395 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3409 /* Create a Windows bitmap from X bitmap data. */
3411 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3413 static unsigned char swap_nibble
[16]
3414 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3415 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3416 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3417 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3419 unsigned char *bits
, *p
;
3422 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3423 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3424 bits
= (unsigned char *) alloca (height
* w2
);
3425 bzero (bits
, height
* w2
);
3426 for (i
= 0; i
< height
; i
++)
3429 for (j
= 0; j
< w1
; j
++)
3431 /* Bitswap XBM bytes to match how Windows does things. */
3432 unsigned char c
= *data
++;
3433 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3434 | (swap_nibble
[(c
>>4) & 0xf]));
3437 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3443 convert_mono_to_color_image (f
, img
, foreground
, background
)
3446 COLORREF foreground
, background
;
3448 HDC hdc
, old_img_dc
, new_img_dc
;
3449 HGDIOBJ old_prev
, new_prev
;
3452 hdc
= get_frame_dc (f
);
3453 old_img_dc
= CreateCompatibleDC (hdc
);
3454 new_img_dc
= CreateCompatibleDC (hdc
);
3455 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3456 release_frame_dc (f
, hdc
);
3457 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3458 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3459 /* Windows convention for mono bitmaps is black = background,
3460 white = foreground. */
3461 SetTextColor (new_img_dc
, background
);
3462 SetBkColor (new_img_dc
, foreground
);
3464 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3467 SelectObject (old_img_dc
, old_prev
);
3468 SelectObject (new_img_dc
, new_prev
);
3469 DeleteDC (old_img_dc
);
3470 DeleteDC (new_img_dc
);
3471 DeleteObject (img
->pixmap
);
3472 if (new_pixmap
== 0)
3473 fprintf (stderr
, "Failed to convert image to color.\n");
3475 img
->pixmap
= new_pixmap
;
3478 #define XBM_BIT_SHUFFLE(b) (~(b))
3482 #define XBM_BIT_SHUFFLE(b) (b)
3484 #endif /* HAVE_NTGUI */
3488 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
3492 RGB_PIXEL_COLOR fg
, bg
;
3493 int non_default_colors
;
3497 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3499 /* If colors were specified, transfer the bitmap to a color one. */
3500 if (non_default_colors
)
3501 convert_mono_to_color_image (f
, img
, fg
, bg
);
3504 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3507 img
->width
, img
->height
,
3509 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3510 #endif /* HAVE_NTGUI */
3515 /* Replacement for XReadBitmapFileData which isn't available under old
3516 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3517 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3518 the image. Return in *DATA the bitmap data allocated with xmalloc.
3519 Value is non-zero if successful. DATA null means just test if
3520 CONTENTS looks like an in-memory XBM file. */
3523 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3525 unsigned char *contents
, *end
;
3526 int *width
, *height
;
3527 unsigned char **data
;
3529 unsigned char *s
= contents
;
3530 char buffer
[BUFSIZ
];
3533 int bytes_per_line
, i
, nbytes
;
3539 LA1 = xbm_scan (&s, end, buffer, &value)
3541 #define expect(TOKEN) \
3542 if (LA1 != (TOKEN)) \
3547 #define expect_ident(IDENT) \
3548 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3553 *width
= *height
= -1;
3556 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3558 /* Parse defines for width, height and hot-spots. */
3562 expect_ident ("define");
3563 expect (XBM_TK_IDENT
);
3565 if (LA1
== XBM_TK_NUMBER
)
3567 char *p
= strrchr (buffer
, '_');
3568 p
= p
? p
+ 1 : buffer
;
3569 if (strcmp (p
, "width") == 0)
3571 else if (strcmp (p
, "height") == 0)
3574 expect (XBM_TK_NUMBER
);
3577 if (!check_image_size (f
, *width
, *height
))
3579 else if (data
== NULL
)
3582 /* Parse bits. Must start with `static'. */
3583 expect_ident ("static");
3584 if (LA1
== XBM_TK_IDENT
)
3586 if (strcmp (buffer
, "unsigned") == 0)
3589 expect_ident ("char");
3591 else if (strcmp (buffer
, "short") == 0)
3595 if (*width
% 16 && *width
% 16 < 9)
3598 else if (strcmp (buffer
, "char") == 0)
3606 expect (XBM_TK_IDENT
);
3612 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3613 nbytes
= bytes_per_line
* *height
;
3614 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3618 for (i
= 0; i
< nbytes
; i
+= 2)
3621 expect (XBM_TK_NUMBER
);
3623 *p
++ = XBM_BIT_SHUFFLE (val
);
3624 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3625 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3627 if (LA1
== ',' || LA1
== '}')
3635 for (i
= 0; i
< nbytes
; ++i
)
3638 expect (XBM_TK_NUMBER
);
3640 *p
++ = XBM_BIT_SHUFFLE (val
);
3642 if (LA1
== ',' || LA1
== '}')
3667 /* Load XBM image IMG which will be displayed on frame F from buffer
3668 CONTENTS. END is the end of the buffer. Value is non-zero if
3672 xbm_load_image (f
, img
, contents
, end
)
3675 unsigned char *contents
, *end
;
3678 unsigned char *data
;
3681 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3684 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3685 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3686 int non_default_colors
= 0;
3689 xassert (img
->width
> 0 && img
->height
> 0);
3691 /* Get foreground and background colors, maybe allocate colors. */
3692 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3695 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3696 non_default_colors
= 1;
3698 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3701 background
= x_alloc_image_color (f
, img
, value
, background
);
3702 img
->background
= background
;
3703 img
->background_valid
= 1;
3704 non_default_colors
= 1;
3707 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3708 foreground
, background
,
3709 non_default_colors
);
3712 if (img
->pixmap
== NO_PIXMAP
)
3714 x_clear_image (f
, img
);
3715 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3721 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3727 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3734 return (STRINGP (data
)
3735 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3742 /* Fill image IMG which is used on frame F with pixmap data. Value is
3743 non-zero if successful. */
3751 Lisp_Object file_name
;
3753 xassert (xbm_image_p (img
->spec
));
3755 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3756 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3757 if (STRINGP (file_name
))
3760 unsigned char *contents
;
3762 struct gcpro gcpro1
;
3764 file
= x_find_image_file (file_name
);
3766 if (!STRINGP (file
))
3768 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3773 contents
= slurp_file (SDATA (file
), &size
);
3774 if (contents
== NULL
)
3776 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3781 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3786 struct image_keyword fmt
[XBM_LAST
];
3788 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3789 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3790 int non_default_colors
= 0;
3793 int in_memory_file_p
= 0;
3795 /* See if data looks like an in-memory XBM file. */
3796 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3797 in_memory_file_p
= xbm_file_p (data
);
3799 /* Parse the image specification. */
3800 bcopy (xbm_format
, fmt
, sizeof fmt
);
3801 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3804 /* Get specified width, and height. */
3805 if (!in_memory_file_p
)
3807 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3808 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3809 xassert (img
->width
> 0 && img
->height
> 0);
3812 /* Get foreground and background colors, maybe allocate colors. */
3813 if (fmt
[XBM_FOREGROUND
].count
3814 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3816 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3818 non_default_colors
= 1;
3821 if (fmt
[XBM_BACKGROUND
].count
3822 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3824 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3826 non_default_colors
= 1;
3829 if (in_memory_file_p
)
3830 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3839 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3841 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3842 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3844 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3846 bcopy (SDATA (line
), p
, nbytes
);
3848 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3851 else if (STRINGP (data
))
3852 bits
= SDATA (data
);
3854 bits
= XBOOL_VECTOR (data
)->data
;
3860 /* Windows mono bitmaps are reversed compared with X. */
3861 invertedBits
= bits
;
3862 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3864 bits
= (char *) alloca(nbytes
);
3865 for (i
= 0; i
< nbytes
; i
++)
3866 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3869 /* Create the pixmap. */
3871 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3872 foreground
, background
,
3873 non_default_colors
);
3878 image_error ("Unable to create pixmap for XBM image `%s'",
3880 x_clear_image (f
, img
);
3890 /***********************************************************************
3892 ***********************************************************************/
3894 #if defined (HAVE_XPM) || defined (MAC_OS)
3896 static int xpm_image_p
P_ ((Lisp_Object object
));
3897 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3898 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3900 #endif /* HAVE_XPM || MAC_OS */
3904 /* Indicate to xpm.h that we don't have Xlib. */
3906 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3907 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3908 #define XColor xpm_XColor
3909 #define XImage xpm_XImage
3910 #define Display xpm_Display
3911 #define PIXEL_ALREADY_TYPEDEFED
3912 #include "X11/xpm.h"
3917 #undef PIXEL_ALREADY_TYPEDEFED
3919 #include "X11/xpm.h"
3920 #endif /* HAVE_NTGUI */
3921 #endif /* HAVE_XPM */
3923 #if defined (HAVE_XPM) || defined (MAC_OS)
3924 /* The symbol `xpm' identifying XPM-format images. */
3928 /* Indices of image specification fields in xpm_format, below. */
3930 enum xpm_keyword_index
3946 /* Vector of image_keyword structures describing the format
3947 of valid XPM image specifications. */
3949 static struct image_keyword xpm_format
[XPM_LAST
] =
3951 {":type", IMAGE_SYMBOL_VALUE
, 1},
3952 {":file", IMAGE_STRING_VALUE
, 0},
3953 {":data", IMAGE_STRING_VALUE
, 0},
3954 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3955 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3956 {":relief", IMAGE_INTEGER_VALUE
, 0},
3957 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3958 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3959 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3960 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3961 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3964 /* Structure describing the image type XPM. */
3966 static struct image_type xpm_type
=
3975 #ifdef HAVE_X_WINDOWS
3977 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3978 functions for allocating image colors. Our own functions handle
3979 color allocation failures more gracefully than the ones on the XPM
3982 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3983 #define ALLOC_XPM_COLORS
3985 #endif /* HAVE_X_WINDOWS */
3987 #ifdef ALLOC_XPM_COLORS
3989 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3990 static void xpm_free_color_cache
P_ ((void));
3991 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3992 static int xpm_color_bucket
P_ ((char *));
3993 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3996 /* An entry in a hash table used to cache color definitions of named
3997 colors. This cache is necessary to speed up XPM image loading in
3998 case we do color allocations ourselves. Without it, we would need
3999 a call to XParseColor per pixel in the image. */
4001 struct xpm_cached_color
4003 /* Next in collision chain. */
4004 struct xpm_cached_color
*next
;
4006 /* Color definition (RGB and pixel color). */
4013 /* The hash table used for the color cache, and its bucket vector
4016 #define XPM_COLOR_CACHE_BUCKETS 1001
4017 struct xpm_cached_color
**xpm_color_cache
;
4019 /* Initialize the color cache. */
4022 xpm_init_color_cache (f
, attrs
)
4024 XpmAttributes
*attrs
;
4026 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
4027 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
4028 memset (xpm_color_cache
, 0, nbytes
);
4029 init_color_table ();
4031 if (attrs
->valuemask
& XpmColorSymbols
)
4036 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
4037 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4038 attrs
->colorsymbols
[i
].value
, &color
))
4040 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
4042 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
4047 /* Free the color cache. */
4050 xpm_free_color_cache ()
4052 struct xpm_cached_color
*p
, *next
;
4055 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
4056 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
4062 xfree (xpm_color_cache
);
4063 xpm_color_cache
= NULL
;
4064 free_color_table ();
4067 /* Return the bucket index for color named COLOR_NAME in the color
4071 xpm_color_bucket (color_name
)
4077 for (s
= color_name
; *s
; ++s
)
4079 return h
%= XPM_COLOR_CACHE_BUCKETS
;
4083 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4084 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4087 static struct xpm_cached_color
*
4088 xpm_cache_color (f
, color_name
, color
, bucket
)
4095 struct xpm_cached_color
*p
;
4098 bucket
= xpm_color_bucket (color_name
);
4100 nbytes
= sizeof *p
+ strlen (color_name
);
4101 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
4102 strcpy (p
->name
, color_name
);
4104 p
->next
= xpm_color_cache
[bucket
];
4105 xpm_color_cache
[bucket
] = p
;
4109 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4110 return the cached definition in *COLOR. Otherwise, make a new
4111 entry in the cache and allocate the color. Value is zero if color
4112 allocation failed. */
4115 xpm_lookup_color (f
, color_name
, color
)
4120 struct xpm_cached_color
*p
;
4121 int h
= xpm_color_bucket (color_name
);
4123 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
4124 if (strcmp (p
->name
, color_name
) == 0)
4129 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4132 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
4134 p
= xpm_cache_color (f
, color_name
, color
, h
);
4136 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4137 with transparency, and it's useful. */
4138 else if (strcmp ("opaque", color_name
) == 0)
4140 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
4141 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
4142 p
= xpm_cache_color (f
, color_name
, color
, h
);
4149 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4150 CLOSURE is a pointer to the frame on which we allocate the
4151 color. Return in *COLOR the allocated color. Value is non-zero
4155 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
4162 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
4166 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4167 is a pointer to the frame on which we allocate the color. Value is
4168 non-zero if successful. */
4171 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
4181 #endif /* ALLOC_XPM_COLORS */
4186 /* XPM library details. */
4188 DEF_IMGLIB_FN (XpmFreeAttributes
);
4189 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
4190 DEF_IMGLIB_FN (XpmReadFileToImage
);
4191 DEF_IMGLIB_FN (XImageFree
);
4194 init_xpm_functions (Lisp_Object libraries
)
4198 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
4201 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
4202 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
4203 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
4204 LOAD_IMGLIB_FN (library
, XImageFree
);
4208 #endif /* HAVE_NTGUI */
4211 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4212 for XPM images. Such a list must consist of conses whose car and
4216 xpm_valid_color_symbols_p (color_symbols
)
4217 Lisp_Object color_symbols
;
4219 while (CONSP (color_symbols
))
4221 Lisp_Object sym
= XCAR (color_symbols
);
4223 || !STRINGP (XCAR (sym
))
4224 || !STRINGP (XCDR (sym
)))
4226 color_symbols
= XCDR (color_symbols
);
4229 return NILP (color_symbols
);
4233 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4236 xpm_image_p (object
)
4239 struct image_keyword fmt
[XPM_LAST
];
4240 bcopy (xpm_format
, fmt
, sizeof fmt
);
4241 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
4242 /* Either `:file' or `:data' must be present. */
4243 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
4244 /* Either no `:color-symbols' or it's a list of conses
4245 whose car and cdr are strings. */
4246 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
4247 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
4250 #endif /* HAVE_XPM || MAC_OS */
4252 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4254 x_create_bitmap_from_xpm_data (f
, bits
)
4258 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4260 XpmAttributes attrs
;
4261 Pixmap bitmap
, mask
;
4263 bzero (&attrs
, sizeof attrs
);
4265 attrs
.visual
= FRAME_X_VISUAL (f
);
4266 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4267 attrs
.valuemask
|= XpmVisual
;
4268 attrs
.valuemask
|= XpmColormap
;
4270 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4271 bits
, &bitmap
, &mask
, &attrs
);
4272 if (rc
!= XpmSuccess
)
4274 XpmFreeAttributes (&attrs
);
4278 id
= x_allocate_bitmap_record (f
);
4279 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
4280 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
4281 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
4282 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
4283 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
4284 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
4285 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
4286 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
4288 XpmFreeAttributes (&attrs
);
4291 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4293 /* Load image IMG which will be displayed on frame F. Value is
4294 non-zero if successful. */
4304 XpmAttributes attrs
;
4305 Lisp_Object specified_file
, color_symbols
;
4308 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
4309 #endif /* HAVE_NTGUI */
4311 /* Configure the XPM lib. Use the visual of frame F. Allocate
4312 close colors. Return colors allocated. */
4313 bzero (&attrs
, sizeof attrs
);
4316 attrs
.visual
= FRAME_X_VISUAL (f
);
4317 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4318 attrs
.valuemask
|= XpmVisual
;
4319 attrs
.valuemask
|= XpmColormap
;
4320 #endif /* HAVE_NTGUI */
4322 #ifdef ALLOC_XPM_COLORS
4323 /* Allocate colors with our own functions which handle
4324 failing color allocation more gracefully. */
4325 attrs
.color_closure
= f
;
4326 attrs
.alloc_color
= xpm_alloc_color
;
4327 attrs
.free_colors
= xpm_free_colors
;
4328 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
4329 #else /* not ALLOC_XPM_COLORS */
4330 /* Let the XPM lib allocate colors. */
4331 attrs
.valuemask
|= XpmReturnAllocPixels
;
4332 #ifdef XpmAllocCloseColors
4333 attrs
.alloc_close_colors
= 1;
4334 attrs
.valuemask
|= XpmAllocCloseColors
;
4335 #else /* not XpmAllocCloseColors */
4336 attrs
.closeness
= 600;
4337 attrs
.valuemask
|= XpmCloseness
;
4338 #endif /* not XpmAllocCloseColors */
4339 #endif /* ALLOC_XPM_COLORS */
4341 /* If image specification contains symbolic color definitions, add
4342 these to `attrs'. */
4343 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4344 if (CONSP (color_symbols
))
4347 XpmColorSymbol
*xpm_syms
;
4350 attrs
.valuemask
|= XpmColorSymbols
;
4352 /* Count number of symbols. */
4353 attrs
.numsymbols
= 0;
4354 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4357 /* Allocate an XpmColorSymbol array. */
4358 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4359 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4360 bzero (xpm_syms
, size
);
4361 attrs
.colorsymbols
= xpm_syms
;
4363 /* Fill the color symbol array. */
4364 for (tail
= color_symbols
, i
= 0;
4366 ++i
, tail
= XCDR (tail
))
4368 Lisp_Object name
= XCAR (XCAR (tail
));
4369 Lisp_Object color
= XCDR (XCAR (tail
));
4370 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4371 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4372 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4373 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4377 /* Create a pixmap for the image, either from a file, or from a
4378 string buffer containing data in the same format as an XPM file. */
4379 #ifdef ALLOC_XPM_COLORS
4380 xpm_init_color_cache (f
, &attrs
);
4383 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4387 HDC frame_dc
= get_frame_dc (f
);
4388 hdc
= CreateCompatibleDC (frame_dc
);
4389 release_frame_dc (f
, frame_dc
);
4391 #endif /* HAVE_NTGUI */
4393 if (STRINGP (specified_file
))
4395 Lisp_Object file
= x_find_image_file (specified_file
);
4396 if (!STRINGP (file
))
4398 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4403 /* XpmReadFileToPixmap is not available in the Windows port of
4404 libxpm. But XpmReadFileToImage almost does what we want. */
4405 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4406 &xpm_image
, &xpm_mask
,
4409 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4410 SDATA (file
), &img
->pixmap
, &img
->mask
,
4412 #endif /* HAVE_NTGUI */
4416 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4418 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4419 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4420 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4421 &xpm_image
, &xpm_mask
,
4424 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4426 &img
->pixmap
, &img
->mask
,
4428 #endif /* HAVE_NTGUI */
4431 if (rc
== XpmSuccess
)
4433 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4434 img
->colors
= colors_in_color_table (&img
->ncolors
);
4435 #else /* not ALLOC_XPM_COLORS */
4439 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4440 plus some duplicate attributes. */
4441 if (xpm_image
&& xpm_image
->bitmap
)
4443 img
->pixmap
= xpm_image
->bitmap
;
4444 /* XImageFree in libXpm frees XImage struct without destroying
4445 the bitmap, which is what we want. */
4446 fn_XImageFree (xpm_image
);
4448 if (xpm_mask
&& xpm_mask
->bitmap
)
4450 /* The mask appears to be inverted compared with what we expect.
4451 TODO: invert our expectations. See other places where we
4452 have to invert bits because our idea of masks is backwards. */
4454 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4456 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4457 SelectObject (hdc
, old_obj
);
4459 img
->mask
= xpm_mask
->bitmap
;
4460 fn_XImageFree (xpm_mask
);
4465 #endif /* HAVE_NTGUI */
4467 /* Remember allocated colors. */
4468 img
->ncolors
= attrs
.nalloc_pixels
;
4469 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4470 * sizeof *img
->colors
);
4471 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4473 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4474 #ifdef DEBUG_X_COLORS
4475 register_color (img
->colors
[i
]);
4478 #endif /* not ALLOC_XPM_COLORS */
4480 img
->width
= attrs
.width
;
4481 img
->height
= attrs
.height
;
4482 xassert (img
->width
> 0 && img
->height
> 0);
4484 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4486 fn_XpmFreeAttributes (&attrs
);
4488 XpmFreeAttributes (&attrs
);
4489 #endif /* HAVE_NTGUI */
4495 #endif /* HAVE_NTGUI */
4500 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4503 case XpmFileInvalid
:
4504 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4508 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4511 case XpmColorFailed
:
4512 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4516 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4521 #ifdef ALLOC_XPM_COLORS
4522 xpm_free_color_cache ();
4524 return rc
== XpmSuccess
;
4527 #endif /* HAVE_XPM */
4531 /* XPM support functions for Mac OS where libxpm is not available.
4532 Only XPM version 3 (without any extensions) is supported. */
4534 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4535 const unsigned char **, int *));
4536 static Lisp_Object xpm_make_color_table_v
4537 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4538 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4539 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4541 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4542 const unsigned char *, int));
4543 static Lisp_Object xpm_make_color_table_h
4544 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4545 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4546 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4548 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4549 const unsigned char *, int));
4550 static int xpm_str_to_color_key
P_ ((const char *));
4551 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4552 const unsigned char *, const unsigned char *));
4554 /* Tokens returned from xpm_scan. */
4563 /* Scan an XPM data and return a character (< 256) or a token defined
4564 by enum xpm_token above. *S and END are the start (inclusive) and
4565 the end (exclusive) addresses of the data, respectively. Advance
4566 *S while scanning. If token is either XPM_TK_IDENT or
4567 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4568 length of the corresponding token, respectively. */
4571 xpm_scan (s
, end
, beg
, len
)
4572 const unsigned char **s
, *end
, **beg
;
4579 /* Skip white-space. */
4580 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4583 /* gnus-pointer.xpm uses '-' in its identifier.
4584 sb-dir-plus.xpm uses '+' in its identifier. */
4585 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4589 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4592 return XPM_TK_IDENT
;
4597 while (*s
< end
&& **s
!= '"')
4602 return XPM_TK_STRING
;
4606 if (*s
< end
&& **s
== '*')
4608 /* C-style comment. */
4612 while (*s
< end
&& *(*s
)++ != '*')
4615 while (*s
< end
&& **s
!= '/');
4629 /* Functions for color table lookup in XPM data. A key is a string
4630 specifying the color of each pixel in XPM data. A value is either
4631 an integer that specifies a pixel color, Qt that specifies
4632 transparency, or Qnil for the unspecified color. If the length of
4633 the key string is one, a vector is used as a table. Otherwise, a
4634 hash table is used. */
4637 xpm_make_color_table_v (put_func
, get_func
)
4638 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4639 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4641 *put_func
= xpm_put_color_table_v
;
4642 *get_func
= xpm_get_color_table_v
;
4643 return Fmake_vector (make_number (256), Qnil
);
4647 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4648 Lisp_Object color_table
;
4649 const unsigned char *chars_start
;
4653 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4657 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4658 Lisp_Object color_table
;
4659 const unsigned char *chars_start
;
4662 return XVECTOR (color_table
)->contents
[*chars_start
];
4666 xpm_make_color_table_h (put_func
, get_func
)
4667 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4668 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4670 *put_func
= xpm_put_color_table_h
;
4671 *get_func
= xpm_get_color_table_h
;
4672 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4673 make_float (DEFAULT_REHASH_SIZE
),
4674 make_float (DEFAULT_REHASH_THRESHOLD
),
4679 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4680 Lisp_Object color_table
;
4681 const unsigned char *chars_start
;
4685 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4687 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4689 hash_lookup (table
, chars
, &hash_code
);
4690 hash_put (table
, chars
, color
, hash_code
);
4694 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4695 Lisp_Object color_table
;
4696 const unsigned char *chars_start
;
4699 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4700 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4703 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4706 enum xpm_color_key
{
4714 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4717 xpm_str_to_color_key (s
)
4723 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4725 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4731 xpm_load_image (f
, img
, contents
, end
)
4734 const unsigned char *contents
, *end
;
4736 const unsigned char *s
= contents
, *beg
, *str
;
4737 unsigned char buffer
[BUFSIZ
];
4738 int width
, height
, x
, y
;
4739 int num_colors
, chars_per_pixel
;
4741 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4742 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4743 Lisp_Object frame
, color_symbols
, color_table
;
4744 int best_key
, have_mask
= 0;
4745 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4748 LA1 = xpm_scan (&s, end, &beg, &len)
4750 #define expect(TOKEN) \
4751 if (LA1 != (TOKEN)) \
4756 #define expect_ident(IDENT) \
4757 if (LA1 == XPM_TK_IDENT \
4758 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4763 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4767 expect_ident ("static");
4768 expect_ident ("char");
4770 expect (XPM_TK_IDENT
);
4775 expect (XPM_TK_STRING
);
4778 memcpy (buffer
, beg
, len
);
4780 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4781 &num_colors
, &chars_per_pixel
) != 4
4782 || width
<= 0 || height
<= 0
4783 || num_colors
<= 0 || chars_per_pixel
<= 0)
4786 if (!check_image_size (f
, width
, height
))
4788 image_error ("Invalid image size", Qnil
, Qnil
);
4794 XSETFRAME (frame
, f
);
4795 if (!NILP (Fxw_display_color_p (frame
)))
4796 best_key
= XPM_COLOR_KEY_C
;
4797 else if (!NILP (Fx_display_grayscale_p (frame
)))
4798 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4799 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4801 best_key
= XPM_COLOR_KEY_M
;
4803 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4804 if (chars_per_pixel
== 1)
4805 color_table
= xpm_make_color_table_v (&put_color_table
,
4808 color_table
= xpm_make_color_table_h (&put_color_table
,
4811 while (num_colors
-- > 0)
4813 unsigned char *color
, *max_color
;
4814 int key
, next_key
, max_key
= 0;
4815 Lisp_Object symbol_color
= Qnil
, color_val
;
4818 expect (XPM_TK_STRING
);
4819 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4821 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4822 buffer
[len
- chars_per_pixel
] = '\0';
4824 str
= strtok (buffer
, " \t");
4827 key
= xpm_str_to_color_key (str
);
4832 color
= strtok (NULL
, " \t");
4836 while ((str
= strtok (NULL
, " \t")) != NULL
)
4838 next_key
= xpm_str_to_color_key (str
);
4841 color
[strlen (color
)] = ' ';
4844 if (key
== XPM_COLOR_KEY_S
)
4846 if (NILP (symbol_color
))
4847 symbol_color
= build_string (color
);
4849 else if (max_key
< key
&& key
<= best_key
)
4859 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4861 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4863 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4865 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4867 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4869 color_val
= make_number (cdef
.pixel
);
4872 if (NILP (color_val
) && max_key
> 0)
4874 if (xstricmp (max_color
, "None") == 0)
4876 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4877 color_val
= make_number (cdef
.pixel
);
4879 if (!NILP (color_val
))
4880 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4885 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4886 &ximg
, &img
->pixmap
)
4887 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4888 &mask_img
, &img
->mask
))
4890 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4894 for (y
= 0; y
< height
; y
++)
4896 expect (XPM_TK_STRING
);
4898 if (len
< width
* chars_per_pixel
)
4900 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4902 Lisp_Object color_val
=
4903 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4905 XPutPixel (ximg
, x
, y
,
4906 (INTEGERP (color_val
) ? XINT (color_val
)
4907 : FRAME_FOREGROUND_PIXEL (f
)));
4908 XPutPixel (mask_img
, x
, y
,
4909 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4910 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4917 img
->height
= height
;
4919 /* Maybe fill in the background field while we have ximg handy. */
4920 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4921 IMAGE_BACKGROUND (img
, f
, ximg
);
4923 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4924 x_destroy_x_image (ximg
);
4927 /* Fill in the background_transparent field while we have the
4929 image_background_transparent (img
, f
, mask_img
);
4931 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4932 x_destroy_x_image (mask_img
);
4936 x_destroy_x_image (mask_img
);
4937 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4938 img
->mask
= NO_PIXMAP
;
4944 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4946 x_destroy_x_image (ximg
);
4947 x_destroy_x_image (mask_img
);
4948 x_clear_image (f
, img
);
4962 Lisp_Object file_name
;
4964 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4965 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4966 if (STRINGP (file_name
))
4969 unsigned char *contents
;
4971 struct gcpro gcpro1
;
4973 file
= x_find_image_file (file_name
);
4975 if (!STRINGP (file
))
4977 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4982 contents
= slurp_file (SDATA (file
), &size
);
4983 if (contents
== NULL
)
4985 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4990 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4998 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4999 success_p
= xpm_load_image (f
, img
, SDATA (data
),
5000 SDATA (data
) + SBYTES (data
));
5010 /***********************************************************************
5012 ***********************************************************************/
5014 #ifdef COLOR_TABLE_SUPPORT
5016 /* An entry in the color table mapping an RGB color to a pixel color. */
5021 unsigned long pixel
;
5023 /* Next in color table collision list. */
5024 struct ct_color
*next
;
5027 /* The bucket vector size to use. Must be prime. */
5031 /* Value is a hash of the RGB color given by R, G, and B. */
5033 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5035 /* The color hash table. */
5037 struct ct_color
**ct_table
;
5039 /* Number of entries in the color table. */
5041 int ct_colors_allocated
;
5043 /* Initialize the color table. */
5048 int size
= CT_SIZE
* sizeof (*ct_table
);
5049 ct_table
= (struct ct_color
**) xmalloc (size
);
5050 bzero (ct_table
, size
);
5051 ct_colors_allocated
= 0;
5055 /* Free memory associated with the color table. */
5061 struct ct_color
*p
, *next
;
5063 for (i
= 0; i
< CT_SIZE
; ++i
)
5064 for (p
= ct_table
[i
]; p
; p
= next
)
5075 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5076 entry for that color already is in the color table, return the
5077 pixel color of that entry. Otherwise, allocate a new color for R,
5078 G, B, and make an entry in the color table. */
5080 static unsigned long
5081 lookup_rgb_color (f
, r
, g
, b
)
5085 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
5086 int i
= hash
% CT_SIZE
;
5088 Display_Info
*dpyinfo
;
5090 /* Handle TrueColor visuals specially, which improves performance by
5091 two orders of magnitude. Freeing colors on TrueColor visuals is
5092 a nop, and pixel colors specify RGB values directly. See also
5093 the Xlib spec, chapter 3.1. */
5094 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5095 if (dpyinfo
->red_bits
> 0)
5097 unsigned long pr
, pg
, pb
;
5099 /* Apply gamma-correction like normal color allocation does. */
5103 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
5104 gamma_correct (f
, &color
);
5105 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
5108 /* Scale down RGB values to the visual's bits per RGB, and shift
5109 them to the right position in the pixel color. Note that the
5110 original RGB values are 16-bit values, as usual in X. */
5111 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
5112 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
5113 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
5115 /* Assemble the pixel color. */
5116 return pr
| pg
| pb
;
5119 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5120 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
5126 #ifdef HAVE_X_WINDOWS
5135 cmap
= FRAME_X_COLORMAP (f
);
5136 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5139 ++ct_colors_allocated
;
5140 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5144 p
->pixel
= color
.pixel
;
5145 p
->next
= ct_table
[i
];
5149 return FRAME_FOREGROUND_PIXEL (f
);
5154 color
= PALETTERGB (r
, g
, b
);
5156 color
= RGB_TO_ULONG (r
, g
, b
);
5157 #endif /* HAVE_NTGUI */
5158 ++ct_colors_allocated
;
5159 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5164 p
->next
= ct_table
[i
];
5166 #endif /* HAVE_X_WINDOWS */
5174 /* Look up pixel color PIXEL which is used on frame F in the color
5175 table. If not already present, allocate it. Value is PIXEL. */
5177 static unsigned long
5178 lookup_pixel_color (f
, pixel
)
5180 unsigned long pixel
;
5182 int i
= pixel
% CT_SIZE
;
5185 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5186 if (p
->pixel
== pixel
)
5195 #ifdef HAVE_X_WINDOWS
5196 cmap
= FRAME_X_COLORMAP (f
);
5197 color
.pixel
= pixel
;
5198 x_query_color (f
, &color
);
5199 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5202 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
5203 color
.pixel
= pixel
;
5204 XQueryColor (NULL
, cmap
, &color
);
5205 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5207 #endif /* HAVE_X_WINDOWS */
5211 ++ct_colors_allocated
;
5213 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5218 p
->next
= ct_table
[i
];
5222 return FRAME_FOREGROUND_PIXEL (f
);
5228 /* Value is a vector of all pixel colors contained in the color table,
5229 allocated via xmalloc. Set *N to the number of colors. */
5231 static unsigned long *
5232 colors_in_color_table (n
)
5237 unsigned long *colors
;
5239 if (ct_colors_allocated
== 0)
5246 colors
= (unsigned long *) xmalloc (ct_colors_allocated
5248 *n
= ct_colors_allocated
;
5250 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
5251 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5252 colors
[j
++] = p
->pixel
;
5258 #else /* COLOR_TABLE_SUPPORT */
5260 static unsigned long
5261 lookup_rgb_color (f
, r
, g
, b
)
5265 unsigned long pixel
;
5268 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5269 gamma_correct (f
, &pixel
);
5273 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
5274 #endif /* HAVE_NTGUI */
5283 #endif /* COLOR_TABLE_SUPPORT */
5286 /***********************************************************************
5288 ***********************************************************************/
5290 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
5291 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
5292 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
5295 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
5296 #endif /* HAVE_NTGUI */
5298 /* Non-zero means draw a cross on images having `:conversion
5301 int cross_disabled_images
;
5303 /* Edge detection matrices for different edge-detection
5306 static int emboss_matrix
[9] = {
5308 2, -1, 0, /* y - 1 */
5310 0, 1, -2 /* y + 1 */
5313 static int laplace_matrix
[9] = {
5315 1, 0, 0, /* y - 1 */
5317 0, 0, -1 /* y + 1 */
5320 /* Value is the intensity of the color whose red/green/blue values
5323 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5326 /* On frame F, return an array of XColor structures describing image
5327 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5328 non-zero means also fill the red/green/blue members of the XColor
5329 structures. Value is a pointer to the array of XColors structures,
5330 allocated with xmalloc; it must be freed by the caller. */
5333 x_to_xcolors (f
, img
, rgb_p
)
5340 XImagePtr_or_DC ximg
;
5344 #endif /* HAVE_NTGUI */
5346 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5349 /* Get the X image IMG->pixmap. */
5350 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5351 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5353 /* Load the image into a memory device context. */
5354 hdc
= get_frame_dc (f
);
5355 ximg
= CreateCompatibleDC (hdc
);
5356 release_frame_dc (f
, hdc
);
5357 prev
= SelectObject (ximg
, img
->pixmap
);
5358 #endif /* HAVE_NTGUI */
5360 /* Fill the `pixel' members of the XColor array. I wished there
5361 were an easy and portable way to circumvent XGetPixel. */
5363 for (y
= 0; y
< img
->height
; ++y
)
5367 #ifdef HAVE_X_WINDOWS
5368 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5369 p
->pixel
= XGetPixel (ximg
, x
, y
);
5371 x_query_colors (f
, row
, img
->width
);
5375 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5377 /* W32_TODO: palette support needed here? */
5378 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5382 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5383 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5384 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5387 p
->red
= 256 * GetRValue (p
->pixel
);
5388 p
->green
= 256 * GetGValue (p
->pixel
);
5389 p
->blue
= 256 * GetBValue (p
->pixel
);
5390 #endif /* HAVE_NTGUI */
5393 #endif /* HAVE_X_WINDOWS */
5396 Destroy_Image (ximg
, prev
);
5403 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5404 created with CreateDIBSection, with the pointer to the bit values
5405 stored in ximg->data. */
5408 XPutPixel (ximg
, x
, y
, color
)
5413 int width
= ximg
->info
.bmiHeader
.biWidth
;
5414 int height
= ximg
->info
.bmiHeader
.biHeight
;
5415 unsigned char * pixel
;
5417 /* True color images. */
5418 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5420 int rowbytes
= width
* 3;
5421 /* Ensure scanlines are aligned on 4 byte boundaries. */
5423 rowbytes
+= 4 - (rowbytes
% 4);
5425 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5426 /* Windows bitmaps are in BGR order. */
5427 *pixel
= GetBValue (color
);
5428 *(pixel
+ 1) = GetGValue (color
);
5429 *(pixel
+ 2) = GetRValue (color
);
5431 /* Monochrome images. */
5432 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5434 int rowbytes
= width
/ 8;
5435 /* Ensure scanlines are aligned on 4 byte boundaries. */
5437 rowbytes
+= 4 - (rowbytes
% 4);
5438 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5439 /* Filter out palette info. */
5440 if (color
& 0x00ffffff)
5441 *pixel
= *pixel
| (1 << x
% 8);
5443 *pixel
= *pixel
& ~(1 << x
% 8);
5446 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5449 #endif /* HAVE_NTGUI */
5451 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5452 RGB members are set. F is the frame on which this all happens.
5453 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5456 x_from_xcolors (f
, img
, colors
)
5466 init_color_table ();
5468 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5471 for (y
= 0; y
< img
->height
; ++y
)
5472 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5474 unsigned long pixel
;
5475 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5476 XPutPixel (oimg
, x
, y
, pixel
);
5480 x_clear_image_1 (f
, img
, 1, 0, 1);
5482 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5483 x_destroy_x_image (oimg
);
5484 img
->pixmap
= pixmap
;
5485 #ifdef COLOR_TABLE_SUPPORT
5486 img
->colors
= colors_in_color_table (&img
->ncolors
);
5487 free_color_table ();
5488 #endif /* COLOR_TABLE_SUPPORT */
5492 /* On frame F, perform edge-detection on image IMG.
5494 MATRIX is a nine-element array specifying the transformation
5495 matrix. See emboss_matrix for an example.
5497 COLOR_ADJUST is a color adjustment added to each pixel of the
5501 x_detect_edges (f
, img
, matrix
, color_adjust
)
5504 int matrix
[9], color_adjust
;
5506 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5510 for (i
= sum
= 0; i
< 9; ++i
)
5511 sum
+= eabs (matrix
[i
]);
5513 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5515 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5517 for (y
= 0; y
< img
->height
; ++y
)
5519 p
= COLOR (new, 0, y
);
5520 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5521 p
= COLOR (new, img
->width
- 1, y
);
5522 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5525 for (x
= 1; x
< img
->width
- 1; ++x
)
5527 p
= COLOR (new, x
, 0);
5528 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5529 p
= COLOR (new, x
, img
->height
- 1);
5530 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5533 for (y
= 1; y
< img
->height
- 1; ++y
)
5535 p
= COLOR (new, 1, y
);
5537 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5539 int r
, g
, b
, y1
, x1
;
5542 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5543 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5546 XColor
*t
= COLOR (colors
, x1
, y1
);
5547 r
+= matrix
[i
] * t
->red
;
5548 g
+= matrix
[i
] * t
->green
;
5549 b
+= matrix
[i
] * t
->blue
;
5552 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5553 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5554 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5555 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5560 x_from_xcolors (f
, img
, new);
5566 /* Perform the pre-defined `emboss' edge-detection on image IMG
5574 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5578 /* Transform image IMG which is used on frame F with a Laplace
5579 edge-detection algorithm. The result is an image that can be used
5580 to draw disabled buttons, for example. */
5587 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5591 /* Perform edge-detection on image IMG on frame F, with specified
5592 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5594 MATRIX must be either
5596 - a list of at least 9 numbers in row-major form
5597 - a vector of at least 9 numbers
5599 COLOR_ADJUST nil means use a default; otherwise it must be a
5603 x_edge_detection (f
, img
, matrix
, color_adjust
)
5606 Lisp_Object matrix
, color_adjust
;
5614 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5615 ++i
, matrix
= XCDR (matrix
))
5616 trans
[i
] = XFLOATINT (XCAR (matrix
));
5618 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5620 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5621 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5624 if (NILP (color_adjust
))
5625 color_adjust
= make_number (0xffff / 2);
5627 if (i
== 9 && NUMBERP (color_adjust
))
5628 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5632 /* Transform image IMG on frame F so that it looks disabled. */
5635 x_disable_image (f
, img
)
5639 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5641 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5643 int n_planes
= dpyinfo
->n_planes
;
5644 #endif /* HAVE_NTGUI */
5648 /* Color (or grayscale). Convert to gray, and equalize. Just
5649 drawing such images with a stipple can look very odd, so
5650 we're using this method instead. */
5651 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5653 const int h
= 15000;
5654 const int l
= 30000;
5656 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5660 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5661 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5662 p
->red
= p
->green
= p
->blue
= i2
;
5665 x_from_xcolors (f
, img
, colors
);
5668 /* Draw a cross over the disabled image, if we must or if we
5670 if (n_planes
< 2 || cross_disabled_images
)
5673 Display
*dpy
= FRAME_X_DISPLAY (f
);
5677 #define MaskForeground(f) PIX_MASK_DRAW
5679 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5682 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5683 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5684 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5685 img
->width
- 1, img
->height
- 1);
5686 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5692 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5693 XSetForeground (dpy
, gc
, MaskForeground (f
));
5694 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5695 img
->width
- 1, img
->height
- 1);
5696 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5704 hdc
= get_frame_dc (f
);
5705 bmpdc
= CreateCompatibleDC (hdc
);
5706 release_frame_dc (f
, hdc
);
5708 prev
= SelectObject (bmpdc
, img
->pixmap
);
5710 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5711 MoveToEx (bmpdc
, 0, 0, NULL
);
5712 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5713 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5714 LineTo (bmpdc
, img
->width
- 1, 0);
5718 SelectObject (bmpdc
, img
->mask
);
5719 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5720 MoveToEx (bmpdc
, 0, 0, NULL
);
5721 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5722 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5723 LineTo (bmpdc
, img
->width
- 1, 0);
5725 SelectObject (bmpdc
, prev
);
5727 #endif /* HAVE_NTGUI */
5732 /* Build a mask for image IMG which is used on frame F. FILE is the
5733 name of an image file, for error messages. HOW determines how to
5734 determine the background color of IMG. If it is a list '(R G B)',
5735 with R, G, and B being integers >= 0, take that as the color of the
5736 background. Otherwise, determine the background color of IMG
5737 heuristically. Value is non-zero if successful. */
5740 x_build_heuristic_mask (f
, img
, how
)
5745 XImagePtr_or_DC ximg
;
5753 #endif /* HAVE_NTGUI */
5754 int x
, y
, rc
, use_img_background
;
5755 unsigned long bg
= 0;
5759 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5760 img
->mask
= NO_PIXMAP
;
5761 img
->background_transparent_valid
= 0;
5765 /* Create an image and pixmap serving as mask. */
5766 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5767 &mask_img
, &img
->mask
);
5771 /* Get the X image of IMG->pixmap. */
5772 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5773 img
->width
, img
->height
,
5776 /* Create the bit array serving as mask. */
5777 row_width
= (img
->width
+ 7) / 8;
5778 mask_img
= xmalloc (row_width
* img
->height
);
5779 bzero (mask_img
, row_width
* img
->height
);
5781 /* Create a memory device context for IMG->pixmap. */
5782 frame_dc
= get_frame_dc (f
);
5783 ximg
= CreateCompatibleDC (frame_dc
);
5784 release_frame_dc (f
, frame_dc
);
5785 prev
= SelectObject (ximg
, img
->pixmap
);
5786 #endif /* HAVE_NTGUI */
5788 /* Determine the background color of ximg. If HOW is `(R G B)'
5789 take that as color. Otherwise, use the image's background color. */
5790 use_img_background
= 1;
5796 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5798 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5802 if (i
== 3 && NILP (how
))
5804 char color_name
[30];
5805 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5808 0x00ffffff & /* Filter out palette info. */
5809 #endif /* HAVE_NTGUI */
5810 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5811 use_img_background
= 0;
5815 if (use_img_background
)
5816 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5818 /* Set all bits in mask_img to 1 whose color in ximg is different
5819 from the background color bg. */
5821 for (y
= 0; y
< img
->height
; ++y
)
5822 for (x
= 0; x
< img
->width
; ++x
)
5823 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5824 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5826 /* Fill in the background_transparent field while we have the mask handy. */
5827 image_background_transparent (img
, f
, mask_img
);
5829 /* Put mask_img into img->mask. */
5830 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5831 x_destroy_x_image (mask_img
);
5834 for (y
= 0; y
< img
->height
; ++y
)
5835 for (x
= 0; x
< img
->width
; ++x
)
5837 COLORREF p
= GetPixel (ximg
, x
, y
);
5839 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5842 /* Create the mask image. */
5843 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5845 /* Fill in the background_transparent field while we have the mask handy. */
5846 SelectObject (ximg
, img
->mask
);
5847 image_background_transparent (img
, f
, ximg
);
5849 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5851 #endif /* HAVE_NTGUI */
5853 Destroy_Image (ximg
, prev
);
5859 /***********************************************************************
5860 PBM (mono, gray, color)
5861 ***********************************************************************/
5863 static int pbm_image_p
P_ ((Lisp_Object object
));
5864 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5865 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5867 /* The symbol `pbm' identifying images of this type. */
5871 /* Indices of image specification fields in gs_format, below. */
5873 enum pbm_keyword_index
5889 /* Vector of image_keyword structures describing the format
5890 of valid user-defined image specifications. */
5892 static struct image_keyword pbm_format
[PBM_LAST
] =
5894 {":type", IMAGE_SYMBOL_VALUE
, 1},
5895 {":file", IMAGE_STRING_VALUE
, 0},
5896 {":data", IMAGE_STRING_VALUE
, 0},
5897 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5898 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5899 {":relief", IMAGE_INTEGER_VALUE
, 0},
5900 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5901 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5902 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5903 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5904 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5907 /* Structure describing the image type `pbm'. */
5909 static struct image_type pbm_type
=
5919 /* Return non-zero if OBJECT is a valid PBM image specification. */
5922 pbm_image_p (object
)
5925 struct image_keyword fmt
[PBM_LAST
];
5927 bcopy (pbm_format
, fmt
, sizeof fmt
);
5929 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5932 /* Must specify either :data or :file. */
5933 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5937 /* Scan a decimal number from *S and return it. Advance *S while
5938 reading the number. END is the end of the string. Value is -1 at
5942 pbm_scan_number (s
, end
)
5943 unsigned char **s
, *end
;
5945 int c
= 0, val
= -1;
5949 /* Skip white-space. */
5950 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5955 /* Skip comment to end of line. */
5956 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5959 else if (isdigit (c
))
5961 /* Read decimal number. */
5963 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5964 val
= 10 * val
+ c
- '0';
5976 #if 0 /* Unused. ++kfs */
5978 /* Read FILE into memory. Value is a pointer to a buffer allocated
5979 with xmalloc holding FILE's contents. Value is null if an error
5980 occurred. *SIZE is set to the size of the file. */
5983 pbm_read_file (file
, size
)
5991 if (stat (SDATA (file
), &st
) == 0
5992 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5993 && (buf
= (char *) xmalloc (st
.st_size
),
5994 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6013 #endif /* HAVE_NTGUI */
6015 /* Load PBM image IMG for use on frame F. */
6023 int width
, height
, max_color_idx
= 0;
6025 Lisp_Object file
, specified_file
;
6026 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
6027 struct gcpro gcpro1
;
6028 unsigned char *contents
= NULL
;
6029 unsigned char *end
, *p
;
6032 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6036 if (STRINGP (specified_file
))
6038 file
= x_find_image_file (specified_file
);
6039 if (!STRINGP (file
))
6041 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6046 contents
= slurp_file (SDATA (file
), &size
);
6047 if (contents
== NULL
)
6049 image_error ("Error reading `%s'", file
, Qnil
);
6055 end
= contents
+ size
;
6060 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6062 end
= p
+ SBYTES (data
);
6065 /* Check magic number. */
6066 if (end
- p
< 2 || *p
++ != 'P')
6068 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6078 raw_p
= 0, type
= PBM_MONO
;
6082 raw_p
= 0, type
= PBM_GRAY
;
6086 raw_p
= 0, type
= PBM_COLOR
;
6090 raw_p
= 1, type
= PBM_MONO
;
6094 raw_p
= 1, type
= PBM_GRAY
;
6098 raw_p
= 1, type
= PBM_COLOR
;
6102 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6106 /* Read width, height, maximum color-component. Characters
6107 starting with `#' up to the end of a line are ignored. */
6108 width
= pbm_scan_number (&p
, end
);
6109 height
= pbm_scan_number (&p
, end
);
6111 if (type
!= PBM_MONO
)
6113 max_color_idx
= pbm_scan_number (&p
, end
);
6114 if (max_color_idx
> 65535 || max_color_idx
< 0)
6116 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
6121 if (!check_image_size (f
, width
, height
))
6123 image_error ("Invalid image size", Qnil
, Qnil
);
6127 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
6128 &ximg
, &img
->pixmap
))
6131 /* Initialize the color hash table. */
6132 init_color_table ();
6134 if (type
== PBM_MONO
)
6137 struct image_keyword fmt
[PBM_LAST
];
6138 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
6139 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
6141 /* Parse the image specification. */
6142 bcopy (pbm_format
, fmt
, sizeof fmt
);
6143 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
6145 /* Get foreground and background colors, maybe allocate colors. */
6146 if (fmt
[PBM_FOREGROUND
].count
6147 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
6148 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
6149 if (fmt
[PBM_BACKGROUND
].count
6150 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
6152 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
6153 img
->background
= bg
;
6154 img
->background_valid
= 1;
6157 for (y
= 0; y
< height
; ++y
)
6158 for (x
= 0; x
< width
; ++x
)
6166 x_destroy_x_image (ximg
);
6167 x_clear_image (f
, img
);
6168 image_error ("Invalid image size in image `%s'",
6178 g
= pbm_scan_number (&p
, end
);
6180 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
6185 int expected_size
= height
* width
;
6186 if (max_color_idx
> 255)
6188 if (type
== PBM_COLOR
)
6191 if (raw_p
&& p
+ expected_size
> end
)
6193 x_destroy_x_image (ximg
);
6194 x_clear_image (f
, img
);
6195 image_error ("Invalid image size in image `%s'",
6200 for (y
= 0; y
< height
; ++y
)
6201 for (x
= 0; x
< width
; ++x
)
6205 if (type
== PBM_GRAY
&& raw_p
)
6208 if (max_color_idx
> 255)
6209 r
= g
= b
= r
* 256 + *p
++;
6211 else if (type
== PBM_GRAY
)
6212 r
= g
= b
= pbm_scan_number (&p
, end
);
6216 if (max_color_idx
> 255)
6219 if (max_color_idx
> 255)
6222 if (max_color_idx
> 255)
6227 r
= pbm_scan_number (&p
, end
);
6228 g
= pbm_scan_number (&p
, end
);
6229 b
= pbm_scan_number (&p
, end
);
6232 if (r
< 0 || g
< 0 || b
< 0)
6234 x_destroy_x_image (ximg
);
6235 image_error ("Invalid pixel value in image `%s'",
6240 /* RGB values are now in the range 0..max_color_idx.
6241 Scale this to the range 0..0xffff supported by X. */
6242 r
= (double) r
* 65535 / max_color_idx
;
6243 g
= (double) g
* 65535 / max_color_idx
;
6244 b
= (double) b
* 65535 / max_color_idx
;
6245 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6249 #ifdef COLOR_TABLE_SUPPORT
6250 /* Store in IMG->colors the colors allocated for the image, and
6251 free the color table. */
6252 img
->colors
= colors_in_color_table (&img
->ncolors
);
6253 free_color_table ();
6254 #endif /* COLOR_TABLE_SUPPORT */
6257 img
->height
= height
;
6259 /* Maybe fill in the background field while we have ximg handy. */
6261 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6262 /* Casting avoids a GCC warning. */
6263 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6265 /* Put the image into a pixmap. */
6266 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6267 x_destroy_x_image (ximg
);
6269 /* X and W32 versions did it here, MAC version above. ++kfs
6271 img->height = height; */
6279 /***********************************************************************
6281 ***********************************************************************/
6283 #if defined (HAVE_PNG) || defined (MAC_OS)
6285 /* Function prototypes. */
6287 static int png_image_p
P_ ((Lisp_Object object
));
6288 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
6290 /* The symbol `png' identifying images of this type. */
6294 /* Indices of image specification fields in png_format, below. */
6296 enum png_keyword_index
6311 /* Vector of image_keyword structures describing the format
6312 of valid user-defined image specifications. */
6314 static struct image_keyword png_format
[PNG_LAST
] =
6316 {":type", IMAGE_SYMBOL_VALUE
, 1},
6317 {":data", IMAGE_STRING_VALUE
, 0},
6318 {":file", IMAGE_STRING_VALUE
, 0},
6319 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6320 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6321 {":relief", IMAGE_INTEGER_VALUE
, 0},
6322 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6323 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6324 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6325 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6328 /* Structure describing the image type `png'. */
6330 static struct image_type png_type
=
6339 /* Return non-zero if OBJECT is a valid PNG image specification. */
6342 png_image_p (object
)
6345 struct image_keyword fmt
[PNG_LAST
];
6346 bcopy (png_format
, fmt
, sizeof fmt
);
6348 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
6351 /* Must specify either the :data or :file keyword. */
6352 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
6355 #endif /* HAVE_PNG || MAC_OS */
6360 #if defined HAVE_LIBPNG_PNG_H
6361 # include <libpng/png.h>
6367 /* PNG library details. */
6369 DEF_IMGLIB_FN (png_get_io_ptr
);
6370 DEF_IMGLIB_FN (png_check_sig
);
6371 DEF_IMGLIB_FN (png_create_read_struct
);
6372 DEF_IMGLIB_FN (png_create_info_struct
);
6373 DEF_IMGLIB_FN (png_destroy_read_struct
);
6374 DEF_IMGLIB_FN (png_set_read_fn
);
6375 DEF_IMGLIB_FN (png_set_sig_bytes
);
6376 DEF_IMGLIB_FN (png_read_info
);
6377 DEF_IMGLIB_FN (png_get_IHDR
);
6378 DEF_IMGLIB_FN (png_get_valid
);
6379 DEF_IMGLIB_FN (png_set_strip_16
);
6380 DEF_IMGLIB_FN (png_set_expand
);
6381 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6382 DEF_IMGLIB_FN (png_set_background
);
6383 DEF_IMGLIB_FN (png_get_bKGD
);
6384 DEF_IMGLIB_FN (png_read_update_info
);
6385 DEF_IMGLIB_FN (png_get_channels
);
6386 DEF_IMGLIB_FN (png_get_rowbytes
);
6387 DEF_IMGLIB_FN (png_read_image
);
6388 DEF_IMGLIB_FN (png_read_end
);
6389 DEF_IMGLIB_FN (png_error
);
6392 init_png_functions (Lisp_Object libraries
)
6396 /* Try loading libpng under probable names. */
6397 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6400 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6401 LOAD_IMGLIB_FN (library
, png_check_sig
);
6402 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6403 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6404 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6405 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6406 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6407 LOAD_IMGLIB_FN (library
, png_read_info
);
6408 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6409 LOAD_IMGLIB_FN (library
, png_get_valid
);
6410 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6411 LOAD_IMGLIB_FN (library
, png_set_expand
);
6412 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6413 LOAD_IMGLIB_FN (library
, png_set_background
);
6414 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6415 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6416 LOAD_IMGLIB_FN (library
, png_get_channels
);
6417 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6418 LOAD_IMGLIB_FN (library
, png_read_image
);
6419 LOAD_IMGLIB_FN (library
, png_read_end
);
6420 LOAD_IMGLIB_FN (library
, png_error
);
6425 #define fn_png_get_io_ptr png_get_io_ptr
6426 #define fn_png_check_sig png_check_sig
6427 #define fn_png_create_read_struct png_create_read_struct
6428 #define fn_png_create_info_struct png_create_info_struct
6429 #define fn_png_destroy_read_struct png_destroy_read_struct
6430 #define fn_png_set_read_fn png_set_read_fn
6431 #define fn_png_set_sig_bytes png_set_sig_bytes
6432 #define fn_png_read_info png_read_info
6433 #define fn_png_get_IHDR png_get_IHDR
6434 #define fn_png_get_valid png_get_valid
6435 #define fn_png_set_strip_16 png_set_strip_16
6436 #define fn_png_set_expand png_set_expand
6437 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6438 #define fn_png_set_background png_set_background
6439 #define fn_png_get_bKGD png_get_bKGD
6440 #define fn_png_read_update_info png_read_update_info
6441 #define fn_png_get_channels png_get_channels
6442 #define fn_png_get_rowbytes png_get_rowbytes
6443 #define fn_png_read_image png_read_image
6444 #define fn_png_read_end png_read_end
6445 #define fn_png_error png_error
6447 #endif /* HAVE_NTGUI */
6449 /* Error and warning handlers installed when the PNG library
6453 my_png_error (png_ptr
, msg
)
6454 png_struct
*png_ptr
;
6457 xassert (png_ptr
!= NULL
);
6458 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6459 longjmp (png_ptr
->jmpbuf
, 1);
6464 my_png_warning (png_ptr
, msg
)
6465 png_struct
*png_ptr
;
6468 xassert (png_ptr
!= NULL
);
6469 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6472 /* Memory source for PNG decoding. */
6474 struct png_memory_storage
6476 unsigned char *bytes
; /* The data */
6477 size_t len
; /* How big is it? */
6478 int index
; /* Where are we? */
6482 /* Function set as reader function when reading PNG image from memory.
6483 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6484 bytes from the input to DATA. */
6487 png_read_from_memory (png_ptr
, data
, length
)
6488 png_structp png_ptr
;
6492 struct png_memory_storage
*tbr
6493 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6495 if (length
> tbr
->len
- tbr
->index
)
6496 fn_png_error (png_ptr
, "Read error");
6498 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6499 tbr
->index
= tbr
->index
+ length
;
6503 /* Function set as reader function when reading PNG image from a file.
6504 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6505 bytes from the input to DATA. */
6508 png_read_from_file (png_ptr
, data
, length
)
6509 png_structp png_ptr
;
6513 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6515 if (fread (data
, 1, length
, fp
) < length
)
6516 fn_png_error (png_ptr
, "Read error");
6520 /* Load PNG image IMG for use on frame F. Value is non-zero if
6528 Lisp_Object file
, specified_file
;
6529 Lisp_Object specified_data
;
6531 XImagePtr ximg
, mask_img
= NULL
;
6532 struct gcpro gcpro1
;
6533 png_struct
*png_ptr
= NULL
;
6534 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6535 FILE *volatile fp
= NULL
;
6537 png_byte
* volatile pixels
= NULL
;
6538 png_byte
** volatile rows
= NULL
;
6539 png_uint_32 width
, height
;
6540 int bit_depth
, color_type
, interlace_type
;
6542 png_uint_32 row_bytes
;
6544 struct png_memory_storage tbr
; /* Data to be read */
6546 /* Find out what file to load. */
6547 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6548 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6552 if (NILP (specified_data
))
6554 file
= x_find_image_file (specified_file
);
6555 if (!STRINGP (file
))
6557 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6562 /* Open the image file. */
6563 fp
= fopen (SDATA (file
), "rb");
6566 image_error ("Cannot open image file `%s'", file
, Qnil
);
6571 /* Check PNG signature. */
6572 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6573 || !fn_png_check_sig (sig
, sizeof sig
))
6575 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6583 /* Read from memory. */
6584 tbr
.bytes
= SDATA (specified_data
);
6585 tbr
.len
= SBYTES (specified_data
);
6588 /* Check PNG signature. */
6589 if (tbr
.len
< sizeof sig
6590 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6592 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6597 /* Need to skip past the signature. */
6598 tbr
.bytes
+= sizeof (sig
);
6601 /* Initialize read and info structs for PNG lib. Casting return
6602 value avoids a GCC warning on W32. */
6603 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6608 if (fp
) fclose (fp
);
6613 /* Casting return value avoids a GCC warning on W32. */
6614 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6617 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6618 if (fp
) fclose (fp
);
6623 /* Casting return value avoids a GCC warning on W32. */
6624 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6627 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6628 if (fp
) fclose (fp
);
6633 /* Set error jump-back. We come back here when the PNG library
6634 detects an error. */
6635 if (setjmp (png_ptr
->jmpbuf
))
6639 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6642 if (fp
) fclose (fp
);
6647 /* Read image info. */
6648 if (!NILP (specified_data
))
6649 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6651 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6653 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6654 fn_png_read_info (png_ptr
, info_ptr
);
6655 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6656 &interlace_type
, NULL
, NULL
);
6658 if (!check_image_size (f
, width
, height
))
6661 /* If image contains simply transparency data, we prefer to
6662 construct a clipping mask. */
6663 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6668 /* This function is easier to write if we only have to handle
6669 one data format: RGB or RGBA with 8 bits per channel. Let's
6670 transform other formats into that format. */
6672 /* Strip more than 8 bits per channel. */
6673 if (bit_depth
== 16)
6674 fn_png_set_strip_16 (png_ptr
);
6676 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6678 fn_png_set_expand (png_ptr
);
6680 /* Convert grayscale images to RGB. */
6681 if (color_type
== PNG_COLOR_TYPE_GRAY
6682 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6683 fn_png_set_gray_to_rgb (png_ptr
);
6685 /* Handle alpha channel by combining the image with a background
6686 color. Do this only if a real alpha channel is supplied. For
6687 simple transparency, we prefer a clipping mask. */
6690 /* png_color_16 *image_bg; */
6691 Lisp_Object specified_bg
6692 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6693 int shift
= (bit_depth
== 16) ? 0 : 8;
6695 if (STRINGP (specified_bg
))
6696 /* The user specified `:background', use that. */
6698 /* W32 version incorrectly used COLORREF here!! ++kfs */
6700 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6702 png_color_16 user_bg
;
6704 bzero (&user_bg
, sizeof user_bg
);
6705 user_bg
.red
= color
.red
>> shift
;
6706 user_bg
.green
= color
.green
>> shift
;
6707 user_bg
.blue
= color
.blue
>> shift
;
6709 fn_png_set_background (png_ptr
, &user_bg
,
6710 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6715 /* We use the current frame background, ignoring any default
6716 background color set by the image. */
6717 #ifdef HAVE_X_WINDOWS
6719 png_color_16 frame_background
;
6721 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6722 x_query_color (f
, &color
);
6724 bzero (&frame_background
, sizeof frame_background
);
6725 frame_background
.red
= color
.red
>> shift
;
6726 frame_background
.green
= color
.green
>> shift
;
6727 frame_background
.blue
= color
.blue
>> shift
;
6728 #endif /* HAVE_X_WINDOWS */
6732 png_color_16 frame_background
;
6733 color
= FRAME_BACKGROUND_PIXEL (f
);
6734 #if 0 /* W32 TODO : Colormap support. */
6735 x_query_color (f
, &color
);
6737 bzero (&frame_background
, sizeof frame_background
);
6738 frame_background
.red
= GetRValue (color
);
6739 frame_background
.green
= GetGValue (color
);
6740 frame_background
.blue
= GetBValue (color
);
6741 #endif /* HAVE_NTGUI */
6744 unsigned long color
;
6745 png_color_16 frame_background
;
6746 color
= FRAME_BACKGROUND_PIXEL (f
);
6747 #if 0 /* MAC/W32 TODO : Colormap support. */
6748 x_query_color (f
, &color
);
6750 bzero (&frame_background
, sizeof frame_background
);
6751 frame_background
.red
= RED_FROM_ULONG (color
);
6752 frame_background
.green
= GREEN_FROM_ULONG (color
);
6753 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6756 fn_png_set_background (png_ptr
, &frame_background
,
6757 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6761 /* Update info structure. */
6762 fn_png_read_update_info (png_ptr
, info_ptr
);
6764 /* Get number of channels. Valid values are 1 for grayscale images
6765 and images with a palette, 2 for grayscale images with transparency
6766 information (alpha channel), 3 for RGB images, and 4 for RGB
6767 images with alpha channel, i.e. RGBA. If conversions above were
6768 sufficient we should only have 3 or 4 channels here. */
6769 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6770 xassert (channels
== 3 || channels
== 4);
6772 /* Number of bytes needed for one row of the image. */
6773 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6775 /* Allocate memory for the image. */
6776 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6777 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6778 for (i
= 0; i
< height
; ++i
)
6779 rows
[i
] = pixels
+ i
* row_bytes
;
6781 /* Read the entire image. */
6782 fn_png_read_image (png_ptr
, rows
);
6783 fn_png_read_end (png_ptr
, info_ptr
);
6790 /* Create the X image and pixmap. */
6791 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6795 /* Create an image and pixmap serving as mask if the PNG image
6796 contains an alpha channel. */
6799 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6800 &mask_img
, &img
->mask
))
6802 x_destroy_x_image (ximg
);
6803 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6804 img
->pixmap
= NO_PIXMAP
;
6808 /* Fill the X image and mask from PNG data. */
6809 init_color_table ();
6811 for (y
= 0; y
< height
; ++y
)
6813 png_byte
*p
= rows
[y
];
6815 for (x
= 0; x
< width
; ++x
)
6822 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6823 /* An alpha channel, aka mask channel, associates variable
6824 transparency with an image. Where other image formats
6825 support binary transparency---fully transparent or fully
6826 opaque---PNG allows up to 254 levels of partial transparency.
6827 The PNG library implements partial transparency by combining
6828 the image with a specified background color.
6830 I'm not sure how to handle this here nicely: because the
6831 background on which the image is displayed may change, for
6832 real alpha channel support, it would be necessary to create
6833 a new image for each possible background.
6835 What I'm doing now is that a mask is created if we have
6836 boolean transparency information. Otherwise I'm using
6837 the frame's background color to combine the image with. */
6842 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6848 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6849 /* Set IMG's background color from the PNG image, unless the user
6853 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6855 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6856 img
->background_valid
= 1;
6860 #ifdef COLOR_TABLE_SUPPORT
6861 /* Remember colors allocated for this image. */
6862 img
->colors
= colors_in_color_table (&img
->ncolors
);
6863 free_color_table ();
6864 #endif /* COLOR_TABLE_SUPPORT */
6867 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6872 img
->height
= height
;
6874 /* Maybe fill in the background field while we have ximg handy.
6875 Casting avoids a GCC warning. */
6876 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6878 /* Put the image into the pixmap, then free the X image and its buffer. */
6879 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6880 x_destroy_x_image (ximg
);
6882 /* Same for the mask. */
6885 /* Fill in the background_transparent field while we have the
6886 mask handy. Casting avoids a GCC warning. */
6887 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6889 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6890 x_destroy_x_image (mask_img
);
6897 #else /* HAVE_PNG */
6905 #if USE_MAC_IMAGE_IO
6906 return image_load_image_io (f
, img
, kUTTypePNG
);
6907 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6908 return image_load_quartz2d (f
, img
, 1);
6910 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6915 #endif /* !HAVE_PNG */
6919 /***********************************************************************
6921 ***********************************************************************/
6923 #if defined (HAVE_JPEG) || defined (MAC_OS)
6925 static int jpeg_image_p
P_ ((Lisp_Object object
));
6926 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6928 /* The symbol `jpeg' identifying images of this type. */
6932 /* Indices of image specification fields in gs_format, below. */
6934 enum jpeg_keyword_index
6943 JPEG_HEURISTIC_MASK
,
6949 /* Vector of image_keyword structures describing the format
6950 of valid user-defined image specifications. */
6952 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6954 {":type", IMAGE_SYMBOL_VALUE
, 1},
6955 {":data", IMAGE_STRING_VALUE
, 0},
6956 {":file", IMAGE_STRING_VALUE
, 0},
6957 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6958 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6959 {":relief", IMAGE_INTEGER_VALUE
, 0},
6960 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6961 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6962 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6963 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6966 /* Structure describing the image type `jpeg'. */
6968 static struct image_type jpeg_type
=
6977 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6980 jpeg_image_p (object
)
6983 struct image_keyword fmt
[JPEG_LAST
];
6985 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6987 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6990 /* Must specify either the :data or :file keyword. */
6991 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6994 #endif /* HAVE_JPEG || MAC_OS */
6998 /* Work around a warning about HAVE_STDLIB_H being redefined in
7000 #ifdef HAVE_STDLIB_H
7001 #define HAVE_STDLIB_H_1
7002 #undef HAVE_STDLIB_H
7003 #endif /* HAVE_STLIB_H */
7005 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
7006 /* In older releases of the jpeg library, jpeglib.h will define boolean
7007 differently depending on __WIN32__, so make sure it is defined. */
7011 #include <jpeglib.h>
7015 #ifdef HAVE_STLIB_H_1
7016 #define HAVE_STDLIB_H 1
7021 /* JPEG library details. */
7022 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
7023 DEF_IMGLIB_FN (jpeg_start_decompress
);
7024 DEF_IMGLIB_FN (jpeg_finish_decompress
);
7025 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
7026 DEF_IMGLIB_FN (jpeg_read_header
);
7027 DEF_IMGLIB_FN (jpeg_read_scanlines
);
7028 DEF_IMGLIB_FN (jpeg_std_error
);
7029 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
7032 init_jpeg_functions (Lisp_Object libraries
)
7036 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
7039 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
7040 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
7041 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
7042 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
7043 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
7044 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
7045 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
7046 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
7050 /* Wrapper since we can't directly assign the function pointer
7051 to another function pointer that was declared more completely easily. */
7053 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
7054 j_decompress_ptr cinfo
;
7057 return fn_jpeg_resync_to_restart (cinfo
, desired
);
7062 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7063 #define fn_jpeg_start_decompress jpeg_start_decompress
7064 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7065 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7066 #define fn_jpeg_read_header jpeg_read_header
7067 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7068 #define fn_jpeg_std_error jpeg_std_error
7069 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7071 #endif /* HAVE_NTGUI */
7073 struct my_jpeg_error_mgr
7075 struct jpeg_error_mgr pub
;
7076 jmp_buf setjmp_buffer
;
7081 my_error_exit (cinfo
)
7084 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
7085 longjmp (mgr
->setjmp_buffer
, 1);
7089 /* Init source method for JPEG data source manager. Called by
7090 jpeg_read_header() before any data is actually read. See
7091 libjpeg.doc from the JPEG lib distribution. */
7094 our_common_init_source (cinfo
)
7095 j_decompress_ptr cinfo
;
7100 /* Method to terminate data source. Called by
7101 jpeg_finish_decompress() after all data has been processed. */
7104 our_common_term_source (cinfo
)
7105 j_decompress_ptr cinfo
;
7110 /* Fill input buffer method for JPEG data source manager. Called
7111 whenever more data is needed. We read the whole image in one step,
7112 so this only adds a fake end of input marker at the end. */
7114 static JOCTET our_memory_buffer
[2];
7117 our_memory_fill_input_buffer (cinfo
)
7118 j_decompress_ptr cinfo
;
7120 /* Insert a fake EOI marker. */
7121 struct jpeg_source_mgr
*src
= cinfo
->src
;
7123 our_memory_buffer
[0] = (JOCTET
) 0xFF;
7124 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
7126 src
->next_input_byte
= our_memory_buffer
;
7127 src
->bytes_in_buffer
= 2;
7132 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7133 is the JPEG data source manager. */
7136 our_memory_skip_input_data (cinfo
, num_bytes
)
7137 j_decompress_ptr cinfo
;
7140 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7144 if (num_bytes
> src
->bytes_in_buffer
)
7145 ERREXIT (cinfo
, JERR_INPUT_EOF
);
7147 src
->bytes_in_buffer
-= num_bytes
;
7148 src
->next_input_byte
+= num_bytes
;
7153 /* Set up the JPEG lib for reading an image from DATA which contains
7154 LEN bytes. CINFO is the decompression info structure created for
7155 reading the image. */
7158 jpeg_memory_src (cinfo
, data
, len
)
7159 j_decompress_ptr cinfo
;
7163 struct jpeg_source_mgr
*src
;
7165 if (cinfo
->src
== NULL
)
7167 /* First time for this JPEG object? */
7168 cinfo
->src
= (struct jpeg_source_mgr
*)
7169 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7170 sizeof (struct jpeg_source_mgr
));
7171 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7172 src
->next_input_byte
= data
;
7175 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7176 src
->init_source
= our_common_init_source
;
7177 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
7178 src
->skip_input_data
= our_memory_skip_input_data
;
7179 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7180 src
->term_source
= our_common_term_source
;
7181 src
->bytes_in_buffer
= len
;
7182 src
->next_input_byte
= data
;
7186 struct jpeg_stdio_mgr
7188 struct jpeg_source_mgr mgr
;
7195 /* Size of buffer to read JPEG from file.
7196 Not too big, as we want to use alloc_small. */
7197 #define JPEG_STDIO_BUFFER_SIZE 8192
7200 /* Fill input buffer method for JPEG data source manager. Called
7201 whenever more data is needed. The data is read from a FILE *. */
7204 our_stdio_fill_input_buffer (cinfo
)
7205 j_decompress_ptr cinfo
;
7207 struct jpeg_stdio_mgr
*src
;
7209 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7214 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
7216 src
->mgr
.bytes_in_buffer
= bytes
;
7219 WARNMS (cinfo
, JWRN_JPEG_EOF
);
7221 src
->buffer
[0] = (JOCTET
) 0xFF;
7222 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
7223 src
->mgr
.bytes_in_buffer
= 2;
7225 src
->mgr
.next_input_byte
= src
->buffer
;
7232 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7233 is the JPEG data source manager. */
7236 our_stdio_skip_input_data (cinfo
, num_bytes
)
7237 j_decompress_ptr cinfo
;
7240 struct jpeg_stdio_mgr
*src
;
7241 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7243 while (num_bytes
> 0 && !src
->finished
)
7245 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
7247 src
->mgr
.bytes_in_buffer
-= num_bytes
;
7248 src
->mgr
.next_input_byte
+= num_bytes
;
7253 num_bytes
-= src
->mgr
.bytes_in_buffer
;
7254 src
->mgr
.bytes_in_buffer
= 0;
7255 src
->mgr
.next_input_byte
= NULL
;
7257 our_stdio_fill_input_buffer (cinfo
);
7263 /* Set up the JPEG lib for reading an image from a FILE *.
7264 CINFO is the decompression info structure created for
7265 reading the image. */
7268 jpeg_file_src (cinfo
, fp
)
7269 j_decompress_ptr cinfo
;
7272 struct jpeg_stdio_mgr
*src
;
7274 if (cinfo
->src
!= NULL
)
7275 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7278 /* First time for this JPEG object? */
7279 cinfo
->src
= (struct jpeg_source_mgr
*)
7280 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7281 sizeof (struct jpeg_stdio_mgr
));
7282 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7283 src
->buffer
= (JOCTET
*)
7284 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7285 JPEG_STDIO_BUFFER_SIZE
);
7290 src
->mgr
.init_source
= our_common_init_source
;
7291 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
7292 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
7293 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7294 src
->mgr
.term_source
= our_common_term_source
;
7295 src
->mgr
.bytes_in_buffer
= 0;
7296 src
->mgr
.next_input_byte
= NULL
;
7300 /* Load image IMG for use on frame F. Patterned after example.c
7301 from the JPEG lib. */
7308 struct jpeg_decompress_struct cinfo
;
7309 struct my_jpeg_error_mgr mgr
;
7310 Lisp_Object file
, specified_file
;
7311 Lisp_Object specified_data
;
7312 FILE * volatile fp
= NULL
;
7314 int row_stride
, x
, y
;
7315 XImagePtr ximg
= NULL
;
7317 unsigned long *colors
;
7319 struct gcpro gcpro1
;
7321 /* Open the JPEG file. */
7322 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7323 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7327 if (NILP (specified_data
))
7329 file
= x_find_image_file (specified_file
);
7330 if (!STRINGP (file
))
7332 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7337 fp
= fopen (SDATA (file
), "rb");
7340 image_error ("Cannot open `%s'", file
, Qnil
);
7346 /* Customize libjpeg's error handling to call my_error_exit when an
7347 error is detected. This function will perform a longjmp.
7348 Casting return value avoids a GCC warning on W32. */
7349 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7350 mgr
.pub
.error_exit
= my_error_exit
;
7352 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7356 /* Called from my_error_exit. Display a JPEG error. */
7357 char buffer
[JMSG_LENGTH_MAX
];
7358 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7359 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7360 build_string (buffer
));
7363 /* Close the input file and destroy the JPEG object. */
7365 fclose ((FILE *) fp
);
7366 fn_jpeg_destroy_decompress (&cinfo
);
7368 /* If we already have an XImage, free that. */
7369 x_destroy_x_image (ximg
);
7371 /* Free pixmap and colors. */
7372 x_clear_image (f
, img
);
7378 /* Create the JPEG decompression object. Let it read from fp.
7379 Read the JPEG image header. */
7380 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7382 if (NILP (specified_data
))
7383 jpeg_file_src (&cinfo
, (FILE *) fp
);
7385 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7386 SBYTES (specified_data
));
7388 fn_jpeg_read_header (&cinfo
, 1);
7390 /* Customize decompression so that color quantization will be used.
7391 Start decompression. */
7392 cinfo
.quantize_colors
= 1;
7393 fn_jpeg_start_decompress (&cinfo
);
7394 width
= img
->width
= cinfo
.output_width
;
7395 height
= img
->height
= cinfo
.output_height
;
7397 if (!check_image_size (f
, width
, height
))
7399 image_error ("Invalid image size", Qnil
, Qnil
);
7400 longjmp (mgr
.setjmp_buffer
, 2);
7403 /* Create X image and pixmap. */
7404 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7405 longjmp (mgr
.setjmp_buffer
, 2);
7407 /* Allocate colors. When color quantization is used,
7408 cinfo.actual_number_of_colors has been set with the number of
7409 colors generated, and cinfo.colormap is a two-dimensional array
7410 of color indices in the range 0..cinfo.actual_number_of_colors.
7411 No more than 255 colors will be generated. */
7415 if (cinfo
.out_color_components
> 2)
7416 ir
= 0, ig
= 1, ib
= 2;
7417 else if (cinfo
.out_color_components
> 1)
7418 ir
= 0, ig
= 1, ib
= 0;
7420 ir
= 0, ig
= 0, ib
= 0;
7422 /* Use the color table mechanism because it handles colors that
7423 cannot be allocated nicely. Such colors will be replaced with
7424 a default color, and we don't have to care about which colors
7425 can be freed safely, and which can't. */
7426 init_color_table ();
7427 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7430 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7432 /* Multiply RGB values with 255 because X expects RGB values
7433 in the range 0..0xffff. */
7434 int r
= cinfo
.colormap
[ir
][i
] << 8;
7435 int g
= cinfo
.colormap
[ig
][i
] << 8;
7436 int b
= cinfo
.colormap
[ib
][i
] << 8;
7437 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7440 #ifdef COLOR_TABLE_SUPPORT
7441 /* Remember those colors actually allocated. */
7442 img
->colors
= colors_in_color_table (&img
->ncolors
);
7443 free_color_table ();
7444 #endif /* COLOR_TABLE_SUPPORT */
7448 row_stride
= width
* cinfo
.output_components
;
7449 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7451 for (y
= 0; y
< height
; ++y
)
7453 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7454 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7455 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7459 fn_jpeg_finish_decompress (&cinfo
);
7460 fn_jpeg_destroy_decompress (&cinfo
);
7462 fclose ((FILE *) fp
);
7464 /* Maybe fill in the background field while we have ximg handy. */
7465 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7466 /* Casting avoids a GCC warning. */
7467 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7469 /* Put the image into the pixmap. */
7470 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7471 x_destroy_x_image (ximg
);
7476 #else /* HAVE_JPEG */
7484 #if USE_MAC_IMAGE_IO
7485 return image_load_image_io (f
, img
, kUTTypeJPEG
);
7486 #elif defined (MAC_OSX)
7487 return image_load_quartz2d (f
, img
, 0);
7489 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7494 #endif /* !HAVE_JPEG */
7498 /***********************************************************************
7500 ***********************************************************************/
7502 #if defined (HAVE_TIFF) || defined (MAC_OS)
7504 static int tiff_image_p
P_ ((Lisp_Object object
));
7505 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7507 /* The symbol `tiff' identifying images of this type. */
7511 /* Indices of image specification fields in tiff_format, below. */
7513 enum tiff_keyword_index
7522 TIFF_HEURISTIC_MASK
,
7528 /* Vector of image_keyword structures describing the format
7529 of valid user-defined image specifications. */
7531 static struct image_keyword tiff_format
[TIFF_LAST
] =
7533 {":type", IMAGE_SYMBOL_VALUE
, 1},
7534 {":data", IMAGE_STRING_VALUE
, 0},
7535 {":file", IMAGE_STRING_VALUE
, 0},
7536 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7537 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7538 {":relief", IMAGE_INTEGER_VALUE
, 0},
7539 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7540 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7541 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7542 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7545 /* Structure describing the image type `tiff'. */
7547 static struct image_type tiff_type
=
7556 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7559 tiff_image_p (object
)
7562 struct image_keyword fmt
[TIFF_LAST
];
7563 bcopy (tiff_format
, fmt
, sizeof fmt
);
7565 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7568 /* Must specify either the :data or :file keyword. */
7569 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7572 #endif /* HAVE_TIFF || MAC_OS */
7580 /* TIFF library details. */
7581 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7582 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7583 DEF_IMGLIB_FN (TIFFOpen
);
7584 DEF_IMGLIB_FN (TIFFClientOpen
);
7585 DEF_IMGLIB_FN (TIFFGetField
);
7586 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7587 DEF_IMGLIB_FN (TIFFClose
);
7590 init_tiff_functions (Lisp_Object libraries
)
7594 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7597 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7598 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7599 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7600 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7601 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7602 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7603 LOAD_IMGLIB_FN (library
, TIFFClose
);
7609 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7610 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7611 #define fn_TIFFOpen TIFFOpen
7612 #define fn_TIFFClientOpen TIFFClientOpen
7613 #define fn_TIFFGetField TIFFGetField
7614 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7615 #define fn_TIFFClose TIFFClose
7617 #endif /* HAVE_NTGUI */
7620 /* Reading from a memory buffer for TIFF images Based on the PNG
7621 memory source, but we have to provide a lot of extra functions.
7624 We really only need to implement read and seek, but I am not
7625 convinced that the TIFF library is smart enough not to destroy
7626 itself if we only hand it the function pointers we need to
7631 unsigned char *bytes
;
7638 tiff_read_from_memory (data
, buf
, size
)
7643 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7645 if (size
> src
->len
- src
->index
)
7647 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7653 tiff_write_from_memory (data
, buf
, size
)
7662 tiff_seek_in_memory (data
, off
, whence
)
7667 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7672 case SEEK_SET
: /* Go from beginning of source. */
7676 case SEEK_END
: /* Go from end of source. */
7677 idx
= src
->len
+ off
;
7680 case SEEK_CUR
: /* Go from current position. */
7681 idx
= src
->index
+ off
;
7684 default: /* Invalid `whence'. */
7688 if (idx
> src
->len
|| idx
< 0)
7696 tiff_close_memory (data
)
7704 tiff_mmap_memory (data
, pbase
, psize
)
7709 /* It is already _IN_ memory. */
7714 tiff_unmap_memory (data
, base
, size
)
7719 /* We don't need to do this. */
7723 tiff_size_of_memory (data
)
7726 return ((tiff_memory_source
*) data
)->len
;
7731 tiff_error_handler (title
, format
, ap
)
7732 const char *title
, *format
;
7738 len
= sprintf (buf
, "TIFF error: %s ", title
);
7739 vsprintf (buf
+ len
, format
, ap
);
7740 add_to_log (buf
, Qnil
, Qnil
);
7745 tiff_warning_handler (title
, format
, ap
)
7746 const char *title
, *format
;
7752 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7753 vsprintf (buf
+ len
, format
, ap
);
7754 add_to_log (buf
, Qnil
, Qnil
);
7758 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7766 Lisp_Object file
, specified_file
;
7767 Lisp_Object specified_data
;
7769 int width
, height
, x
, y
;
7773 struct gcpro gcpro1
;
7774 tiff_memory_source memsrc
;
7776 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7777 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7781 fn_TIFFSetErrorHandler (tiff_error_handler
);
7782 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7784 if (NILP (specified_data
))
7786 /* Read from a file */
7787 file
= x_find_image_file (specified_file
);
7788 if (!STRINGP (file
))
7790 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7795 /* Try to open the image file. Casting return value avoids a
7796 GCC warning on W32. */
7797 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7800 image_error ("Cannot open `%s'", file
, Qnil
);
7807 /* Memory source! */
7808 memsrc
.bytes
= SDATA (specified_data
);
7809 memsrc
.len
= SBYTES (specified_data
);
7812 /* Casting return value avoids a GCC warning on W32. */
7813 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7814 (TIFFReadWriteProc
) tiff_read_from_memory
,
7815 (TIFFReadWriteProc
) tiff_write_from_memory
,
7816 tiff_seek_in_memory
,
7818 tiff_size_of_memory
,
7824 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7830 /* Get width and height of the image, and allocate a raster buffer
7831 of width x height 32-bit values. */
7832 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7833 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7835 if (!check_image_size (f
, width
, height
))
7837 image_error ("Invalid image size", Qnil
, Qnil
);
7842 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7844 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7845 fn_TIFFClose (tiff
);
7848 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7854 /* Create the X image and pixmap. */
7855 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7862 /* Initialize the color table. */
7863 init_color_table ();
7865 /* Process the pixel raster. Origin is in the lower-left corner. */
7866 for (y
= 0; y
< height
; ++y
)
7868 uint32
*row
= buf
+ y
* width
;
7870 for (x
= 0; x
< width
; ++x
)
7872 uint32 abgr
= row
[x
];
7873 int r
= TIFFGetR (abgr
) << 8;
7874 int g
= TIFFGetG (abgr
) << 8;
7875 int b
= TIFFGetB (abgr
) << 8;
7876 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7880 #ifdef COLOR_TABLE_SUPPORT
7881 /* Remember the colors allocated for the image. Free the color table. */
7882 img
->colors
= colors_in_color_table (&img
->ncolors
);
7883 free_color_table ();
7884 #endif /* COLOR_TABLE_SUPPORT */
7887 img
->height
= height
;
7889 /* Maybe fill in the background field while we have ximg handy. */
7890 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7891 /* Casting avoids a GCC warning on W32. */
7892 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7894 /* Put the image into the pixmap, then free the X image and its buffer. */
7895 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7896 x_destroy_x_image (ximg
);
7903 #else /* HAVE_TIFF */
7911 #if USE_MAC_IMAGE_IO
7912 return image_load_image_io (f
, img
, kUTTypeTIFF
);
7914 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7919 #endif /* !HAVE_TIFF */
7923 /***********************************************************************
7925 ***********************************************************************/
7927 #if defined (HAVE_GIF) || defined (MAC_OS)
7929 static int gif_image_p
P_ ((Lisp_Object object
));
7930 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7931 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7933 /* The symbol `gif' identifying images of this type. */
7937 /* Indices of image specification fields in gif_format, below. */
7939 enum gif_keyword_index
7955 /* Vector of image_keyword structures describing the format
7956 of valid user-defined image specifications. */
7958 static struct image_keyword gif_format
[GIF_LAST
] =
7960 {":type", IMAGE_SYMBOL_VALUE
, 1},
7961 {":data", IMAGE_STRING_VALUE
, 0},
7962 {":file", IMAGE_STRING_VALUE
, 0},
7963 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7964 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7965 {":relief", IMAGE_INTEGER_VALUE
, 0},
7966 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7967 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7968 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7969 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7970 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7973 /* Structure describing the image type `gif'. */
7975 static struct image_type gif_type
=
7984 /* Free X resources of GIF image IMG which is used on frame F. */
7987 gif_clear_image (f
, img
)
7991 /* IMG->data.ptr_val may contain extension data. */
7992 img
->data
.lisp_val
= Qnil
;
7993 x_clear_image (f
, img
);
7996 /* Return non-zero if OBJECT is a valid GIF image specification. */
7999 gif_image_p (object
)
8002 struct image_keyword fmt
[GIF_LAST
];
8003 bcopy (gif_format
, fmt
, sizeof fmt
);
8005 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
8008 /* Must specify either the :data or :file keyword. */
8009 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
8012 #endif /* HAVE_GIF || MAC_OS */
8016 #if defined (HAVE_NTGUI) || defined (MAC_OS)
8017 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
8018 Undefine before redefining to avoid a preprocessor warning. */
8022 /* avoid conflict with QuickdrawText.h */
8023 #define DrawText gif_DrawText
8024 #include <gif_lib.h>
8027 #else /* HAVE_NTGUI || MAC_OS */
8029 #include <gif_lib.h>
8031 #endif /* HAVE_NTGUI || MAC_OS */
8036 /* GIF library details. */
8037 DEF_IMGLIB_FN (DGifCloseFile
);
8038 DEF_IMGLIB_FN (DGifSlurp
);
8039 DEF_IMGLIB_FN (DGifOpen
);
8040 DEF_IMGLIB_FN (DGifOpenFileName
);
8043 init_gif_functions (Lisp_Object libraries
)
8047 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
8050 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
8051 LOAD_IMGLIB_FN (library
, DGifSlurp
);
8052 LOAD_IMGLIB_FN (library
, DGifOpen
);
8053 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
8059 #define fn_DGifCloseFile DGifCloseFile
8060 #define fn_DGifSlurp DGifSlurp
8061 #define fn_DGifOpen DGifOpen
8062 #define fn_DGifOpenFileName DGifOpenFileName
8064 #endif /* HAVE_NTGUI */
8066 /* Reading a GIF image from memory
8067 Based on the PNG memory stuff to a certain extent. */
8071 unsigned char *bytes
;
8077 /* Make the current memory source available to gif_read_from_memory.
8078 It's done this way because not all versions of libungif support
8079 a UserData field in the GifFileType structure. */
8080 static gif_memory_source
*current_gif_memory_src
;
8083 gif_read_from_memory (file
, buf
, len
)
8088 gif_memory_source
*src
= current_gif_memory_src
;
8090 if (len
> src
->len
- src
->index
)
8093 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8099 /* Load GIF image IMG for use on frame F. Value is non-zero if
8102 static int interlace_start
[] = {0, 4, 2, 1};
8103 static int interlace_increment
[] = {8, 8, 4, 2};
8110 Lisp_Object file
, specified_file
;
8111 Lisp_Object specified_data
;
8112 int rc
, width
, height
, x
, y
, i
;
8114 ColorMapObject
*gif_color_map
;
8115 unsigned long pixel_colors
[256];
8117 struct gcpro gcpro1
;
8119 int ino
, image_height
, image_width
;
8120 gif_memory_source memsrc
;
8121 unsigned char *raster
;
8123 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8124 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8128 if (NILP (specified_data
))
8130 file
= x_find_image_file (specified_file
);
8131 if (!STRINGP (file
))
8133 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8138 /* Open the GIF file. Casting return value avoids a GCC warning
8140 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
8143 image_error ("Cannot open `%s'", file
, Qnil
);
8150 /* Read from memory! */
8151 current_gif_memory_src
= &memsrc
;
8152 memsrc
.bytes
= SDATA (specified_data
);
8153 memsrc
.len
= SBYTES (specified_data
);
8156 /* Casting return value avoids a GCC warning on W32. */
8157 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
8160 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
8166 /* Before reading entire contents, check the declared image size. */
8167 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
8169 image_error ("Invalid image size", Qnil
, Qnil
);
8170 fn_DGifCloseFile (gif
);
8175 /* Read entire contents. */
8176 rc
= fn_DGifSlurp (gif
);
8177 if (rc
== GIF_ERROR
)
8179 image_error ("Error reading `%s'", img
->spec
, Qnil
);
8180 fn_DGifCloseFile (gif
);
8185 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8186 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8187 if (ino
>= gif
->ImageCount
)
8189 image_error ("Invalid image number `%s' in image `%s'",
8191 fn_DGifCloseFile (gif
);
8196 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
8197 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
8198 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8199 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
8200 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8201 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
8203 width
= img
->width
= max (gif
->SWidth
,
8204 max (gif
->Image
.Left
+ gif
->Image
.Width
,
8205 img
->corners
[RIGHT_CORNER
]));
8206 height
= img
->height
= max (gif
->SHeight
,
8207 max (gif
->Image
.Top
+ gif
->Image
.Height
,
8208 img
->corners
[BOT_CORNER
]));
8210 if (!check_image_size (f
, width
, height
))
8212 image_error ("Invalid image size", Qnil
, Qnil
);
8213 fn_DGifCloseFile (gif
);
8218 /* Create the X image and pixmap. */
8219 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8221 fn_DGifCloseFile (gif
);
8226 /* Allocate colors. */
8227 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8229 gif_color_map
= gif
->SColorMap
;
8230 init_color_table ();
8231 bzero (pixel_colors
, sizeof pixel_colors
);
8234 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8236 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8237 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8238 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8239 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8242 #ifdef COLOR_TABLE_SUPPORT
8243 img
->colors
= colors_in_color_table (&img
->ncolors
);
8244 free_color_table ();
8245 #endif /* COLOR_TABLE_SUPPORT */
8247 /* Clear the part of the screen image that are not covered by
8248 the image from the GIF file. Full animated GIF support
8249 requires more than can be done here (see the gif89 spec,
8250 disposal methods). Let's simply assume that the part
8251 not covered by a sub-image is in the frame's background color. */
8252 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
8253 for (x
= 0; x
< width
; ++x
)
8254 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8256 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
8257 for (x
= 0; x
< width
; ++x
)
8258 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8260 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
8262 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
8263 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8264 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
8265 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8268 /* Read the GIF image into the X image. We use a local variable
8269 `raster' here because RasterBits below is a char *, and invites
8270 problems with bytes >= 0x80. */
8271 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
8273 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8276 int row
= interlace_start
[0];
8280 for (y
= 0; y
< image_height
; y
++)
8282 if (row
>= image_height
)
8284 row
= interlace_start
[++pass
];
8285 while (row
>= image_height
)
8286 row
= interlace_start
[++pass
];
8289 for (x
= 0; x
< image_width
; x
++)
8291 int i
= raster
[(y
* image_width
) + x
];
8292 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8293 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8296 row
+= interlace_increment
[pass
];
8301 for (y
= 0; y
< image_height
; ++y
)
8302 for (x
= 0; x
< image_width
; ++x
)
8304 int i
= raster
[y
* image_width
+ x
];
8305 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8306 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8310 /* Save GIF image extension data for `image-extension-data'.
8311 Format is (count IMAGES FUNCTION "BYTES" ...). */
8312 img
->data
.lisp_val
= Qnil
;
8313 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
8315 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
8316 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
8317 /* Append (... FUNCTION "BYTES") */
8318 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
8319 Fcons (make_number (ext
->Function
),
8320 img
->data
.lisp_val
));
8321 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
8323 if (gif
->ImageCount
> 1)
8324 img
->data
.lisp_val
= Fcons (Qcount
,
8325 Fcons (make_number (gif
->ImageCount
),
8326 img
->data
.lisp_val
));
8328 fn_DGifCloseFile (gif
);
8330 /* Maybe fill in the background field while we have ximg handy. */
8331 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8332 /* Casting avoids a GCC warning. */
8333 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8335 /* Put the image into the pixmap, then free the X image and its buffer. */
8336 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8337 x_destroy_x_image (ximg
);
8343 #else /* !HAVE_GIF */
8351 #if USE_MAC_IMAGE_IO
8352 return image_load_image_io (f
, img
, kUTTypeGIF
);
8353 #else /* !USE_MAC_IMAGE_IO */
8354 Lisp_Object specified_file
, file
;
8355 Lisp_Object specified_data
;
8357 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8365 Lisp_Object specified_bg
;
8370 TimeScale time_scale
;
8371 TimeValue time
, duration
;
8376 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8377 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8379 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8382 if (NILP (specified_data
))
8384 /* Read from a file */
8388 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8392 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8397 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8398 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8402 if (!graphic_p
&& !movie_p
)
8404 if (prefer_graphic_p
)
8405 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8406 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8409 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8410 CloseMovieFile (refnum
);
8413 image_error ("Error reading `%s'", file
, Qnil
);
8419 /* Memory source! */
8421 long file_type_atom
[3];
8423 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8426 image_error ("Cannot allocate data handle for `%s'",
8431 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8432 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8433 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8434 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8437 err
= PtrAndHand ("\p", dref
, 1);
8439 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8442 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8445 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8446 &movie_p
, &prefer_graphic_p
, 0);
8450 if (!graphic_p
&& !movie_p
)
8452 if (prefer_graphic_p
)
8456 DisposeHandle (dref
);
8457 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8461 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8462 HandleDataHandlerSubType
);
8463 DisposeHandle (dref
);
8468 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8469 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8470 track
= GetMovieIndTrack (movie
, 1);
8471 media
= GetTrackMedia (track
);
8472 nsamples
= GetMediaSampleCount (media
);
8473 if (ino
>= nsamples
)
8475 image_error ("Invalid image number `%s' in image `%s'",
8479 time_scale
= GetMediaTimeScale (media
);
8481 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8482 if (!STRINGP (specified_bg
)
8483 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8485 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8486 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8487 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8488 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8490 GetMovieBox (movie
, &rect
);
8491 width
= img
->width
= rect
.right
- rect
.left
;
8492 height
= img
->height
= rect
.bottom
- rect
.top
;
8493 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8496 GetGWorld (&old_port
, &old_gdh
);
8497 SetGWorld (ximg
, NULL
);
8498 bg_color
.red
= color
.red
;
8499 bg_color
.green
= color
.green
;
8500 bg_color
.blue
= color
.blue
;
8501 RGBBackColor (&bg_color
);
8502 SetGWorld (old_port
, old_gdh
);
8503 SetMovieActive (movie
, 1);
8504 SetMovieGWorld (movie
, ximg
, NULL
);
8505 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8506 SetMovieTimeValue (movie
, time
);
8507 MoviesTask (movie
, 0L);
8508 DisposeTrackMedia (media
);
8509 DisposeMovieTrack (track
);
8510 DisposeMovie (movie
);
8514 /* Save GIF image extension data for `image-extension-data'.
8515 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8517 Lisp_Object gce
= make_uninit_string (4);
8518 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8520 /* Fill the delay time field. */
8521 SSET (gce
, 1, centisec
& 0xff);
8522 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8523 /* We don't know about other fields. */
8527 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8528 make_number (0xf9), gce
);
8531 /* Maybe fill in the background field while we have ximg handy. */
8532 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8533 IMAGE_BACKGROUND (img
, f
, ximg
);
8535 /* Put the image into the pixmap. */
8536 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8537 x_destroy_x_image (ximg
);
8541 image_error ("Cannot open `%s'", file
, Qnil
);
8544 DisposeTrackMedia (media
);
8546 DisposeMovieTrack (track
);
8548 DisposeMovie (movie
);
8552 #endif /* !USE_MAC_IMAGE_IO */
8556 #endif /* HAVE_GIF */
8560 /***********************************************************************
8562 ***********************************************************************/
8564 #if defined (HAVE_RSVG)
8566 /* Function prototypes. */
8568 static int svg_image_p
P_ ((Lisp_Object object
));
8569 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
8571 static int svg_load_image
P_ ((struct frame
*, struct image
*,
8572 unsigned char *, unsigned int));
8574 /* The symbol `svg' identifying images of this type. */
8578 /* Indices of image specification fields in svg_format, below. */
8580 enum svg_keyword_index
8595 /* Vector of image_keyword structures describing the format
8596 of valid user-defined image specifications. */
8598 static struct image_keyword svg_format
[SVG_LAST
] =
8600 {":type", IMAGE_SYMBOL_VALUE
, 1},
8601 {":data", IMAGE_STRING_VALUE
, 0},
8602 {":file", IMAGE_STRING_VALUE
, 0},
8603 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8604 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8605 {":relief", IMAGE_INTEGER_VALUE
, 0},
8606 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8607 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8608 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8609 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8612 /* Structure describing the image type `svg'. Its the same type of
8613 structure defined for all image formats, handled by emacs image
8614 functions. See struct image_type in dispextern.h. */
8616 static struct image_type svg_type
=
8618 /* An identifier showing that this is an image structure for the SVG format. */
8620 /* Handle to a function that can be used to identify a SVG file. */
8622 /* Handle to function used to load a SVG file. */
8624 /* Handle to function to free sresources for SVG. */
8626 /* An internal field to link to the next image type in a list of
8627 image types, will be filled in when registering the format. */
8632 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8633 this by calling parse_image_spec and supplying the keywords that
8634 identify the SVG format. */
8637 svg_image_p (object
)
8640 struct image_keyword fmt
[SVG_LAST
];
8641 bcopy (svg_format
, fmt
, sizeof fmt
);
8643 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
8646 /* Must specify either the :data or :file keyword. */
8647 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
8650 #include <librsvg/rsvg.h>
8654 /* SVG library functions. */
8655 DEF_IMGLIB_FN (rsvg_handle_new
);
8656 DEF_IMGLIB_FN (rsvg_handle_set_size_callback
);
8657 DEF_IMGLIB_FN (rsvg_handle_write
);
8658 DEF_IMGLIB_FN (rsvg_handle_close
);
8659 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
8660 DEF_IMGLIB_FN (rsvg_handle_free
);
8662 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
8663 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
8664 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
8665 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
8666 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
8667 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
8668 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
8669 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
8671 DEF_IMGLIB_FN (g_type_init
);
8672 DEF_IMGLIB_FN (g_object_unref
);
8673 DEF_IMGLIB_FN (g_error_free
);
8675 Lisp_Object Qgdk_pixbuf
, Qglib
;
8678 init_svg_functions (Lisp_Object libraries
)
8680 HMODULE library
, gdklib
, glib
;
8682 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
8683 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
8684 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
8687 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
8688 LOAD_IMGLIB_FN (library
, rsvg_handle_set_size_callback
);
8689 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
8690 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
8691 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
8692 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
8694 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
8695 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
8696 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
8697 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
8698 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
8699 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
8700 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
8701 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
8703 LOAD_IMGLIB_FN (glib
, g_type_init
);
8704 LOAD_IMGLIB_FN (glib
, g_object_unref
);
8705 LOAD_IMGLIB_FN (glib
, g_error_free
);
8710 /* The following aliases for library functions allow dynamic loading
8711 to be used on some platforms. */
8712 #define fn_rsvg_handle_new rsvg_handle_new
8713 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8714 #define fn_rsvg_handle_write rsvg_handle_write
8715 #define fn_rsvg_handle_close rsvg_handle_close
8716 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8717 #define fn_rsvg_handle_free rsvg_handle_free
8719 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8720 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8721 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8722 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8723 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8724 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8725 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8726 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8728 #define fn_g_type_init g_type_init
8729 #define fn_g_object_unref g_object_unref
8730 #define fn_g_error_free g_error_free
8731 #endif /* !HAVE_NTGUI */
8733 /* Load SVG image IMG for use on frame F. Value is non-zero if
8734 successful. this function will go into the svg_type structure, and
8735 the prototype thus needs to be compatible with that structure. */
8743 Lisp_Object file_name
;
8745 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8746 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8747 if (STRINGP (file_name
))
8750 unsigned char *contents
;
8752 struct gcpro gcpro1
;
8754 file
= x_find_image_file (file_name
);
8756 if (!STRINGP (file
))
8758 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
8763 /* Read the entire file into memory. */
8764 contents
= slurp_file (SDATA (file
), &size
);
8765 if (contents
== NULL
)
8767 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8771 /* If the file was slurped into memory properly, parse it. */
8772 success_p
= svg_load_image (f
, img
, contents
, size
);
8776 /* Else its not a file, its a lisp object. Load the image from a
8777 lisp object rather than a file. */
8782 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8783 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8789 /* svg_load_image is a helper function for svg_load, which does the
8790 actual loading given contents and size, apart from frame and image
8791 structures, passed from svg_load.
8793 Uses librsvg to do most of the image processing.
8795 Returns non-zero when successful. */
8797 svg_load_image (f
, img
, contents
, size
)
8798 /* Pointer to emacs frame structure. */
8800 /* Pointer to emacs image structure. */
8802 /* String containing the SVG XML data to be parsed. */
8803 unsigned char *contents
;
8804 /* Size of data in bytes. */
8807 RsvgHandle
*rsvg_handle
;
8808 GError
*error
= NULL
;
8812 const guint8
*pixels
;
8815 Lisp_Object specified_bg
;
8820 /* g_type_init is a glib function that must be called prior to using
8821 gnome type library functions. */
8823 /* Make a handle to a new rsvg object. */
8824 rsvg_handle
= fn_rsvg_handle_new ();
8826 /* Parse the contents argument and fill in the rsvg_handle. */
8827 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8831 /* The parsing is complete, rsvg_handle is ready to used, close it
8832 for further writes. */
8833 fn_rsvg_handle_close (rsvg_handle
, &error
);
8836 /* We can now get a valid pixel buffer from the svg file, if all
8838 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8841 /* Extract some meta data from the svg handle. */
8842 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8843 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8844 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8845 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8847 /* Validate the svg meta data. */
8848 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8849 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8850 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8851 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8853 /* Try to create a x pixmap to hold the svg pixmap. */
8854 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8856 fn_g_object_unref (pixbuf
);
8860 init_color_table ();
8862 /* Handle alpha channel by combining the image with a background
8864 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8865 if (STRINGP (specified_bg
)
8866 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8868 background
.red
>>= 8;
8869 background
.green
>>= 8;
8870 background
.blue
>>= 8;
8874 #ifdef HAVE_X_WINDOWS
8875 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8876 x_query_color (f
, &background
);
8878 /* SVG pixmaps specify transparency in the last byte, so right
8879 shift 8 bits to get rid of it, since emacs doesn't support
8881 background
.red
>>= 8;
8882 background
.green
>>= 8;
8883 background
.blue
>>= 8;
8884 #elif defined (MAC_OS)
8885 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8886 background
.red
= RED_FROM_ULONG (background
.pixel
);
8887 background
.green
= GREEN_FROM_ULONG (background
.pixel
);
8888 background
.blue
= BLUE_FROM_ULONG (background
.pixel
);
8889 #elif defined (HAVE_NTGUI)
8890 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8891 #if 0 /* W32 TODO : Colormap support. */
8892 x_query_color (f
, &background
);
8895 /* SVG pixmaps specify transparency in the last byte, so right
8896 shift 8 bits to get rid of it, since emacs doesn't support
8898 background
.red
>>= 8;
8899 background
.green
>>= 8;
8900 background
.blue
>>= 8;
8901 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8906 /* This loop handles opacity values, since Emacs assumes
8907 non-transparent images. Each pixel must be "flattened" by
8908 calculating the resulting color, given the transparency of the
8909 pixel, and the image background color. */
8910 for (y
= 0; y
< height
; ++y
)
8912 for (x
= 0; x
< width
; ++x
)
8922 opacity
= *pixels
++;
8924 red
= ((red
* opacity
)
8925 + (background
.red
* ((1 << 8) - opacity
)));
8926 green
= ((green
* opacity
)
8927 + (background
.green
* ((1 << 8) - opacity
)));
8928 blue
= ((blue
* opacity
)
8929 + (background
.blue
* ((1 << 8) - opacity
)));
8931 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8934 pixels
+= rowstride
- 4 * width
;
8937 #ifdef COLOR_TABLE_SUPPORT
8938 /* Remember colors allocated for this image. */
8939 img
->colors
= colors_in_color_table (&img
->ncolors
);
8940 free_color_table ();
8941 #endif /* COLOR_TABLE_SUPPORT */
8943 fn_g_object_unref (pixbuf
);
8946 img
->height
= height
;
8948 /* Maybe fill in the background field while we have ximg handy.
8949 Casting avoids a GCC warning. */
8950 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8952 /* Put the image into the pixmap, then free the X image and its
8954 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8955 x_destroy_x_image (ximg
);
8960 /* FIXME: Use error->message so the user knows what is the actual
8961 problem with the image. */
8962 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8963 fn_g_error_free (error
);
8967 #endif /* defined (HAVE_RSVG) */
8972 /***********************************************************************
8974 ***********************************************************************/
8976 #ifdef HAVE_X_WINDOWS
8977 #define HAVE_GHOSTSCRIPT 1
8978 #endif /* HAVE_X_WINDOWS */
8980 /* The symbol `postscript' identifying images of this type. */
8982 Lisp_Object Qpostscript
;
8984 #ifdef HAVE_GHOSTSCRIPT
8986 static int gs_image_p
P_ ((Lisp_Object object
));
8987 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8988 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8990 /* Keyword symbols. */
8992 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8994 /* Indices of image specification fields in gs_format, below. */
8996 enum gs_keyword_index
9014 /* Vector of image_keyword structures describing the format
9015 of valid user-defined image specifications. */
9017 static struct image_keyword gs_format
[GS_LAST
] =
9019 {":type", IMAGE_SYMBOL_VALUE
, 1},
9020 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9021 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9022 {":file", IMAGE_STRING_VALUE
, 1},
9023 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9024 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9025 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9026 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9027 {":relief", IMAGE_INTEGER_VALUE
, 0},
9028 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9029 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9030 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9031 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9034 /* Structure describing the image type `ghostscript'. */
9036 static struct image_type gs_type
=
9046 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9049 gs_clear_image (f
, img
)
9053 /* IMG->data.ptr_val may contain a recorded colormap. */
9054 xfree (img
->data
.ptr_val
);
9055 x_clear_image (f
, img
);
9059 /* Return non-zero if OBJECT is a valid Ghostscript image
9066 struct image_keyword fmt
[GS_LAST
];
9070 bcopy (gs_format
, fmt
, sizeof fmt
);
9072 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9075 /* Bounding box must be a list or vector containing 4 integers. */
9076 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9079 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9080 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9085 else if (VECTORP (tem
))
9087 if (XVECTOR (tem
)->size
!= 4)
9089 for (i
= 0; i
< 4; ++i
)
9090 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9100 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9109 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9110 struct gcpro gcpro1
, gcpro2
;
9112 double in_width
, in_height
;
9113 Lisp_Object pixel_colors
= Qnil
;
9115 /* Compute pixel size of pixmap needed from the given size in the
9116 image specification. Sizes in the specification are in pt. 1 pt
9117 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9119 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9120 in_width
= XFASTINT (pt_width
) / 72.0;
9121 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9122 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9123 in_height
= XFASTINT (pt_height
) / 72.0;
9124 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9126 if (!check_image_size (f
, img
->width
, img
->height
))
9128 image_error ("Invalid image size", Qnil
, Qnil
);
9132 /* Create the pixmap. */
9133 xassert (img
->pixmap
== NO_PIXMAP
);
9135 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9137 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9138 img
->width
, img
->height
,
9139 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9144 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9148 /* Call the loader to fill the pixmap. It returns a process object
9149 if successful. We do not record_unwind_protect here because
9150 other places in redisplay like calling window scroll functions
9151 don't either. Let the Lisp loader use `unwind-protect' instead. */
9152 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9154 sprintf (buffer
, "%lu %lu",
9155 (unsigned long) FRAME_X_WINDOW (f
),
9156 (unsigned long) img
->pixmap
);
9157 window_and_pixmap_id
= build_string (buffer
);
9159 sprintf (buffer
, "%lu %lu",
9160 FRAME_FOREGROUND_PIXEL (f
),
9161 FRAME_BACKGROUND_PIXEL (f
));
9162 pixel_colors
= build_string (buffer
);
9164 XSETFRAME (frame
, f
);
9165 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9167 loader
= intern ("gs-load-image");
9169 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9170 make_number (img
->width
),
9171 make_number (img
->height
),
9172 window_and_pixmap_id
,
9175 return PROCESSP (img
->data
.lisp_val
);
9179 /* Kill the Ghostscript process that was started to fill PIXMAP on
9180 frame F. Called from XTread_socket when receiving an event
9181 telling Emacs that Ghostscript has finished drawing. */
9184 x_kill_gs_process (pixmap
, f
)
9188 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
9192 /* Find the image containing PIXMAP. */
9193 for (i
= 0; i
< c
->used
; ++i
)
9194 if (c
->images
[i
]->pixmap
== pixmap
)
9197 /* Should someone in between have cleared the image cache, for
9198 instance, give up. */
9202 /* Kill the GS process. We should have found PIXMAP in the image
9203 cache and its image should contain a process object. */
9205 xassert (PROCESSP (img
->data
.lisp_val
));
9206 Fkill_process (img
->data
.lisp_val
, Qnil
);
9207 img
->data
.lisp_val
= Qnil
;
9209 #if defined (HAVE_X_WINDOWS)
9211 /* On displays with a mutable colormap, figure out the colors
9212 allocated for the image by looking at the pixels of an XImage for
9214 class = FRAME_X_VISUAL (f
)->class;
9215 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9221 /* Try to get an XImage for img->pixmep. */
9222 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9223 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9228 /* Initialize the color table. */
9229 init_color_table ();
9231 /* For each pixel of the image, look its color up in the
9232 color table. After having done so, the color table will
9233 contain an entry for each color used by the image. */
9234 for (y
= 0; y
< img
->height
; ++y
)
9235 for (x
= 0; x
< img
->width
; ++x
)
9237 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9238 lookup_pixel_color (f
, pixel
);
9241 /* Record colors in the image. Free color table and XImage. */
9242 #ifdef COLOR_TABLE_SUPPORT
9243 img
->colors
= colors_in_color_table (&img
->ncolors
);
9244 free_color_table ();
9246 XDestroyImage (ximg
);
9248 #if 0 /* This doesn't seem to be the case. If we free the colors
9249 here, we get a BadAccess later in x_clear_image when
9250 freeing the colors. */
9251 /* We have allocated colors once, but Ghostscript has also
9252 allocated colors on behalf of us. So, to get the
9253 reference counts right, free them once. */
9255 x_free_colors (f
, img
->colors
, img
->ncolors
);
9259 image_error ("Cannot get X image of `%s'; colors will not be freed",
9264 #endif /* HAVE_X_WINDOWS */
9266 /* Now that we have the pixmap, compute mask and transform the
9267 image if requested. */
9269 postprocess_image (f
, img
);
9273 #endif /* HAVE_GHOSTSCRIPT */
9276 /***********************************************************************
9278 ***********************************************************************/
9282 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9283 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
9287 return valid_image_p (spec
) ? Qt
: Qnil
;
9291 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
9297 if (valid_image_p (spec
))
9298 id
= lookup_image (SELECTED_FRAME (), spec
);
9301 return make_number (id
);
9304 #endif /* GLYPH_DEBUG != 0 */
9307 /***********************************************************************
9309 ***********************************************************************/
9312 /* Image types that rely on external libraries are loaded dynamically
9313 if the library is available. */
9314 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9315 define_image_type (image_type, init_lib_fn (libraries))
9317 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9318 define_image_type (image_type, 1)
9319 #endif /* HAVE_NTGUI */
9321 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
9322 doc
: /* Initialize image library implementing image type TYPE.
9323 Return non-nil if TYPE is a supported image type.
9325 Image types pbm and xbm are prebuilt; other types are loaded here.
9326 Libraries to load are specified in alist LIBRARIES (usually, the value
9327 of `image-library-alist', which see). */)
9329 Lisp_Object type
, libraries
;
9333 /* Don't try to reload the library. */
9334 tested
= Fassq (type
, Vimage_type_cache
);
9336 return XCDR (tested
);
9338 #if defined (HAVE_XPM) || defined (MAC_OS)
9339 if (EQ (type
, Qxpm
))
9340 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
9343 #if defined (HAVE_JPEG) || defined (MAC_OS)
9344 if (EQ (type
, Qjpeg
))
9345 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
9348 #if defined (HAVE_TIFF) || defined (MAC_OS)
9349 if (EQ (type
, Qtiff
))
9350 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
9353 #if defined (HAVE_GIF) || defined (MAC_OS)
9354 if (EQ (type
, Qgif
))
9355 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
9358 #if defined (HAVE_PNG) || defined (MAC_OS)
9359 if (EQ (type
, Qpng
))
9360 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
9363 #if defined (HAVE_RSVG)
9364 if (EQ (type
, Qsvg
))
9365 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
9368 #ifdef HAVE_GHOSTSCRIPT
9369 if (EQ (type
, Qpostscript
))
9370 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
9373 /* If the type is not recognized, avoid testing it ever again. */
9374 CACHE_IMAGE_TYPE (type
, Qnil
);
9381 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
9383 /* Initialize this only once, since that's what we do with Vimage_types
9384 and they are supposed to be in sync. Initializing here gives correct
9385 operation on GNU/Linux of calling dump-emacs after loading some images. */
9388 /* Must be defined now becase we're going to update it below, while
9389 defining the supported image types. */
9390 DEFVAR_LISP ("image-types", &Vimage_types
,
9391 doc
: /* List of potentially supported image types.
9392 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9393 To check whether it is really supported, use `image-type-available-p'. */);
9394 Vimage_types
= Qnil
;
9396 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
9397 doc
: /* Alist of image types vs external libraries needed to display them.
9399 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9400 representing a supported image type, and the rest are strings giving
9401 alternate filenames for the corresponding external libraries.
9403 Emacs tries to load the libraries in the order they appear on the
9404 list; if none is loaded, the running session of Emacs won't
9405 support the image type. Types 'pbm and 'xbm don't need to be
9406 listed; they are always supported. */);
9407 Vimage_library_alist
= Qnil
;
9408 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
9410 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
9411 doc
: /* Maximum size of images.
9412 Emacs will not load an image into memory if its pixel width or
9413 pixel height exceeds this limit.
9415 If the value is an integer, it directly specifies the maximum
9416 image height and width, measured in pixels. If it is a floating
9417 point number, it specifies the maximum image height and width
9418 as a ratio to the frame height and width. If the value is
9419 non-numeric, there is no explicit limit on the size of images. */);
9420 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
9422 Vimage_type_cache
= Qnil
;
9423 staticpro (&Vimage_type_cache
);
9425 Qpbm
= intern ("pbm");
9427 ADD_IMAGE_TYPE (Qpbm
);
9429 Qxbm
= intern ("xbm");
9431 ADD_IMAGE_TYPE (Qxbm
);
9433 define_image_type (&xbm_type
, 1);
9434 define_image_type (&pbm_type
, 1);
9436 Qcount
= intern ("count");
9437 staticpro (&Qcount
);
9439 QCascent
= intern (":ascent");
9440 staticpro (&QCascent
);
9441 QCmargin
= intern (":margin");
9442 staticpro (&QCmargin
);
9443 QCrelief
= intern (":relief");
9444 staticpro (&QCrelief
);
9445 QCconversion
= intern (":conversion");
9446 staticpro (&QCconversion
);
9447 QCcolor_symbols
= intern (":color-symbols");
9448 staticpro (&QCcolor_symbols
);
9449 QCheuristic_mask
= intern (":heuristic-mask");
9450 staticpro (&QCheuristic_mask
);
9451 QCindex
= intern (":index");
9452 staticpro (&QCindex
);
9453 QCmatrix
= intern (":matrix");
9454 staticpro (&QCmatrix
);
9455 QCcolor_adjustment
= intern (":color-adjustment");
9456 staticpro (&QCcolor_adjustment
);
9457 QCmask
= intern (":mask");
9458 staticpro (&QCmask
);
9460 Qlaplace
= intern ("laplace");
9461 staticpro (&Qlaplace
);
9462 Qemboss
= intern ("emboss");
9463 staticpro (&Qemboss
);
9464 Qedge_detection
= intern ("edge-detection");
9465 staticpro (&Qedge_detection
);
9466 Qheuristic
= intern ("heuristic");
9467 staticpro (&Qheuristic
);
9469 Qpostscript
= intern ("postscript");
9470 staticpro (&Qpostscript
);
9471 #ifdef HAVE_GHOSTSCRIPT
9472 ADD_IMAGE_TYPE (Qpostscript
);
9473 QCloader
= intern (":loader");
9474 staticpro (&QCloader
);
9475 QCbounding_box
= intern (":bounding-box");
9476 staticpro (&QCbounding_box
);
9477 QCpt_width
= intern (":pt-width");
9478 staticpro (&QCpt_width
);
9479 QCpt_height
= intern (":pt-height");
9480 staticpro (&QCpt_height
);
9481 #endif /* HAVE_GHOSTSCRIPT */
9483 #if defined (HAVE_XPM) || defined (MAC_OS)
9484 Qxpm
= intern ("xpm");
9486 ADD_IMAGE_TYPE (Qxpm
);
9489 #if defined (HAVE_JPEG) || defined (MAC_OS)
9490 Qjpeg
= intern ("jpeg");
9492 ADD_IMAGE_TYPE (Qjpeg
);
9495 #if defined (HAVE_TIFF) || defined (MAC_OS)
9496 Qtiff
= intern ("tiff");
9498 ADD_IMAGE_TYPE (Qtiff
);
9501 #if defined (HAVE_GIF) || defined (MAC_OS)
9502 Qgif
= intern ("gif");
9504 ADD_IMAGE_TYPE (Qgif
);
9507 #if defined (HAVE_PNG) || defined (MAC_OS)
9508 Qpng
= intern ("png");
9510 ADD_IMAGE_TYPE (Qpng
);
9513 #if defined (HAVE_RSVG)
9514 Qsvg
= intern ("svg");
9516 ADD_IMAGE_TYPE (Qsvg
);
9518 Qgdk_pixbuf
= intern ("gdk-pixbuf");
9519 staticpro (&Qgdk_pixbuf
);
9520 Qglib
= intern ("glib");
9522 #endif /* HAVE_NTGUI */
9523 #endif /* HAVE_RSVG */
9525 defsubr (&Sinit_image_library
);
9526 defsubr (&Sclear_image_cache
);
9527 defsubr (&Simage_refresh
);
9528 defsubr (&Simage_size
);
9529 defsubr (&Simage_mask_p
);
9530 defsubr (&Simage_extension_data
);
9534 defsubr (&Slookup_image
);
9537 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9538 doc
: /* Non-nil means always draw a cross over disabled images.
9539 Disabled images are those having a `:conversion disabled' property.
9540 A cross is always drawn on black & white displays. */);
9541 cross_disabled_images
= 0;
9543 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9544 doc
: /* List of directories to search for window system bitmap files. */);
9545 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9547 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9548 doc
: /* Time after which cached images are removed from the cache.
9549 When an image has not been displayed this many seconds, remove it
9550 from the image cache. Value must be an integer or nil with nil
9551 meaning don't clear the cache. */);
9552 Vimage_cache_eviction_delay
= make_number (30 * 60);
9560 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9561 (do not change this comment) */