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, or (at your option)
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; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
32 /* This makes the fields of a Display accessible, in Xlib header files. */
34 #define XLIB_ILLEGAL_ACCESS
39 #include "dispextern.h"
40 #include "blockinput.h"
49 #include <sys/types.h>
52 #define COLOR_TABLE_SUPPORT 1
54 typedef struct x_bitmap_record Bitmap_Record
;
55 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
56 #define NO_PIXMAP None
58 #define RGB_PIXEL_COLOR unsigned long
60 #define PIX_MASK_RETAIN 0
61 #define PIX_MASK_DRAW 1
62 #endif /* HAVE_X_WINDOWS */
68 /* W32_TODO : Color tables on W32. */
69 #undef COLOR_TABLE_SUPPORT
71 typedef struct w32_bitmap_record Bitmap_Record
;
72 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
75 #define RGB_PIXEL_COLOR COLORREF
77 #define PIX_MASK_RETAIN 0
78 #define PIX_MASK_DRAW 1
80 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
81 #define x_defined_color w32_defined_color
82 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 #endif /* HAVE_NTGUI */
91 #include <sys/param.h>
93 #if TARGET_API_MAC_CARBON
95 #include <QuickTime/QuickTime.h>
96 #else /* not MAC_OSX */
97 #include <QuickTime.h>
98 #endif /* not MAC_OSX */
99 #else /* not TARGET_API_MAC_CARBON */
102 #include <TextUtils.h>
103 #include <ImageCompression.h>
104 #include <QuickTimeComponents.h>
105 #endif /* not TARGET_API_MAC_CARBON */
107 /* MAC_TODO : Color tables on Mac. */
108 #undef COLOR_TABLE_SUPPORT
110 #define ZPixmap 0 /* arbitrary */
111 typedef struct mac_bitmap_record Bitmap_Record
;
113 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
116 #define RGB_PIXEL_COLOR unsigned long
119 #define PIX_MASK_DRAW 255
120 #define PIX_MASK_RETAIN 0
122 /* A black pixel in a mask bitmap/pixmap means ``draw a source
123 pixel''. A white pixel means ``retain the current pixel''. */
124 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
125 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
128 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
129 #define x_defined_color mac_defined_color
130 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
135 /* Search path for bitmap files. */
137 Lisp_Object Vx_bitmap_file_path
;
140 static void x_disable_image
P_ ((struct frame
*, struct image
*));
141 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
144 static void init_color_table
P_ ((void));
145 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
146 #ifdef COLOR_TABLE_SUPPORT
147 static void free_color_table
P_ ((void));
148 static unsigned long *colors_in_color_table
P_ ((int *n
));
149 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
152 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
153 id, which is just an int that this section returns. Bitmaps are
154 reference counted so they can be shared among frames.
156 Bitmap indices are guaranteed to be > 0, so a negative number can
157 be used to indicate no bitmap.
159 If you use x_create_bitmap_from_data, then you must keep track of
160 the bitmaps yourself. That is, creating a bitmap from the same
161 data more than once will not be caught. */
166 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
167 Display
*display
; /* not used */
169 int x
, y
; /* not used */
170 unsigned int width
, height
; /* not used */
171 unsigned long plane_mask
; /* not used */
172 int format
; /* not used */
174 #if !USE_MAC_IMAGE_IO
176 xassert (x
== 0 && y
== 0);
179 SetRect (&ri
, 0, 0, width
, height
);
180 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
182 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
185 LockPixels (GetGWorldPixMap (pixmap
));
192 XPutPixel (ximage
, x
, y
, pixel
)
198 if (ximage
->bits_per_pixel
== 32)
199 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
201 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
203 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
204 short depth
= GetPixDepth (pixmap
);
206 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
209 char *base_addr
= GetPixBaseAddr (pixmap
);
210 short row_bytes
= GetPixRowBytes (pixmap
);
212 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
218 char *base_addr
= GetPixBaseAddr (pixmap
);
219 short row_bytes
= GetPixRowBytes (pixmap
);
221 if (pixel
== PIX_MASK_DRAW
)
222 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
224 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
232 GetGWorld (&old_port
, &old_gdh
);
233 SetGWorld (ximage
, NULL
);
235 color
.red
= RED16_FROM_ULONG (pixel
);
236 color
.green
= GREEN16_FROM_ULONG (pixel
);
237 color
.blue
= BLUE16_FROM_ULONG (pixel
);
239 SetCPixel (x
, y
, &color
);
241 SetGWorld (old_port
, old_gdh
);
247 XGetPixel (ximage
, x
, y
)
252 if (ximage
->bits_per_pixel
== 32)
253 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
255 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
257 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
258 short depth
= GetPixDepth (pixmap
);
260 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
263 char *base_addr
= GetPixBaseAddr (pixmap
);
264 short row_bytes
= GetPixRowBytes (pixmap
);
266 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
272 char *base_addr
= GetPixBaseAddr (pixmap
);
273 short row_bytes
= GetPixRowBytes (pixmap
);
275 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
276 return PIX_MASK_DRAW
;
278 return PIX_MASK_RETAIN
;
286 GetGWorld (&old_port
, &old_gdh
);
287 SetGWorld (ximage
, NULL
);
289 GetCPixel (x
, y
, &color
);
291 SetGWorld (old_port
, old_gdh
);
292 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
301 #if !USE_MAC_IMAGE_IO
302 UnlockPixels (GetGWorldPixMap (ximg
));
309 mac_data_provider_release_data (info
, data
, size
)
314 xfree ((void *)data
);
319 mac_create_cg_image_from_image (f
, img
)
324 XImagePtr ximg
= img
->pixmap
;
325 CGDataProviderRef provider
;
331 unsigned long color
, alpha
;
333 for (y
= 0; y
< ximg
->height
; y
++)
334 for (x
= 0; x
< ximg
->width
; x
++)
336 color
= XGetPixel (ximg
, x
, y
);
337 alpha
= XGetPixel (img
->mask
, x
, y
);
338 XPutPixel (ximg
, x
, y
,
339 ARGB_TO_ULONG (alpha
,
340 RED_FROM_ULONG (color
)
341 * alpha
/ PIX_MASK_DRAW
,
342 GREEN_FROM_ULONG (color
)
343 * alpha
/ PIX_MASK_DRAW
,
344 BLUE_FROM_ULONG (color
)
345 * alpha
/ PIX_MASK_DRAW
));
347 xfree (img
->mask
->data
);
348 img
->mask
->data
= NULL
;
351 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
352 ximg
->bytes_per_line
* ximg
->height
,
353 mac_data_provider_release_data
);
355 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
356 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
357 ((img
->mask
? kCGImageAlphaPremultipliedFirst
358 : kCGImageAlphaNoneSkipFirst
)
359 | kCGBitmapByteOrder32Host
),
360 provider
, NULL
, 0, kCGRenderingIntentDefault
);
361 CGDataProviderRelease (provider
);
367 CGImageRef result
= NULL
;
374 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
375 img
->width
, img
->height
, 1);
382 GetGWorld (&old_port
, &old_gdh
);
383 SetGWorld (mask
, NULL
);
384 BackColor (blackColor
); /* Don't mask. */
385 SetRect (&r
, 0, 0, img
->width
, img
->height
);
387 SetGWorld (old_port
, old_gdh
);
392 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
393 GetGWorldPixMap (mask
), &result
);
394 if (mask
!= img
->mask
)
395 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
402 #endif /* USE_CG_DRAWING */
406 /* Functions to access the contents of a bitmap, given an id. */
409 x_bitmap_height (f
, id
)
413 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
417 x_bitmap_width (f
, id
)
421 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
424 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
426 x_bitmap_pixmap (f
, id
)
430 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
434 #ifdef HAVE_X_WINDOWS
436 x_bitmap_mask (f
, id
)
440 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
444 /* Allocate a new bitmap record. Returns index of new record. */
447 x_allocate_bitmap_record (f
)
450 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
453 if (dpyinfo
->bitmaps
== NULL
)
455 dpyinfo
->bitmaps_size
= 10;
457 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
458 dpyinfo
->bitmaps_last
= 1;
462 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
463 return ++dpyinfo
->bitmaps_last
;
465 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
466 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
469 dpyinfo
->bitmaps_size
*= 2;
471 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
472 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
473 return ++dpyinfo
->bitmaps_last
;
476 /* Add one reference to the reference count of the bitmap with id ID. */
479 x_reference_bitmap (f
, id
)
483 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
486 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
489 x_create_bitmap_from_data (f
, bits
, width
, height
)
492 unsigned int width
, height
;
494 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
497 #ifdef HAVE_X_WINDOWS
499 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
500 bits
, width
, height
);
503 #endif /* HAVE_X_WINDOWS */
507 bitmap
= CreateBitmap (width
, height
,
508 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
509 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
513 #endif /* HAVE_NTGUI */
516 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
521 id
= x_allocate_bitmap_record (f
);
523 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
524 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
527 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
528 dpyinfo
->bitmaps
[id
- 1].height
= height
;
529 dpyinfo
->bitmaps
[id
- 1].width
= width
;
530 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
532 #ifdef HAVE_X_WINDOWS
533 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
534 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
535 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
536 #endif /* HAVE_X_WINDOWS */
539 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
540 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
541 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
542 #endif /* HAVE_NTGUI */
547 /* Create bitmap from file FILE for frame F. */
550 x_create_bitmap_from_file (f
, file
)
555 return -1; /* MAC_TODO : bitmap support */
559 return -1; /* W32_TODO : bitmap support */
560 #endif /* HAVE_NTGUI */
562 #ifdef HAVE_X_WINDOWS
563 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
564 unsigned int width
, height
;
566 int xhot
, yhot
, result
, id
;
571 /* Look for an existing bitmap with the same name. */
572 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
574 if (dpyinfo
->bitmaps
[id
].refcount
575 && dpyinfo
->bitmaps
[id
].file
576 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
578 ++dpyinfo
->bitmaps
[id
].refcount
;
583 /* Search bitmap-file-path for the file, if appropriate. */
584 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
589 filename
= (char *) SDATA (found
);
591 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
592 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
593 if (result
!= BitmapSuccess
)
596 id
= x_allocate_bitmap_record (f
);
597 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
598 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
599 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
600 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
601 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
602 dpyinfo
->bitmaps
[id
- 1].height
= height
;
603 dpyinfo
->bitmaps
[id
- 1].width
= width
;
604 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
607 #endif /* HAVE_X_WINDOWS */
613 Free_Bitmap_Record (dpyinfo
, bm
)
614 Display_Info
*dpyinfo
;
617 #ifdef HAVE_X_WINDOWS
618 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
620 XFreePixmap (dpyinfo
->display
, bm
->mask
);
621 #endif /* HAVE_X_WINDOWS */
624 DeleteObject (bm
->pixmap
);
625 #endif /* HAVE_NTGUI */
628 xfree (bm
->bitmap_data
); /* Added ++kfs */
629 bm
->bitmap_data
= NULL
;
639 /* Remove reference to bitmap with id number ID. */
642 x_destroy_bitmap (f
, id
)
646 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
650 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
652 if (--bm
->refcount
== 0)
655 Free_Bitmap_Record (dpyinfo
, bm
);
661 /* Free all the bitmaps for the display specified by DPYINFO. */
664 x_destroy_all_bitmaps (dpyinfo
)
665 Display_Info
*dpyinfo
;
668 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
670 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
671 if (bm
->refcount
> 0)
672 Free_Bitmap_Record (dpyinfo
, bm
);
674 dpyinfo
->bitmaps_last
= 0;
678 #ifdef HAVE_X_WINDOWS
680 /* Useful functions defined in the section
681 `Image type independent image structures' below. */
683 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
686 unsigned long height
));
688 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
689 int depth
, XImagePtr
*ximg
,
692 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
695 /* Create a mask of a bitmap. Note is this not a perfect mask.
696 It's nicer with some borders in this context */
699 x_create_bitmap_mask (f
, id
)
704 XImagePtr ximg
, mask_img
;
705 unsigned long width
, height
;
708 unsigned long x
, y
, xp
, xm
, yp
, ym
;
711 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
716 pixmap
= x_bitmap_pixmap (f
, id
);
717 width
= x_bitmap_width (f
, id
);
718 height
= x_bitmap_height (f
, id
);
721 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
730 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
735 XDestroyImage (ximg
);
739 bg
= four_corners_best (ximg
, NULL
, width
, height
);
741 for (y
= 0; y
< ximg
->height
; ++y
)
743 for (x
= 0; x
< ximg
->width
; ++x
)
745 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
746 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
747 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
748 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
749 if (XGetPixel (ximg
, x
, y
) == bg
750 && XGetPixel (ximg
, x
, yp
) == bg
751 && XGetPixel (ximg
, x
, ym
) == bg
752 && XGetPixel (ximg
, xp
, y
) == bg
753 && XGetPixel (ximg
, xp
, yp
) == bg
754 && XGetPixel (ximg
, xp
, ym
) == bg
755 && XGetPixel (ximg
, xm
, y
) == bg
756 && XGetPixel (ximg
, xm
, yp
) == bg
757 && XGetPixel (ximg
, xm
, ym
) == bg
)
758 XPutPixel (mask_img
, x
, y
, 0);
760 XPutPixel (mask_img
, x
, y
, 1);
764 xassert (interrupt_input_blocked
);
765 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
766 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
768 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
770 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
771 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
773 XDestroyImage (ximg
);
774 x_destroy_x_image (mask_img
);
779 #endif /* HAVE_X_WINDOWS */
782 /***********************************************************************
784 ***********************************************************************/
786 /* Value is the number of elements of vector VECTOR. */
788 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
790 /* List of supported image types. Use define_image_type to add new
791 types. Use lookup_image_type to find a type for a given symbol. */
793 static struct image_type
*image_types
;
795 /* A list of symbols, one for each supported image type. */
797 Lisp_Object Vimage_types
;
799 /* An alist of image types and libraries that implement the type. */
801 Lisp_Object Vimage_library_alist
;
803 /* Cache for delayed-loading image types. */
805 static Lisp_Object Vimage_type_cache
;
807 /* The symbol `xbm' which is used as the type symbol for XBM images. */
813 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
814 extern Lisp_Object QCdata
, QCtype
, Qcount
;
815 extern Lisp_Object Qcenter
;
816 Lisp_Object QCascent
, QCmargin
, QCrelief
;
817 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
818 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
822 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
824 /* Time in seconds after which images should be removed from the cache
827 Lisp_Object Vimage_cache_eviction_delay
;
829 /* Function prototypes. */
831 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
832 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
833 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
834 static void x_laplace
P_ ((struct frame
*, struct image
*));
835 static void x_emboss
P_ ((struct frame
*, struct image
*));
836 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
839 #define CACHE_IMAGE_TYPE(type, status) \
840 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
842 #define ADD_IMAGE_TYPE(type) \
843 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
845 /* Define a new image type from TYPE. This adds a copy of TYPE to
846 image_types and caches the loading status of TYPE. */
849 define_image_type (type
, loaded
)
850 struct image_type
*type
;
859 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
860 The initialized data segment is read-only. */
861 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
862 bcopy (type
, p
, sizeof *p
);
863 p
->next
= image_types
;
868 CACHE_IMAGE_TYPE (*type
->type
, success
);
873 /* Look up image type SYMBOL, and return a pointer to its image_type
874 structure. Value is null if SYMBOL is not a known image type. */
876 static INLINE
struct image_type
*
877 lookup_image_type (symbol
)
880 struct image_type
*type
;
882 /* We must initialize the image-type if it hasn't been already. */
883 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
884 return 0; /* unimplemented */
886 for (type
= image_types
; type
; type
= type
->next
)
887 if (EQ (symbol
, *type
->type
))
894 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
895 valid image specification is a list whose car is the symbol
896 `image', and whose rest is a property list. The property list must
897 contain a value for key `:type'. That value must be the name of a
898 supported image type. The rest of the property list depends on the
902 valid_image_p (object
)
911 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
912 if (EQ (XCAR (tem
), QCtype
))
915 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
917 struct image_type
*type
;
918 type
= lookup_image_type (XCAR (tem
));
920 valid_p
= type
->valid_p (object
);
931 /* Log error message with format string FORMAT and argument ARG.
932 Signaling an error, e.g. when an image cannot be loaded, is not a
933 good idea because this would interrupt redisplay, and the error
934 message display would lead to another redisplay. This function
935 therefore simply displays a message. */
938 image_error (format
, arg1
, arg2
)
940 Lisp_Object arg1
, arg2
;
942 add_to_log (format
, arg1
, arg2
);
947 /***********************************************************************
949 ***********************************************************************/
951 enum image_value_type
953 IMAGE_DONT_CHECK_VALUE_TYPE
,
955 IMAGE_STRING_OR_NIL_VALUE
,
957 IMAGE_POSITIVE_INTEGER_VALUE
,
958 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
959 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
962 IMAGE_FUNCTION_VALUE
,
967 /* Structure used when parsing image specifications. */
971 /* Name of keyword. */
974 /* The type of value allowed. */
975 enum image_value_type type
;
977 /* Non-zero means key must be present. */
980 /* Used to recognize duplicate keywords in a property list. */
983 /* The value that was found. */
988 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
990 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
993 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
994 has the format (image KEYWORD VALUE ...). One of the keyword/
995 value pairs must be `:type TYPE'. KEYWORDS is a vector of
996 image_keywords structures of size NKEYWORDS describing other
997 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1000 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1002 struct image_keyword
*keywords
;
1012 plist
= XCDR (spec
);
1013 while (CONSP (plist
))
1015 Lisp_Object key
, value
;
1017 /* First element of a pair must be a symbol. */
1019 plist
= XCDR (plist
);
1023 /* There must follow a value. */
1026 value
= XCAR (plist
);
1027 plist
= XCDR (plist
);
1029 /* Find key in KEYWORDS. Error if not found. */
1030 for (i
= 0; i
< nkeywords
; ++i
)
1031 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1037 /* Record that we recognized the keyword. If a keywords
1038 was found more than once, it's an error. */
1039 keywords
[i
].value
= value
;
1040 ++keywords
[i
].count
;
1042 if (keywords
[i
].count
> 1)
1045 /* Check type of value against allowed type. */
1046 switch (keywords
[i
].type
)
1048 case IMAGE_STRING_VALUE
:
1049 if (!STRINGP (value
))
1053 case IMAGE_STRING_OR_NIL_VALUE
:
1054 if (!STRINGP (value
) && !NILP (value
))
1058 case IMAGE_SYMBOL_VALUE
:
1059 if (!SYMBOLP (value
))
1063 case IMAGE_POSITIVE_INTEGER_VALUE
:
1064 if (!INTEGERP (value
) || XINT (value
) <= 0)
1068 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1069 if (INTEGERP (value
) && XINT (value
) >= 0)
1072 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1073 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1077 case IMAGE_ASCENT_VALUE
:
1078 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1080 else if (INTEGERP (value
)
1081 && XINT (value
) >= 0
1082 && XINT (value
) <= 100)
1086 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1087 if (!INTEGERP (value
) || XINT (value
) < 0)
1091 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1094 case IMAGE_FUNCTION_VALUE
:
1095 value
= indirect_function (value
);
1097 || COMPILEDP (value
)
1098 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1102 case IMAGE_NUMBER_VALUE
:
1103 if (!INTEGERP (value
) && !FLOATP (value
))
1107 case IMAGE_INTEGER_VALUE
:
1108 if (!INTEGERP (value
))
1112 case IMAGE_BOOL_VALUE
:
1113 if (!NILP (value
) && !EQ (value
, Qt
))
1122 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1126 /* Check that all mandatory fields are present. */
1127 for (i
= 0; i
< nkeywords
; ++i
)
1128 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1131 return NILP (plist
);
1135 /* Return the value of KEY in image specification SPEC. Value is nil
1136 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1137 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1140 image_spec_value (spec
, key
, found
)
1141 Lisp_Object spec
, key
;
1146 xassert (valid_image_p (spec
));
1148 for (tail
= XCDR (spec
);
1149 CONSP (tail
) && CONSP (XCDR (tail
));
1150 tail
= XCDR (XCDR (tail
)))
1152 if (EQ (XCAR (tail
), key
))
1156 return XCAR (XCDR (tail
));
1166 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1167 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1168 PIXELS non-nil means return the size in pixels, otherwise return the
1169 size in canonical character units.
1170 FRAME is the frame on which the image will be displayed. FRAME nil
1171 or omitted means use the selected frame. */)
1172 (spec
, pixels
, frame
)
1173 Lisp_Object spec
, pixels
, frame
;
1178 if (valid_image_p (spec
))
1180 struct frame
*f
= check_x_frame (frame
);
1181 int id
= lookup_image (f
, spec
);
1182 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1183 int width
= img
->width
+ 2 * img
->hmargin
;
1184 int height
= img
->height
+ 2 * img
->vmargin
;
1187 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1188 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1190 size
= Fcons (make_number (width
), make_number (height
));
1193 error ("Invalid image specification");
1199 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1200 doc
: /* Return t if image SPEC has a mask bitmap.
1201 FRAME is the frame on which the image will be displayed. FRAME nil
1202 or omitted means use the selected frame. */)
1204 Lisp_Object spec
, frame
;
1209 if (valid_image_p (spec
))
1211 struct frame
*f
= check_x_frame (frame
);
1212 int id
= lookup_image (f
, spec
);
1213 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1218 error ("Invalid image specification");
1223 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1224 doc
: /* Return extension data for image SPEC.
1225 FRAME is the frame on which the image will be displayed. FRAME nil
1226 or omitted means use the selected frame. */)
1228 Lisp_Object spec
, frame
;
1233 if (valid_image_p (spec
))
1235 struct frame
*f
= check_x_frame (frame
);
1236 int id
= lookup_image (f
, spec
);
1237 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1238 ext
= img
->data
.lisp_val
;
1245 /***********************************************************************
1246 Image type independent image structures
1247 ***********************************************************************/
1249 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1250 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1251 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1253 #define MAX_IMAGE_SIZE 6.0
1254 Lisp_Object Vmax_image_size
;
1256 /* Allocate and return a new image structure for image specification
1257 SPEC. SPEC has a hash value of HASH. */
1259 static struct image
*
1260 make_image (spec
, hash
)
1264 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1266 xassert (valid_image_p (spec
));
1267 bzero (img
, sizeof *img
);
1268 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1269 xassert (img
->type
!= NULL
);
1271 img
->data
.lisp_val
= Qnil
;
1272 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1274 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1279 /* Free image IMG which was used on frame F, including its resources. */
1288 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1290 /* Remove IMG from the hash table of its cache. */
1292 img
->prev
->next
= img
->next
;
1294 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1297 img
->next
->prev
= img
->prev
;
1299 c
->images
[img
->id
] = NULL
;
1301 /* Free resources, then free IMG. */
1302 img
->type
->free (f
, img
);
1307 /* Return 1 if the given widths and heights are valid for display;
1308 otherwise, return 0. */
1311 check_image_size (f
, width
, height
)
1318 if (width
<= 0 || height
<= 0)
1321 if (INTEGERP (Vmax_image_size
))
1322 w
= h
= XINT (Vmax_image_size
);
1323 else if (FLOATP (Vmax_image_size
))
1327 w
= FRAME_PIXEL_WIDTH (f
);
1328 h
= FRAME_PIXEL_HEIGHT (f
);
1331 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1332 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1333 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1338 return (width
<= w
&& height
<= h
);
1341 /* Prepare image IMG for display on frame F. Must be called before
1342 drawing an image. */
1345 prepare_image_for_display (f
, img
)
1351 /* We're about to display IMG, so set its timestamp to `now'. */
1353 img
->timestamp
= EMACS_SECS (t
);
1355 /* If IMG doesn't have a pixmap yet, load it now, using the image
1356 type dependent loader function. */
1357 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1358 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1360 #if defined (MAC_OS) && USE_CG_DRAWING
1361 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1363 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1364 if (img
->data
.ptr_val
== NULL
)
1366 img
->load_failed_p
= 1;
1367 img
->type
->free (f
, img
);
1374 /* Value is the number of pixels for the ascent of image IMG when
1375 drawn in face FACE. */
1378 image_ascent (img
, face
, slice
)
1381 struct glyph_slice
*slice
;
1386 if (slice
->height
== img
->height
)
1387 height
= img
->height
+ img
->vmargin
;
1388 else if (slice
->y
== 0)
1389 height
= slice
->height
+ img
->vmargin
;
1391 height
= slice
->height
;
1393 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1398 /* W32 specific version. Why?. ++kfs */
1399 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1400 - FONT_BASE(face
->font
)) / 2;
1402 /* This expression is arranged so that if the image can't be
1403 exactly centered, it will be moved slightly up. This is
1404 because a typical font is `top-heavy' (due to the presence
1405 uppercase letters), so the image placement should err towards
1406 being top-heavy too. It also just generally looks better. */
1407 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1408 #endif /* HAVE_NTGUI */
1411 ascent
= height
/ 2;
1414 ascent
= (int) (height
* img
->ascent
/ 100.0);
1420 /* Image background colors. */
1422 /* Find the "best" corner color of a bitmap.
1423 On W32, XIMG is assumed to a device context with the bitmap selected. */
1425 static RGB_PIXEL_COLOR
1426 four_corners_best (ximg
, corners
, width
, height
)
1427 XImagePtr_or_DC ximg
;
1429 unsigned long width
, height
;
1431 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1434 if (corners
&& corners
[BOT_CORNER
] >= 0)
1436 /* Get the colors at the corner_pixels of ximg. */
1437 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1438 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1439 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1440 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1444 /* Get the colors at the corner_pixels of ximg. */
1445 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1446 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1447 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1448 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1450 /* Choose the most frequently found color as background. */
1451 for (i
= best_count
= 0; i
< 4; ++i
)
1455 for (j
= n
= 0; j
< 4; ++j
)
1456 if (corner_pixels
[i
] == corner_pixels
[j
])
1460 best
= corner_pixels
[i
], best_count
= n
;
1466 /* Portability macros */
1470 #define Destroy_Image(img_dc, prev) \
1471 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1473 #define Free_Pixmap(display, pixmap) \
1474 DeleteObject (pixmap)
1478 #define Destroy_Image(ximg, dummy) \
1479 XDestroyImage (ximg)
1481 #define Free_Pixmap(display, pixmap) \
1482 XFreePixmap (display, pixmap)
1484 #endif /* HAVE_NTGUI */
1487 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1488 it is guessed heuristically. If non-zero, XIMG is an existing
1489 XImage object (or device context with the image selected on W32) to
1490 use for the heuristic. */
1493 image_background (img
, f
, ximg
)
1496 XImagePtr_or_DC ximg
;
1498 if (! img
->background_valid
)
1499 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1501 int free_ximg
= !ximg
;
1504 #endif /* HAVE_NTGUI */
1509 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1510 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1512 HDC frame_dc
= get_frame_dc (f
);
1513 ximg
= CreateCompatibleDC (frame_dc
);
1514 release_frame_dc (f
, frame_dc
);
1515 prev
= SelectObject (ximg
, img
->pixmap
);
1516 #endif /* !HAVE_NTGUI */
1519 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1522 Destroy_Image (ximg
, prev
);
1524 img
->background_valid
= 1;
1527 return img
->background
;
1530 /* Return the `background_transparent' field of IMG. If IMG doesn't
1531 have one yet, it is guessed heuristically. If non-zero, MASK is an
1532 existing XImage object to use for the heuristic. */
1535 image_background_transparent (img
, f
, mask
)
1538 XImagePtr_or_DC mask
;
1540 if (! img
->background_transparent_valid
)
1541 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1545 int free_mask
= !mask
;
1548 #endif /* HAVE_NTGUI */
1553 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1554 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1556 HDC frame_dc
= get_frame_dc (f
);
1557 mask
= CreateCompatibleDC (frame_dc
);
1558 release_frame_dc (f
, frame_dc
);
1559 prev
= SelectObject (mask
, img
->mask
);
1560 #endif /* HAVE_NTGUI */
1563 img
->background_transparent
1564 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1567 Destroy_Image (mask
, prev
);
1570 img
->background_transparent
= 0;
1572 img
->background_transparent_valid
= 1;
1575 return img
->background_transparent
;
1579 /***********************************************************************
1580 Helper functions for X image types
1581 ***********************************************************************/
1583 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1585 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1586 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1588 Lisp_Object color_name
,
1589 unsigned long dflt
));
1592 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1593 free the pixmap if any. MASK_P non-zero means clear the mask
1594 pixmap if any. COLORS_P non-zero means free colors allocated for
1595 the image, if any. */
1598 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1601 int pixmap_p
, mask_p
, colors_p
;
1603 if (pixmap_p
&& img
->pixmap
)
1605 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1606 img
->pixmap
= NO_PIXMAP
;
1607 img
->background_valid
= 0;
1610 if (mask_p
&& img
->mask
)
1612 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1613 img
->mask
= NO_PIXMAP
;
1614 img
->background_transparent_valid
= 0;
1617 if (colors_p
&& img
->ncolors
)
1619 /* MAC_TODO: color table support. */
1620 /* W32_TODO: color table support. */
1621 #ifdef HAVE_X_WINDOWS
1622 x_free_colors (f
, img
->colors
, img
->ncolors
);
1623 #endif /* HAVE_X_WINDOWS */
1624 xfree (img
->colors
);
1629 #if defined (MAC_OS) && USE_CG_DRAWING
1630 if (img
->data
.ptr_val
)
1632 CGImageRelease (img
->data
.ptr_val
);
1633 img
->data
.ptr_val
= NULL
;
1638 /* Free X resources of image IMG which is used on frame F. */
1641 x_clear_image (f
, img
)
1646 x_clear_image_1 (f
, img
, 1, 1, 1);
1651 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1652 cannot be allocated, use DFLT. Add a newly allocated color to
1653 IMG->colors, so that it can be freed again. Value is the pixel
1656 static unsigned long
1657 x_alloc_image_color (f
, img
, color_name
, dflt
)
1660 Lisp_Object color_name
;
1664 unsigned long result
;
1666 xassert (STRINGP (color_name
));
1668 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1670 /* This isn't called frequently so we get away with simply
1671 reallocating the color vector to the needed size, here. */
1674 (unsigned long *) xrealloc (img
->colors
,
1675 img
->ncolors
* sizeof *img
->colors
);
1676 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1677 result
= color
.pixel
;
1687 /***********************************************************************
1689 ***********************************************************************/
1691 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1692 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1693 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1695 /* Return a new, initialized image cache that is allocated from the
1696 heap. Call free_image_cache to free an image cache. */
1698 struct image_cache
*
1701 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1704 bzero (c
, sizeof *c
);
1706 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1707 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1708 c
->buckets
= (struct image
**) xmalloc (size
);
1709 bzero (c
->buckets
, size
);
1714 /* Find an image matching SPEC in the cache, and return it. If no
1715 image is found, return NULL. */
1716 static struct image
*
1717 search_image_cache (f
, spec
, hash
)
1723 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1724 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1726 if (!c
) return NULL
;
1728 /* If the image spec does not specify a background color, the cached
1729 image must have the same background color as the current frame.
1730 The foreground color must also match, for the sake of monochrome
1733 In fact, we could ignore the foreground color matching condition
1734 for color images, or if the image spec specifies :foreground;
1735 similarly we could ignore the background color matching condition
1736 for formats that don't use transparency (such as jpeg), or if the
1737 image spec specifies :background. However, the extra memory
1738 usage is probably negligible in practice, so we don't bother. */
1740 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1741 if (img
->hash
== hash
1742 && !NILP (Fequal (img
->spec
, spec
))
1743 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1744 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1750 /* Search frame F for an image with spec SPEC, and free it. */
1753 uncache_image (f
, spec
)
1757 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1759 free_image (f
, img
);
1763 /* Free image cache of frame F. Be aware that X frames share images
1767 free_image_cache (f
)
1770 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1775 /* Cache should not be referenced by any frame when freed. */
1776 xassert (c
->refcount
== 0);
1778 for (i
= 0; i
< c
->used
; ++i
)
1779 free_image (f
, c
->images
[i
]);
1783 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1788 /* Clear image cache of frame F. FORCE_P non-zero means free all
1789 images. FORCE_P zero means clear only images that haven't been
1790 displayed for some time. Should be called from time to time to
1791 reduce the number of loaded images. If image-cache-eviction-delay
1792 is non-nil, this frees images in the cache which weren't displayed
1793 for at least that many seconds. */
1796 clear_image_cache (f
, force_p
)
1800 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1802 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1809 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1811 /* Block input so that we won't be interrupted by a SIGIO
1812 while being in an inconsistent state. */
1815 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1817 struct image
*img
= c
->images
[i
];
1819 && (force_p
|| img
->timestamp
< old
))
1821 free_image (f
, img
);
1826 /* We may be clearing the image cache because, for example,
1827 Emacs was iconified for a longer period of time. In that
1828 case, current matrices may still contain references to
1829 images freed above. So, clear these matrices. */
1832 Lisp_Object tail
, frame
;
1834 FOR_EACH_FRAME (tail
, frame
)
1836 struct frame
*f
= XFRAME (frame
);
1837 if (FRAME_WINDOW_P (f
)
1838 && FRAME_X_IMAGE_CACHE (f
) == c
)
1839 clear_current_matrices (f
);
1842 ++windows_or_buffers_changed
;
1850 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1852 doc
: /* Clear the image cache of FRAME.
1853 FRAME nil or omitted means use the selected frame.
1854 FRAME t means clear the image caches of all frames. */)
1862 FOR_EACH_FRAME (tail
, frame
)
1863 if (FRAME_WINDOW_P (XFRAME (frame
)))
1864 clear_image_cache (XFRAME (frame
), 1);
1867 clear_image_cache (check_x_frame (frame
), 1);
1873 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1875 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1876 If SPEC specifies an image file, the displayed image is updated with
1877 the current contents of that file.
1878 FRAME nil or omitted means use the selected frame.
1879 FRAME t means refresh the image on all frames. */)
1881 Lisp_Object spec
, frame
;
1883 if (!valid_image_p (spec
))
1884 error ("Invalid image specification");
1889 FOR_EACH_FRAME (tail
, frame
)
1891 struct frame
*f
= XFRAME (frame
);
1892 if (FRAME_WINDOW_P (f
))
1893 uncache_image (f
, spec
);
1897 uncache_image (check_x_frame (frame
), spec
);
1903 /* Compute masks and transform image IMG on frame F, as specified
1904 by the image's specification, */
1907 postprocess_image (f
, img
)
1911 /* Manipulation of the image's mask. */
1914 Lisp_Object conversion
, spec
;
1919 /* `:heuristic-mask t'
1921 means build a mask heuristically.
1922 `:heuristic-mask (R G B)'
1923 `:mask (heuristic (R G B))'
1924 means build a mask from color (R G B) in the
1927 means remove a mask, if any. */
1929 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1931 x_build_heuristic_mask (f
, img
, mask
);
1936 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1938 if (EQ (mask
, Qheuristic
))
1939 x_build_heuristic_mask (f
, img
, Qt
);
1940 else if (CONSP (mask
)
1941 && EQ (XCAR (mask
), Qheuristic
))
1943 if (CONSP (XCDR (mask
)))
1944 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1946 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1948 else if (NILP (mask
) && found_p
&& img
->mask
)
1950 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1951 img
->mask
= NO_PIXMAP
;
1956 /* Should we apply an image transformation algorithm? */
1957 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1958 if (EQ (conversion
, Qdisabled
))
1959 x_disable_image (f
, img
);
1960 else if (EQ (conversion
, Qlaplace
))
1962 else if (EQ (conversion
, Qemboss
))
1964 else if (CONSP (conversion
)
1965 && EQ (XCAR (conversion
), Qedge_detection
))
1968 tem
= XCDR (conversion
);
1970 x_edge_detection (f
, img
,
1971 Fplist_get (tem
, QCmatrix
),
1972 Fplist_get (tem
, QCcolor_adjustment
));
1978 /* Return the id of image with Lisp specification SPEC on frame F.
1979 SPEC must be a valid Lisp image specification (see valid_image_p). */
1982 lookup_image (f
, spec
)
1988 struct gcpro gcpro1
;
1991 /* F must be a window-system frame, and SPEC must be a valid image
1993 xassert (FRAME_WINDOW_P (f
));
1994 xassert (valid_image_p (spec
));
1998 /* Look up SPEC in the hash table of the image cache. */
1999 hash
= sxhash (spec
, 0);
2000 img
= search_image_cache (f
, spec
, hash
);
2001 if (img
&& img
->load_failed_p
)
2003 free_image (f
, img
);
2007 /* If not found, create a new image and cache it. */
2010 extern Lisp_Object Qpostscript
;
2013 img
= make_image (spec
, hash
);
2014 cache_image (f
, img
);
2015 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2016 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2017 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2019 /* If we can't load the image, and we don't have a width and
2020 height, use some arbitrary width and height so that we can
2021 draw a rectangle for it. */
2022 if (img
->load_failed_p
)
2026 value
= image_spec_value (spec
, QCwidth
, NULL
);
2027 img
->width
= (INTEGERP (value
)
2028 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2029 value
= image_spec_value (spec
, QCheight
, NULL
);
2030 img
->height
= (INTEGERP (value
)
2031 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2035 /* Handle image type independent image attributes
2036 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2037 `:background COLOR'. */
2038 Lisp_Object ascent
, margin
, relief
, bg
;
2040 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2041 if (INTEGERP (ascent
))
2042 img
->ascent
= XFASTINT (ascent
);
2043 else if (EQ (ascent
, Qcenter
))
2044 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2046 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2047 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2048 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2049 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2050 && INTEGERP (XCDR (margin
)))
2052 if (XINT (XCAR (margin
)) > 0)
2053 img
->hmargin
= XFASTINT (XCAR (margin
));
2054 if (XINT (XCDR (margin
)) > 0)
2055 img
->vmargin
= XFASTINT (XCDR (margin
));
2058 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2059 if (INTEGERP (relief
))
2061 img
->relief
= XINT (relief
);
2062 img
->hmargin
+= abs (img
->relief
);
2063 img
->vmargin
+= abs (img
->relief
);
2066 if (! img
->background_valid
)
2068 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2072 = x_alloc_image_color (f
, img
, bg
,
2073 FRAME_BACKGROUND_PIXEL (f
));
2074 img
->background_valid
= 1;
2078 /* Do image transformations and compute masks, unless we
2079 don't have the image yet. */
2080 if (!EQ (*img
->type
->type
, Qpostscript
))
2081 postprocess_image (f
, img
);
2087 /* We're using IMG, so set its timestamp to `now'. */
2088 EMACS_GET_TIME (now
);
2089 img
->timestamp
= EMACS_SECS (now
);
2093 /* Value is the image id. */
2098 /* Cache image IMG in the image cache of frame F. */
2101 cache_image (f
, img
)
2105 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
2108 /* Find a free slot in c->images. */
2109 for (i
= 0; i
< c
->used
; ++i
)
2110 if (c
->images
[i
] == NULL
)
2113 /* If no free slot found, maybe enlarge c->images. */
2114 if (i
== c
->used
&& c
->used
== c
->size
)
2117 c
->images
= (struct image
**) xrealloc (c
->images
,
2118 c
->size
* sizeof *c
->images
);
2121 /* Add IMG to c->images, and assign IMG an id. */
2127 /* Add IMG to the cache's hash table. */
2128 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2129 img
->next
= c
->buckets
[i
];
2131 img
->next
->prev
= img
;
2133 c
->buckets
[i
] = img
;
2137 /* Call FN on every image in the image cache of frame F. Used to mark
2138 Lisp Objects in the image cache. */
2141 forall_images_in_image_cache (f
, fn
)
2143 void (*fn
) P_ ((struct image
*img
));
2145 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
2147 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
2151 for (i
= 0; i
< c
->used
; ++i
)
2160 /***********************************************************************
2161 X / MAC / W32 support code
2162 ***********************************************************************/
2166 /* Macro for defining functions that will be loaded from image DLLs. */
2167 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2169 /* Macro for loading those image functions from the library. */
2170 #define LOAD_IMGLIB_FN(lib,func) { \
2171 fn_##func = (void *) GetProcAddress (lib, #func); \
2172 if (!fn_##func) return 0; \
2175 /* Load a DLL implementing an image type.
2176 The `image-library-alist' variable associates a symbol,
2177 identifying an image type, to a list of possible filenames.
2178 The function returns NULL if no library could be loaded for
2179 the given image type, or if the library was previously loaded;
2180 else the handle of the DLL. */
2182 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2184 HMODULE library
= NULL
;
2186 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2188 Lisp_Object dlls
= Fassq (type
, libraries
);
2191 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2193 CHECK_STRING_CAR (dlls
);
2194 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2202 #endif /* HAVE_NTGUI */
2204 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2205 XImagePtr
*, Pixmap
*));
2206 static void x_destroy_x_image
P_ ((XImagePtr
));
2207 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2210 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2211 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2212 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2213 via xmalloc. Print error messages via image_error if an error
2214 occurs. Value is non-zero if successful.
2216 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2217 should indicate the bit depth of the image. */
2220 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2222 int width
, height
, depth
;
2226 #ifdef HAVE_X_WINDOWS
2227 Display
*display
= FRAME_X_DISPLAY (f
);
2228 Window window
= FRAME_X_WINDOW (f
);
2229 Screen
*screen
= FRAME_X_SCREEN (f
);
2231 xassert (interrupt_input_blocked
);
2234 depth
= DefaultDepthOfScreen (screen
);
2235 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2236 depth
, ZPixmap
, 0, NULL
, width
, height
,
2237 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2240 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2244 /* Allocate image raster. */
2245 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2247 /* Allocate a pixmap of the same size. */
2248 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2249 if (*pixmap
== NO_PIXMAP
)
2251 x_destroy_x_image (*ximg
);
2253 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2258 #endif /* HAVE_X_WINDOWS */
2262 BITMAPINFOHEADER
*header
;
2264 int scanline_width_bits
;
2266 int palette_colors
= 0;
2271 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2272 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2274 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2278 scanline_width_bits
= width
* depth
;
2279 remainder
= scanline_width_bits
% 32;
2282 scanline_width_bits
+= 32 - remainder
;
2284 /* Bitmaps with a depth less than 16 need a palette. */
2285 /* BITMAPINFO structure already contains the first RGBQUAD. */
2287 palette_colors
= 1 << depth
- 1;
2289 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2292 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2296 header
= &((*ximg
)->info
.bmiHeader
);
2297 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2298 header
->biSize
= sizeof (*header
);
2299 header
->biWidth
= width
;
2300 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2301 header
->biPlanes
= 1;
2302 header
->biBitCount
= depth
;
2303 header
->biCompression
= BI_RGB
;
2304 header
->biClrUsed
= palette_colors
;
2306 /* TODO: fill in palette. */
2309 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2310 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2311 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2312 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2313 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2314 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2315 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2316 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2319 hdc
= get_frame_dc (f
);
2321 /* Create a DIBSection and raster array for the bitmap,
2322 and store its handle in *pixmap. */
2323 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2324 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2325 /* casting avoids a GCC warning */
2326 (void **)&((*ximg
)->data
), NULL
, 0);
2328 /* Realize display palette and garbage all frames. */
2329 release_frame_dc (f
, hdc
);
2331 if (*pixmap
== NULL
)
2333 DWORD err
= GetLastError();
2334 Lisp_Object errcode
;
2335 /* All system errors are < 10000, so the following is safe. */
2336 XSETINT (errcode
, (int) err
);
2337 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2338 x_destroy_x_image (*ximg
);
2344 #endif /* HAVE_NTGUI */
2347 Display
*display
= FRAME_X_DISPLAY (f
);
2348 Window window
= FRAME_X_WINDOW (f
);
2350 xassert (interrupt_input_blocked
);
2352 /* Allocate a pixmap of the same size. */
2353 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2354 if (*pixmap
== NO_PIXMAP
)
2357 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2361 #if !USE_MAC_IMAGE_IO
2362 LockPixels (GetGWorldPixMap (*pixmap
));
2371 /* Destroy XImage XIMG. Free XIMG->data. */
2374 x_destroy_x_image (ximg
)
2377 xassert (interrupt_input_blocked
);
2380 #ifdef HAVE_X_WINDOWS
2383 XDestroyImage (ximg
);
2384 #endif /* HAVE_X_WINDOWS */
2386 /* Data will be freed by DestroyObject. */
2389 #endif /* HAVE_NTGUI */
2391 XDestroyImage (ximg
);
2397 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2398 are width and height of both the image and pixmap. */
2401 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2407 #ifdef HAVE_X_WINDOWS
2410 xassert (interrupt_input_blocked
);
2411 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2412 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2413 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2414 #endif /* HAVE_X_WINDOWS */
2417 #if 0 /* I don't think this is necessary looking at where it is used. */
2418 HDC hdc
= get_frame_dc (f
);
2419 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2420 release_frame_dc (f
, hdc
);
2422 #endif /* HAVE_NTGUI */
2425 xassert (ximg
== pixmap
);
2430 /***********************************************************************
2432 ***********************************************************************/
2434 static unsigned char *slurp_file
P_ ((char *, int *));
2437 /* Find image file FILE. Look in data-directory, then
2438 x-bitmap-file-path. Value is the encoded full name of the file
2439 found, or nil if not found. */
2442 x_find_image_file (file
)
2445 Lisp_Object file_found
, search_path
;
2446 struct gcpro gcpro1
, gcpro2
;
2450 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2451 GCPRO2 (file_found
, search_path
);
2453 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2454 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2460 file_found
= ENCODE_FILE (file_found
);
2469 /* Read FILE into memory. Value is a pointer to a buffer allocated
2470 with xmalloc holding FILE's contents. Value is null if an error
2471 occurred. *SIZE is set to the size of the file. */
2473 static unsigned char *
2474 slurp_file (file
, size
)
2479 unsigned char *buf
= NULL
;
2482 if (stat (file
, &st
) == 0
2483 && (fp
= fopen (file
, "rb")) != NULL
2484 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2485 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2508 /***********************************************************************
2509 MAC Image Load Functions
2510 ***********************************************************************/
2512 #if USE_MAC_IMAGE_IO
2514 image_load_image_io (f
, img
, type
)
2519 CFDictionaryRef options
, src_props
= NULL
, props
= NULL
;
2520 CFStringRef keys
[2];
2521 CFTypeRef values
[2];
2522 Lisp_Object specified_file
, specified_data
;
2523 CGImageSourceRef source
= NULL
;
2525 CGImageRef image
= NULL
;
2526 int loop_count
= -1;
2527 double delay_time
= -1.0;
2529 XImagePtr ximg
= NULL
;
2530 CGContextRef context
;
2532 int has_alpha_p
, gif_p
;
2534 gif_p
= UTTypeEqual (type
, kUTTypeGIF
);
2536 keys
[0] = kCGImageSourceTypeIdentifierHint
;
2537 values
[0] = (CFTypeRef
) type
;
2538 keys
[1] = kCGImageSourceShouldCache
;
2539 values
[1] = (CFTypeRef
) kCFBooleanFalse
;
2540 options
= CFDictionaryCreate (NULL
, (const void **) keys
,
2541 (const void **) values
,
2542 sizeof (keys
) / sizeof (keys
[0]),
2543 &kCFTypeDictionaryKeyCallBacks
,
2544 &kCFTypeDictionaryValueCallBacks
);
2545 if (options
== NULL
)
2547 image_error ("Error creating options for image `%s'", img
->spec
, Qnil
);
2551 /* Open the file. */
2552 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2553 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2555 if (NILP (specified_data
))
2561 file
= x_find_image_file (specified_file
);
2562 if (!STRINGP (file
))
2564 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2567 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2570 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2571 kCFURLPOSIXPathStyle
, 0);
2575 source
= CGImageSourceCreateWithURL (url
, NULL
);
2582 CFDataRef data
= CFDataCreate (NULL
, SDATA (specified_data
),
2583 SBYTES (specified_data
));
2587 source
= CGImageSourceCreateWithData (data
, options
);
2591 CFRelease (options
);
2595 CFStringRef real_type
= CGImageSourceGetType (source
);
2597 if (real_type
&& UTTypeEqual (type
, real_type
))
2598 src_props
= CGImageSourceCopyProperties (source
, NULL
);
2603 count
= CGImageSourceGetCount (source
);
2606 Lisp_Object image
= image_spec_value (img
->spec
, QCindex
, NULL
);
2608 if (INTEGERP (image
))
2609 ino
= XFASTINT (image
);
2611 if (ino
>= 0 && ino
< count
)
2613 props
= CGImageSourceCopyPropertiesAtIndex (source
, ino
, NULL
);
2615 image
= CGImageSourceCreateImageAtIndex (source
, ino
, NULL
);
2624 CFRelease (src_props
);
2627 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2632 CFBooleanRef boolean
;
2634 if (CFDictionaryGetValueIfPresent (props
, kCGImagePropertyHasAlpha
,
2635 (const void **) &boolean
))
2636 has_alpha_p
= CFBooleanGetValue (boolean
);
2639 CFDictionaryRef dict
;
2642 dict
= CFDictionaryGetValue (src_props
,
2643 kCGImagePropertyGIFDictionary
);
2645 && CFDictionaryGetValueIfPresent (dict
,
2646 kCGImagePropertyGIFLoopCount
,
2647 (const void **) &number
))
2648 CFNumberGetValue (number
, kCFNumberIntType
, &loop_count
);
2650 dict
= CFDictionaryGetValue (props
, kCGImagePropertyGIFDictionary
);
2652 && CFDictionaryGetValueIfPresent (dict
,
2653 kCGImagePropertyGIFDelayTime
,
2654 (const void **) &number
))
2655 CFNumberGetValue (number
, kCFNumberDoubleType
, &delay_time
);
2657 CFRelease (src_props
);
2661 width
= img
->width
= CGImageGetWidth (image
);
2662 height
= img
->height
= CGImageGetHeight (image
);
2664 if (!check_image_size (f
, width
, height
))
2666 CGImageRelease (image
);
2667 image_error ("Invalid image size", Qnil
, Qnil
);
2671 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2673 CGImageRelease (image
);
2674 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
2677 rectangle
= CGRectMake (0, 0, width
, height
);
2679 context
= CGBitmapContextCreate (ximg
->data
, ximg
->width
, ximg
->height
, 8,
2680 ximg
->bytes_per_line
,
2681 mac_cg_color_space_rgb
,
2682 kCGImageAlphaNoneSkipFirst
2683 | kCGBitmapByteOrder32Host
);
2686 Lisp_Object specified_bg
;
2689 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2690 if (!STRINGP (specified_bg
)
2691 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2693 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2694 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2695 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2696 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2698 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2699 color
.green
/ 65535.0,
2700 color
.blue
/ 65535.0, 1.0);
2701 CGContextFillRect (context
, rectangle
);
2703 CGContextDrawImage (context
, rectangle
, image
);
2704 CGContextRelease (context
);
2705 CGImageRelease (image
);
2707 /* Save GIF image extension data for `image-extension-data'.
2708 Format is (count IMAGES
2709 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2710 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2713 img
->data
.lisp_val
= Qnil
;
2714 if (delay_time
>= 0)
2716 Lisp_Object gce
= make_uninit_string (4);
2717 int centisec
= delay_time
* 100.0 + 0.5;
2719 /* Fill the delay time field. */
2720 SSET (gce
, 1, centisec
& 0xff);
2721 SSET (gce
, 2, (centisec
>> 8) & 0xff);
2722 /* We don't know about other fields. */
2725 img
->data
.lisp_val
= Fcons (make_number (0xf9),
2727 img
->data
.lisp_val
));
2729 if (loop_count
>= 0)
2731 Lisp_Object data_sub_block
= make_uninit_string (3);
2733 SSET (data_sub_block
, 0, 0x01);
2734 SSET (data_sub_block
, 1, loop_count
& 0xff);
2735 SSET (data_sub_block
, 2, (loop_count
>> 8) & 0xff);
2736 img
->data
.lisp_val
= Fcons (make_number (0),
2737 Fcons (data_sub_block
,
2738 img
->data
.lisp_val
));
2739 img
->data
.lisp_val
= Fcons (make_number (0xff),
2740 Fcons (build_string ("NETSCAPE2.0"),
2741 img
->data
.lisp_val
));
2744 img
->data
.lisp_val
= Fcons (Qcount
,
2745 Fcons (make_number (count
),
2746 img
->data
.lisp_val
));
2749 /* Maybe fill in the background field while we have ximg handy. */
2750 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2751 IMAGE_BACKGROUND (img
, f
, ximg
);
2753 /* Put the image into the pixmap. */
2754 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2755 x_destroy_x_image (ximg
);
2758 #else /* !USE_MAC_IMAGE_IO */
2759 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2762 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2766 find_image_fsspec (specified_file
, file
, fss
)
2767 Lisp_Object specified_file
, *file
;
2773 *file
= x_find_image_file (specified_file
);
2774 if (!STRINGP (*file
))
2775 return fnfErr
; /* file or directory not found;
2776 incomplete pathname */
2777 /* Try to open the image file. */
2778 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2779 SBYTES (*file
), typeFSS
, &desc
);
2782 #if TARGET_API_MAC_CARBON
2783 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2785 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2787 AEDisposeDesc (&desc
);
2793 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2800 ComponentResult err
;
2801 GraphicsImportComponent gi
;
2804 ImageDescriptionHandle desc_handle
;
2805 short draw_all_pixels
;
2806 Lisp_Object specified_bg
;
2811 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2814 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2819 /* read from file system spec */
2820 err
= GraphicsImportSetDataFile (gi
, fss
);
2823 image_error ("Cannot set fsspec to graphics importer for '%s'",
2830 /* read from data handle */
2831 err
= GraphicsImportSetDataHandle (gi
, dh
);
2834 image_error ("Cannot set data handle to graphics importer for `%s'",
2839 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2840 if (err
!= noErr
|| desc_handle
== NULL
)
2842 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2845 width
= img
->width
= (*desc_handle
)->width
;
2846 height
= img
->height
= (*desc_handle
)->height
;
2847 DisposeHandle ((Handle
)desc_handle
);
2849 if (!check_image_size (f
, width
, height
))
2851 image_error ("Invalid image size", Qnil
, Qnil
);
2855 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2857 /* Don't check the error code here. It may have an undocumented
2861 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2865 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2867 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2868 if (!STRINGP (specified_bg
) ||
2869 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2871 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2872 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2873 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2874 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2878 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2880 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2885 GetGWorld (&old_port
, &old_gdh
);
2886 SetGWorld (ximg
, NULL
);
2887 bg_color
.red
= color
.red
;
2888 bg_color
.green
= color
.green
;
2889 bg_color
.blue
= color
.blue
;
2890 RGBBackColor (&bg_color
);
2891 #if TARGET_API_MAC_CARBON
2892 GetPortBounds (ximg
, &rect
);
2895 EraseRect (&(ximg
->portRect
));
2897 SetGWorld (old_port
, old_gdh
);
2899 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2900 GraphicsImportDraw (gi
);
2901 CloseComponent (gi
);
2903 /* Maybe fill in the background field while we have ximg handy. */
2904 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2905 IMAGE_BACKGROUND (img
, f
, ximg
);
2907 /* Put the image into the pixmap. */
2908 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2909 x_destroy_x_image (ximg
);
2913 CloseComponent (gi
);
2918 /* Load an image using the QuickTime Graphics Importer.
2919 Note: The alpha channel does not work for PNG images. */
2921 image_load_quicktime (f
, img
, type
)
2926 Lisp_Object specified_file
;
2927 Lisp_Object specified_data
;
2930 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2931 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2933 if (NILP (specified_data
))
2935 /* Read from a file */
2939 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2943 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2945 image_error ("Cannot open `%s'", file
, Qnil
);
2948 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2952 /* Memory source! */
2956 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2959 image_error ("Cannot allocate data handle for `%s'",
2963 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2972 image_load_quartz2d (f
, img
, png_p
)
2977 Lisp_Object file
, specified_file
;
2978 Lisp_Object specified_data
, specified_bg
;
2979 struct gcpro gcpro1
;
2980 CGDataProviderRef source
;
2984 XImagePtr ximg
= NULL
;
2985 CGContextRef context
;
2988 /* Open the file. */
2989 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2990 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2995 if (NILP (specified_data
))
3000 file
= x_find_image_file (specified_file
);
3001 if (!STRINGP (file
))
3003 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3007 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
3008 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
3009 kCFURLPOSIXPathStyle
, 0);
3011 source
= CGDataProviderCreateWithURL (url
);
3015 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
3016 SBYTES (specified_data
), NULL
);
3018 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3020 image
= CGImageCreateWithPNGDataProvider (source
, NULL
, false,
3021 kCGRenderingIntentDefault
);
3024 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, false,
3025 kCGRenderingIntentDefault
);
3027 CGDataProviderRelease (source
);
3031 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
3034 width
= img
->width
= CGImageGetWidth (image
);
3035 height
= img
->height
= CGImageGetHeight (image
);
3037 if (!check_image_size (f
, width
, height
))
3039 CGImageRelease (image
);
3041 image_error ("Invalid image size", Qnil
, Qnil
);
3047 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3048 if (!STRINGP (specified_bg
) ||
3049 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
3051 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
3052 color
.red
= RED16_FROM_ULONG (color
.pixel
);
3053 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
3054 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
3058 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
3060 CGImageRelease (image
);
3064 rectangle
= CGRectMake (0, 0, width
, height
);
3065 QDBeginCGContext (ximg
, &context
);
3068 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
3069 color
.green
/ 65535.0,
3070 color
.blue
/ 65535.0, 1.0);
3071 CGContextFillRect (context
, rectangle
);
3073 CGContextDrawImage (context
, rectangle
, image
);
3074 QDEndCGContext (ximg
, &context
);
3075 CGImageRelease (image
);
3077 /* Maybe fill in the background field while we have ximg handy. */
3078 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
3079 IMAGE_BACKGROUND (img
, f
, ximg
);
3081 /* Put the image into the pixmap. */
3082 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
3083 x_destroy_x_image (ximg
);
3088 #endif /* !USE_MAC_IMAGE_IO */
3093 /***********************************************************************
3095 ***********************************************************************/
3097 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
3098 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
3099 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
3100 unsigned char *, unsigned char *));
3101 static int xbm_image_p
P_ ((Lisp_Object object
));
3102 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
3103 unsigned char *, unsigned char *,
3104 int *, int *, unsigned char **));
3105 static int xbm_file_p
P_ ((Lisp_Object
));
3108 /* Indices of image specification fields in xbm_format, below. */
3110 enum xbm_keyword_index
3128 /* Vector of image_keyword structures describing the format
3129 of valid XBM image specifications. */
3131 static struct image_keyword xbm_format
[XBM_LAST
] =
3133 {":type", IMAGE_SYMBOL_VALUE
, 1},
3134 {":file", IMAGE_STRING_VALUE
, 0},
3135 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3136 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3137 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3138 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
3139 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
3140 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3141 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3142 {":relief", IMAGE_INTEGER_VALUE
, 0},
3143 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3144 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3145 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
3148 /* Structure describing the image type XBM. */
3150 static struct image_type xbm_type
=
3159 /* Tokens returned from xbm_scan. */
3168 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3169 A valid specification is a list starting with the symbol `image'
3170 The rest of the list is a property list which must contain an
3173 If the specification specifies a file to load, it must contain
3174 an entry `:file FILENAME' where FILENAME is a string.
3176 If the specification is for a bitmap loaded from memory it must
3177 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3178 WIDTH and HEIGHT are integers > 0. DATA may be:
3180 1. a string large enough to hold the bitmap data, i.e. it must
3181 have a size >= (WIDTH + 7) / 8 * HEIGHT
3183 2. a bool-vector of size >= WIDTH * HEIGHT
3185 3. a vector of strings or bool-vectors, one for each line of the
3188 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3189 may not be specified in this case because they are defined in the
3192 Both the file and data forms may contain the additional entries
3193 `:background COLOR' and `:foreground COLOR'. If not present,
3194 foreground and background of the frame on which the image is
3195 displayed is used. */
3198 xbm_image_p (object
)
3201 struct image_keyword kw
[XBM_LAST
];
3203 bcopy (xbm_format
, kw
, sizeof kw
);
3204 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
3207 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
3209 if (kw
[XBM_FILE
].count
)
3211 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
3214 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
3216 /* In-memory XBM file. */
3217 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
3225 /* Entries for `:width', `:height' and `:data' must be present. */
3226 if (!kw
[XBM_WIDTH
].count
3227 || !kw
[XBM_HEIGHT
].count
3228 || !kw
[XBM_DATA
].count
)
3231 data
= kw
[XBM_DATA
].value
;
3232 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
3233 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
3235 /* Check type of data, and width and height against contents of
3241 /* Number of elements of the vector must be >= height. */
3242 if (XVECTOR (data
)->size
< height
)
3245 /* Each string or bool-vector in data must be large enough
3246 for one line of the image. */
3247 for (i
= 0; i
< height
; ++i
)
3249 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
3254 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
3257 else if (BOOL_VECTOR_P (elt
))
3259 if (XBOOL_VECTOR (elt
)->size
< width
)
3266 else if (STRINGP (data
))
3269 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
3272 else if (BOOL_VECTOR_P (data
))
3274 if (XBOOL_VECTOR (data
)->size
< width
* height
)
3285 /* Scan a bitmap file. FP is the stream to read from. Value is
3286 either an enumerator from enum xbm_token, or a character for a
3287 single-character token, or 0 at end of file. If scanning an
3288 identifier, store the lexeme of the identifier in SVAL. If
3289 scanning a number, store its value in *IVAL. */
3292 xbm_scan (s
, end
, sval
, ival
)
3293 unsigned char **s
, *end
;
3301 /* Skip white space. */
3302 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3307 else if (isdigit (c
))
3309 int value
= 0, digit
;
3311 if (c
== '0' && *s
< end
)
3314 if (c
== 'x' || c
== 'X')
3321 else if (c
>= 'a' && c
<= 'f')
3322 digit
= c
- 'a' + 10;
3323 else if (c
>= 'A' && c
<= 'F')
3324 digit
= c
- 'A' + 10;
3327 value
= 16 * value
+ digit
;
3330 else if (isdigit (c
))
3334 && (c
= *(*s
)++, isdigit (c
)))
3335 value
= 8 * value
+ c
- '0';
3342 && (c
= *(*s
)++, isdigit (c
)))
3343 value
= 10 * value
+ c
- '0';
3351 else if (isalpha (c
) || c
== '_')
3355 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3362 else if (c
== '/' && **s
== '*')
3364 /* C-style comment. */
3366 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3380 /* Create a Windows bitmap from X bitmap data. */
3382 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3384 static unsigned char swap_nibble
[16]
3385 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3386 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3387 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3388 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3390 unsigned char *bits
, *p
;
3393 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3394 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3395 bits
= (unsigned char *) alloca (height
* w2
);
3396 bzero (bits
, height
* w2
);
3397 for (i
= 0; i
< height
; i
++)
3400 for (j
= 0; j
< w1
; j
++)
3402 /* Bitswap XBM bytes to match how Windows does things. */
3403 unsigned char c
= *data
++;
3404 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3405 | (swap_nibble
[(c
>>4) & 0xf]));
3408 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3414 convert_mono_to_color_image (f
, img
, foreground
, background
)
3417 COLORREF foreground
, background
;
3419 HDC hdc
, old_img_dc
, new_img_dc
;
3420 HGDIOBJ old_prev
, new_prev
;
3423 hdc
= get_frame_dc (f
);
3424 old_img_dc
= CreateCompatibleDC (hdc
);
3425 new_img_dc
= CreateCompatibleDC (hdc
);
3426 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3427 release_frame_dc (f
, hdc
);
3428 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3429 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3430 /* Windows convention for mono bitmaps is black = background,
3431 white = foreground. */
3432 SetTextColor (new_img_dc
, background
);
3433 SetBkColor (new_img_dc
, foreground
);
3435 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3438 SelectObject (old_img_dc
, old_prev
);
3439 SelectObject (new_img_dc
, new_prev
);
3440 DeleteDC (old_img_dc
);
3441 DeleteDC (new_img_dc
);
3442 DeleteObject (img
->pixmap
);
3443 if (new_pixmap
== 0)
3444 fprintf (stderr
, "Failed to convert image to color.\n");
3446 img
->pixmap
= new_pixmap
;
3449 #define XBM_BIT_SHUFFLE(b) (~(b))
3453 #define XBM_BIT_SHUFFLE(b) (b)
3455 #endif /* HAVE_NTGUI */
3459 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
3463 RGB_PIXEL_COLOR fg
, bg
;
3464 int non_default_colors
;
3468 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3470 /* If colors were specified, transfer the bitmap to a color one. */
3471 if (non_default_colors
)
3472 convert_mono_to_color_image (f
, img
, fg
, bg
);
3475 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3478 img
->width
, img
->height
,
3480 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3481 #endif /* HAVE_NTGUI */
3486 /* Replacement for XReadBitmapFileData which isn't available under old
3487 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3488 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3489 the image. Return in *DATA the bitmap data allocated with xmalloc.
3490 Value is non-zero if successful. DATA null means just test if
3491 CONTENTS looks like an in-memory XBM file. */
3494 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3496 unsigned char *contents
, *end
;
3497 int *width
, *height
;
3498 unsigned char **data
;
3500 unsigned char *s
= contents
;
3501 char buffer
[BUFSIZ
];
3504 int bytes_per_line
, i
, nbytes
;
3510 LA1 = xbm_scan (&s, end, buffer, &value)
3512 #define expect(TOKEN) \
3513 if (LA1 != (TOKEN)) \
3518 #define expect_ident(IDENT) \
3519 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3524 *width
= *height
= -1;
3527 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3529 /* Parse defines for width, height and hot-spots. */
3533 expect_ident ("define");
3534 expect (XBM_TK_IDENT
);
3536 if (LA1
== XBM_TK_NUMBER
)
3538 char *p
= strrchr (buffer
, '_');
3539 p
= p
? p
+ 1 : buffer
;
3540 if (strcmp (p
, "width") == 0)
3542 else if (strcmp (p
, "height") == 0)
3545 expect (XBM_TK_NUMBER
);
3548 if (!check_image_size (f
, *width
, *height
))
3550 else if (data
== NULL
)
3553 /* Parse bits. Must start with `static'. */
3554 expect_ident ("static");
3555 if (LA1
== XBM_TK_IDENT
)
3557 if (strcmp (buffer
, "unsigned") == 0)
3560 expect_ident ("char");
3562 else if (strcmp (buffer
, "short") == 0)
3566 if (*width
% 16 && *width
% 16 < 9)
3569 else if (strcmp (buffer
, "char") == 0)
3577 expect (XBM_TK_IDENT
);
3583 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3584 nbytes
= bytes_per_line
* *height
;
3585 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3589 for (i
= 0; i
< nbytes
; i
+= 2)
3592 expect (XBM_TK_NUMBER
);
3594 *p
++ = XBM_BIT_SHUFFLE (val
);
3595 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3596 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3598 if (LA1
== ',' || LA1
== '}')
3606 for (i
= 0; i
< nbytes
; ++i
)
3609 expect (XBM_TK_NUMBER
);
3611 *p
++ = XBM_BIT_SHUFFLE (val
);
3613 if (LA1
== ',' || LA1
== '}')
3638 /* Load XBM image IMG which will be displayed on frame F from buffer
3639 CONTENTS. END is the end of the buffer. Value is non-zero if
3643 xbm_load_image (f
, img
, contents
, end
)
3646 unsigned char *contents
, *end
;
3649 unsigned char *data
;
3652 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3655 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3656 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3657 int non_default_colors
= 0;
3660 xassert (img
->width
> 0 && img
->height
> 0);
3662 /* Get foreground and background colors, maybe allocate colors. */
3663 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3666 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3667 non_default_colors
= 1;
3669 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3672 background
= x_alloc_image_color (f
, img
, value
, background
);
3673 img
->background
= background
;
3674 img
->background_valid
= 1;
3675 non_default_colors
= 1;
3678 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3679 foreground
, background
,
3680 non_default_colors
);
3683 if (img
->pixmap
== NO_PIXMAP
)
3685 x_clear_image (f
, img
);
3686 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3692 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3698 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3705 return (STRINGP (data
)
3706 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3713 /* Fill image IMG which is used on frame F with pixmap data. Value is
3714 non-zero if successful. */
3722 Lisp_Object file_name
;
3724 xassert (xbm_image_p (img
->spec
));
3726 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3727 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3728 if (STRINGP (file_name
))
3731 unsigned char *contents
;
3733 struct gcpro gcpro1
;
3735 file
= x_find_image_file (file_name
);
3737 if (!STRINGP (file
))
3739 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3744 contents
= slurp_file (SDATA (file
), &size
);
3745 if (contents
== NULL
)
3747 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3752 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3757 struct image_keyword fmt
[XBM_LAST
];
3759 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3760 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3761 int non_default_colors
= 0;
3764 int in_memory_file_p
= 0;
3766 /* See if data looks like an in-memory XBM file. */
3767 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3768 in_memory_file_p
= xbm_file_p (data
);
3770 /* Parse the image specification. */
3771 bcopy (xbm_format
, fmt
, sizeof fmt
);
3772 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3775 /* Get specified width, and height. */
3776 if (!in_memory_file_p
)
3778 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3779 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3780 xassert (img
->width
> 0 && img
->height
> 0);
3783 /* Get foreground and background colors, maybe allocate colors. */
3784 if (fmt
[XBM_FOREGROUND
].count
3785 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3787 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3789 non_default_colors
= 1;
3792 if (fmt
[XBM_BACKGROUND
].count
3793 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3795 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3797 non_default_colors
= 1;
3800 if (in_memory_file_p
)
3801 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3810 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3812 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3813 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3815 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3817 bcopy (SDATA (line
), p
, nbytes
);
3819 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3822 else if (STRINGP (data
))
3823 bits
= SDATA (data
);
3825 bits
= XBOOL_VECTOR (data
)->data
;
3831 /* Windows mono bitmaps are reversed compared with X. */
3832 invertedBits
= bits
;
3833 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3835 bits
= (char *) alloca(nbytes
);
3836 for (i
= 0; i
< nbytes
; i
++)
3837 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3840 /* Create the pixmap. */
3842 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3843 foreground
, background
,
3844 non_default_colors
);
3849 image_error ("Unable to create pixmap for XBM image `%s'",
3851 x_clear_image (f
, img
);
3861 /***********************************************************************
3863 ***********************************************************************/
3865 #if defined (HAVE_XPM) || defined (MAC_OS)
3867 static int xpm_image_p
P_ ((Lisp_Object object
));
3868 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3869 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3871 #endif /* HAVE_XPM || MAC_OS */
3875 /* Indicate to xpm.h that we don't have Xlib. */
3877 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3878 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3879 #define XColor xpm_XColor
3880 #define XImage xpm_XImage
3881 #define Display xpm_Display
3882 #define PIXEL_ALREADY_TYPEDEFED
3883 #include "X11/xpm.h"
3888 #undef PIXEL_ALREADY_TYPEDEFED
3890 #include "X11/xpm.h"
3891 #endif /* HAVE_NTGUI */
3892 #endif /* HAVE_XPM */
3894 #if defined (HAVE_XPM) || defined (MAC_OS)
3895 /* The symbol `xpm' identifying XPM-format images. */
3899 /* Indices of image specification fields in xpm_format, below. */
3901 enum xpm_keyword_index
3917 /* Vector of image_keyword structures describing the format
3918 of valid XPM image specifications. */
3920 static struct image_keyword xpm_format
[XPM_LAST
] =
3922 {":type", IMAGE_SYMBOL_VALUE
, 1},
3923 {":file", IMAGE_STRING_VALUE
, 0},
3924 {":data", IMAGE_STRING_VALUE
, 0},
3925 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3926 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3927 {":relief", IMAGE_INTEGER_VALUE
, 0},
3928 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3929 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3930 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3931 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3932 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3935 /* Structure describing the image type XPM. */
3937 static struct image_type xpm_type
=
3946 #ifdef HAVE_X_WINDOWS
3948 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3949 functions for allocating image colors. Our own functions handle
3950 color allocation failures more gracefully than the ones on the XPM
3953 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3954 #define ALLOC_XPM_COLORS
3956 #endif /* HAVE_X_WINDOWS */
3958 #ifdef ALLOC_XPM_COLORS
3960 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3961 static void xpm_free_color_cache
P_ ((void));
3962 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3963 static int xpm_color_bucket
P_ ((char *));
3964 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3967 /* An entry in a hash table used to cache color definitions of named
3968 colors. This cache is necessary to speed up XPM image loading in
3969 case we do color allocations ourselves. Without it, we would need
3970 a call to XParseColor per pixel in the image. */
3972 struct xpm_cached_color
3974 /* Next in collision chain. */
3975 struct xpm_cached_color
*next
;
3977 /* Color definition (RGB and pixel color). */
3984 /* The hash table used for the color cache, and its bucket vector
3987 #define XPM_COLOR_CACHE_BUCKETS 1001
3988 struct xpm_cached_color
**xpm_color_cache
;
3990 /* Initialize the color cache. */
3993 xpm_init_color_cache (f
, attrs
)
3995 XpmAttributes
*attrs
;
3997 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3998 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3999 memset (xpm_color_cache
, 0, nbytes
);
4000 init_color_table ();
4002 if (attrs
->valuemask
& XpmColorSymbols
)
4007 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
4008 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4009 attrs
->colorsymbols
[i
].value
, &color
))
4011 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
4013 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
4018 /* Free the color cache. */
4021 xpm_free_color_cache ()
4023 struct xpm_cached_color
*p
, *next
;
4026 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
4027 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
4033 xfree (xpm_color_cache
);
4034 xpm_color_cache
= NULL
;
4035 free_color_table ();
4038 /* Return the bucket index for color named COLOR_NAME in the color
4042 xpm_color_bucket (color_name
)
4048 for (s
= color_name
; *s
; ++s
)
4050 return h
%= XPM_COLOR_CACHE_BUCKETS
;
4054 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4055 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4058 static struct xpm_cached_color
*
4059 xpm_cache_color (f
, color_name
, color
, bucket
)
4066 struct xpm_cached_color
*p
;
4069 bucket
= xpm_color_bucket (color_name
);
4071 nbytes
= sizeof *p
+ strlen (color_name
);
4072 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
4073 strcpy (p
->name
, color_name
);
4075 p
->next
= xpm_color_cache
[bucket
];
4076 xpm_color_cache
[bucket
] = p
;
4080 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4081 return the cached definition in *COLOR. Otherwise, make a new
4082 entry in the cache and allocate the color. Value is zero if color
4083 allocation failed. */
4086 xpm_lookup_color (f
, color_name
, color
)
4091 struct xpm_cached_color
*p
;
4092 int h
= xpm_color_bucket (color_name
);
4094 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
4095 if (strcmp (p
->name
, color_name
) == 0)
4100 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4103 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
4105 p
= xpm_cache_color (f
, color_name
, color
, h
);
4107 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4108 with transparency, and it's useful. */
4109 else if (strcmp ("opaque", color_name
) == 0)
4111 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
4112 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
4113 p
= xpm_cache_color (f
, color_name
, color
, h
);
4120 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4121 CLOSURE is a pointer to the frame on which we allocate the
4122 color. Return in *COLOR the allocated color. Value is non-zero
4126 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
4133 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
4137 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4138 is a pointer to the frame on which we allocate the color. Value is
4139 non-zero if successful. */
4142 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
4152 #endif /* ALLOC_XPM_COLORS */
4157 /* XPM library details. */
4159 DEF_IMGLIB_FN (XpmFreeAttributes
);
4160 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
4161 DEF_IMGLIB_FN (XpmReadFileToImage
);
4162 DEF_IMGLIB_FN (XImageFree
);
4165 init_xpm_functions (Lisp_Object libraries
)
4169 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
4172 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
4173 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
4174 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
4175 LOAD_IMGLIB_FN (library
, XImageFree
);
4179 #endif /* HAVE_NTGUI */
4182 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4183 for XPM images. Such a list must consist of conses whose car and
4187 xpm_valid_color_symbols_p (color_symbols
)
4188 Lisp_Object color_symbols
;
4190 while (CONSP (color_symbols
))
4192 Lisp_Object sym
= XCAR (color_symbols
);
4194 || !STRINGP (XCAR (sym
))
4195 || !STRINGP (XCDR (sym
)))
4197 color_symbols
= XCDR (color_symbols
);
4200 return NILP (color_symbols
);
4204 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4207 xpm_image_p (object
)
4210 struct image_keyword fmt
[XPM_LAST
];
4211 bcopy (xpm_format
, fmt
, sizeof fmt
);
4212 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
4213 /* Either `:file' or `:data' must be present. */
4214 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
4215 /* Either no `:color-symbols' or it's a list of conses
4216 whose car and cdr are strings. */
4217 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
4218 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
4221 #endif /* HAVE_XPM || MAC_OS */
4223 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4225 x_create_bitmap_from_xpm_data (f
, bits
)
4229 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4231 XpmAttributes attrs
;
4232 Pixmap bitmap
, mask
;
4234 bzero (&attrs
, sizeof attrs
);
4236 attrs
.visual
= FRAME_X_VISUAL (f
);
4237 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4238 attrs
.valuemask
|= XpmVisual
;
4239 attrs
.valuemask
|= XpmColormap
;
4241 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4242 bits
, &bitmap
, &mask
, &attrs
);
4243 if (rc
!= XpmSuccess
)
4245 XpmFreeAttributes (&attrs
);
4249 id
= x_allocate_bitmap_record (f
);
4250 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
4251 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
4252 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
4253 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
4254 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
4255 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
4256 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
4257 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
4259 XpmFreeAttributes (&attrs
);
4262 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4264 /* Load image IMG which will be displayed on frame F. Value is
4265 non-zero if successful. */
4275 XpmAttributes attrs
;
4276 Lisp_Object specified_file
, color_symbols
;
4279 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
4280 #endif /* HAVE_NTGUI */
4282 /* Configure the XPM lib. Use the visual of frame F. Allocate
4283 close colors. Return colors allocated. */
4284 bzero (&attrs
, sizeof attrs
);
4287 attrs
.visual
= FRAME_X_VISUAL (f
);
4288 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4289 attrs
.valuemask
|= XpmVisual
;
4290 attrs
.valuemask
|= XpmColormap
;
4291 #endif /* HAVE_NTGUI */
4293 #ifdef ALLOC_XPM_COLORS
4294 /* Allocate colors with our own functions which handle
4295 failing color allocation more gracefully. */
4296 attrs
.color_closure
= f
;
4297 attrs
.alloc_color
= xpm_alloc_color
;
4298 attrs
.free_colors
= xpm_free_colors
;
4299 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
4300 #else /* not ALLOC_XPM_COLORS */
4301 /* Let the XPM lib allocate colors. */
4302 attrs
.valuemask
|= XpmReturnAllocPixels
;
4303 #ifdef XpmAllocCloseColors
4304 attrs
.alloc_close_colors
= 1;
4305 attrs
.valuemask
|= XpmAllocCloseColors
;
4306 #else /* not XpmAllocCloseColors */
4307 attrs
.closeness
= 600;
4308 attrs
.valuemask
|= XpmCloseness
;
4309 #endif /* not XpmAllocCloseColors */
4310 #endif /* ALLOC_XPM_COLORS */
4312 /* If image specification contains symbolic color definitions, add
4313 these to `attrs'. */
4314 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4315 if (CONSP (color_symbols
))
4318 XpmColorSymbol
*xpm_syms
;
4321 attrs
.valuemask
|= XpmColorSymbols
;
4323 /* Count number of symbols. */
4324 attrs
.numsymbols
= 0;
4325 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4328 /* Allocate an XpmColorSymbol array. */
4329 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4330 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4331 bzero (xpm_syms
, size
);
4332 attrs
.colorsymbols
= xpm_syms
;
4334 /* Fill the color symbol array. */
4335 for (tail
= color_symbols
, i
= 0;
4337 ++i
, tail
= XCDR (tail
))
4339 Lisp_Object name
= XCAR (XCAR (tail
));
4340 Lisp_Object color
= XCDR (XCAR (tail
));
4341 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4342 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4343 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4344 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4348 /* Create a pixmap for the image, either from a file, or from a
4349 string buffer containing data in the same format as an XPM file. */
4350 #ifdef ALLOC_XPM_COLORS
4351 xpm_init_color_cache (f
, &attrs
);
4354 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4358 HDC frame_dc
= get_frame_dc (f
);
4359 hdc
= CreateCompatibleDC (frame_dc
);
4360 release_frame_dc (f
, frame_dc
);
4362 #endif /* HAVE_NTGUI */
4364 if (STRINGP (specified_file
))
4366 Lisp_Object file
= x_find_image_file (specified_file
);
4367 if (!STRINGP (file
))
4369 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4374 /* XpmReadFileToPixmap is not available in the Windows port of
4375 libxpm. But XpmReadFileToImage almost does what we want. */
4376 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4377 &xpm_image
, &xpm_mask
,
4380 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4381 SDATA (file
), &img
->pixmap
, &img
->mask
,
4383 #endif /* HAVE_NTGUI */
4387 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4389 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4390 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4391 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4392 &xpm_image
, &xpm_mask
,
4395 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4397 &img
->pixmap
, &img
->mask
,
4399 #endif /* HAVE_NTGUI */
4402 if (rc
== XpmSuccess
)
4404 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4405 img
->colors
= colors_in_color_table (&img
->ncolors
);
4406 #else /* not ALLOC_XPM_COLORS */
4410 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4411 plus some duplicate attributes. */
4412 if (xpm_image
&& xpm_image
->bitmap
)
4414 img
->pixmap
= xpm_image
->bitmap
;
4415 /* XImageFree in libXpm frees XImage struct without destroying
4416 the bitmap, which is what we want. */
4417 fn_XImageFree (xpm_image
);
4419 if (xpm_mask
&& xpm_mask
->bitmap
)
4421 /* The mask appears to be inverted compared with what we expect.
4422 TODO: invert our expectations. See other places where we
4423 have to invert bits because our idea of masks is backwards. */
4425 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4427 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4428 SelectObject (hdc
, old_obj
);
4430 img
->mask
= xpm_mask
->bitmap
;
4431 fn_XImageFree (xpm_mask
);
4436 #endif /* HAVE_NTGUI */
4438 /* Remember allocated colors. */
4439 img
->ncolors
= attrs
.nalloc_pixels
;
4440 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4441 * sizeof *img
->colors
);
4442 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4444 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4445 #ifdef DEBUG_X_COLORS
4446 register_color (img
->colors
[i
]);
4449 #endif /* not ALLOC_XPM_COLORS */
4451 img
->width
= attrs
.width
;
4452 img
->height
= attrs
.height
;
4453 xassert (img
->width
> 0 && img
->height
> 0);
4455 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4457 fn_XpmFreeAttributes (&attrs
);
4459 XpmFreeAttributes (&attrs
);
4460 #endif /* HAVE_NTGUI */
4466 #endif /* HAVE_NTGUI */
4471 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4474 case XpmFileInvalid
:
4475 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4479 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4482 case XpmColorFailed
:
4483 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4487 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4492 #ifdef ALLOC_XPM_COLORS
4493 xpm_free_color_cache ();
4495 return rc
== XpmSuccess
;
4498 #endif /* HAVE_XPM */
4502 /* XPM support functions for Mac OS where libxpm is not available.
4503 Only XPM version 3 (without any extensions) is supported. */
4505 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4506 const unsigned char **, int *));
4507 static Lisp_Object xpm_make_color_table_v
4508 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4509 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4510 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4512 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4513 const unsigned char *, int));
4514 static Lisp_Object xpm_make_color_table_h
4515 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4516 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4517 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4519 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4520 const unsigned char *, int));
4521 static int xpm_str_to_color_key
P_ ((const char *));
4522 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4523 const unsigned char *, const unsigned char *));
4525 /* Tokens returned from xpm_scan. */
4534 /* Scan an XPM data and return a character (< 256) or a token defined
4535 by enum xpm_token above. *S and END are the start (inclusive) and
4536 the end (exclusive) addresses of the data, respectively. Advance
4537 *S while scanning. If token is either XPM_TK_IDENT or
4538 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4539 length of the corresponding token, respectively. */
4542 xpm_scan (s
, end
, beg
, len
)
4543 const unsigned char **s
, *end
, **beg
;
4550 /* Skip white-space. */
4551 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4554 /* gnus-pointer.xpm uses '-' in its identifier.
4555 sb-dir-plus.xpm uses '+' in its identifier. */
4556 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4560 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4563 return XPM_TK_IDENT
;
4568 while (*s
< end
&& **s
!= '"')
4573 return XPM_TK_STRING
;
4577 if (*s
< end
&& **s
== '*')
4579 /* C-style comment. */
4583 while (*s
< end
&& *(*s
)++ != '*')
4586 while (*s
< end
&& **s
!= '/');
4600 /* Functions for color table lookup in XPM data. A key is a string
4601 specifying the color of each pixel in XPM data. A value is either
4602 an integer that specifies a pixel color, Qt that specifies
4603 transparency, or Qnil for the unspecified color. If the length of
4604 the key string is one, a vector is used as a table. Otherwise, a
4605 hash table is used. */
4608 xpm_make_color_table_v (put_func
, get_func
)
4609 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4610 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4612 *put_func
= xpm_put_color_table_v
;
4613 *get_func
= xpm_get_color_table_v
;
4614 return Fmake_vector (make_number (256), Qnil
);
4618 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4619 Lisp_Object color_table
;
4620 const unsigned char *chars_start
;
4624 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4628 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4629 Lisp_Object color_table
;
4630 const unsigned char *chars_start
;
4633 return XVECTOR (color_table
)->contents
[*chars_start
];
4637 xpm_make_color_table_h (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_h
;
4642 *get_func
= xpm_get_color_table_h
;
4643 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4644 make_float (DEFAULT_REHASH_SIZE
),
4645 make_float (DEFAULT_REHASH_THRESHOLD
),
4650 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4651 Lisp_Object color_table
;
4652 const unsigned char *chars_start
;
4656 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4658 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4660 hash_lookup (table
, chars
, &hash_code
);
4661 hash_put (table
, chars
, color
, hash_code
);
4665 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4666 Lisp_Object color_table
;
4667 const unsigned char *chars_start
;
4670 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4671 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4674 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4677 enum xpm_color_key
{
4685 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4688 xpm_str_to_color_key (s
)
4694 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4696 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4702 xpm_load_image (f
, img
, contents
, end
)
4705 const unsigned char *contents
, *end
;
4707 const unsigned char *s
= contents
, *beg
, *str
;
4708 unsigned char buffer
[BUFSIZ
];
4709 int width
, height
, x
, y
;
4710 int num_colors
, chars_per_pixel
;
4712 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4713 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4714 Lisp_Object frame
, color_symbols
, color_table
;
4715 int best_key
, have_mask
= 0;
4716 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4719 LA1 = xpm_scan (&s, end, &beg, &len)
4721 #define expect(TOKEN) \
4722 if (LA1 != (TOKEN)) \
4727 #define expect_ident(IDENT) \
4728 if (LA1 == XPM_TK_IDENT \
4729 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4734 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4738 expect_ident ("static");
4739 expect_ident ("char");
4741 expect (XPM_TK_IDENT
);
4746 expect (XPM_TK_STRING
);
4749 memcpy (buffer
, beg
, len
);
4751 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4752 &num_colors
, &chars_per_pixel
) != 4
4753 || width
<= 0 || height
<= 0
4754 || num_colors
<= 0 || chars_per_pixel
<= 0)
4757 if (!check_image_size (f
, width
, height
))
4759 image_error ("Invalid image size", Qnil
, Qnil
);
4765 XSETFRAME (frame
, f
);
4766 if (!NILP (Fxw_display_color_p (frame
)))
4767 best_key
= XPM_COLOR_KEY_C
;
4768 else if (!NILP (Fx_display_grayscale_p (frame
)))
4769 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4770 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4772 best_key
= XPM_COLOR_KEY_M
;
4774 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4775 if (chars_per_pixel
== 1)
4776 color_table
= xpm_make_color_table_v (&put_color_table
,
4779 color_table
= xpm_make_color_table_h (&put_color_table
,
4782 while (num_colors
-- > 0)
4784 unsigned char *color
, *max_color
;
4785 int key
, next_key
, max_key
= 0;
4786 Lisp_Object symbol_color
= Qnil
, color_val
;
4789 expect (XPM_TK_STRING
);
4790 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4792 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4793 buffer
[len
- chars_per_pixel
] = '\0';
4795 str
= strtok (buffer
, " \t");
4798 key
= xpm_str_to_color_key (str
);
4803 color
= strtok (NULL
, " \t");
4807 while ((str
= strtok (NULL
, " \t")) != NULL
)
4809 next_key
= xpm_str_to_color_key (str
);
4812 color
[strlen (color
)] = ' ';
4815 if (key
== XPM_COLOR_KEY_S
)
4817 if (NILP (symbol_color
))
4818 symbol_color
= build_string (color
);
4820 else if (max_key
< key
&& key
<= best_key
)
4830 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4832 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4834 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4836 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4838 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4840 color_val
= make_number (cdef
.pixel
);
4843 if (NILP (color_val
) && max_key
> 0)
4845 if (xstricmp (max_color
, "None") == 0)
4847 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4848 color_val
= make_number (cdef
.pixel
);
4850 if (!NILP (color_val
))
4851 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4856 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4857 &ximg
, &img
->pixmap
)
4858 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4859 &mask_img
, &img
->mask
))
4861 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4865 for (y
= 0; y
< height
; y
++)
4867 expect (XPM_TK_STRING
);
4869 if (len
< width
* chars_per_pixel
)
4871 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4873 Lisp_Object color_val
=
4874 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4876 XPutPixel (ximg
, x
, y
,
4877 (INTEGERP (color_val
) ? XINT (color_val
)
4878 : FRAME_FOREGROUND_PIXEL (f
)));
4879 XPutPixel (mask_img
, x
, y
,
4880 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4881 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4888 img
->height
= height
;
4890 /* Maybe fill in the background field while we have ximg handy. */
4891 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4892 IMAGE_BACKGROUND (img
, f
, ximg
);
4894 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4895 x_destroy_x_image (ximg
);
4898 /* Fill in the background_transparent field while we have the
4900 image_background_transparent (img
, f
, mask_img
);
4902 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4903 x_destroy_x_image (mask_img
);
4907 x_destroy_x_image (mask_img
);
4908 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4909 img
->mask
= NO_PIXMAP
;
4915 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4917 x_destroy_x_image (ximg
);
4918 x_destroy_x_image (mask_img
);
4919 x_clear_image (f
, img
);
4933 Lisp_Object file_name
;
4935 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4936 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4937 if (STRINGP (file_name
))
4940 unsigned char *contents
;
4942 struct gcpro gcpro1
;
4944 file
= x_find_image_file (file_name
);
4946 if (!STRINGP (file
))
4948 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4953 contents
= slurp_file (SDATA (file
), &size
);
4954 if (contents
== NULL
)
4956 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4961 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4969 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4970 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4971 SDATA (data
) + SBYTES (data
));
4981 /***********************************************************************
4983 ***********************************************************************/
4985 #ifdef COLOR_TABLE_SUPPORT
4987 /* An entry in the color table mapping an RGB color to a pixel color. */
4992 unsigned long pixel
;
4994 /* Next in color table collision list. */
4995 struct ct_color
*next
;
4998 /* The bucket vector size to use. Must be prime. */
5002 /* Value is a hash of the RGB color given by R, G, and B. */
5004 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5006 /* The color hash table. */
5008 struct ct_color
**ct_table
;
5010 /* Number of entries in the color table. */
5012 int ct_colors_allocated
;
5014 /* Initialize the color table. */
5019 int size
= CT_SIZE
* sizeof (*ct_table
);
5020 ct_table
= (struct ct_color
**) xmalloc (size
);
5021 bzero (ct_table
, size
);
5022 ct_colors_allocated
= 0;
5026 /* Free memory associated with the color table. */
5032 struct ct_color
*p
, *next
;
5034 for (i
= 0; i
< CT_SIZE
; ++i
)
5035 for (p
= ct_table
[i
]; p
; p
= next
)
5046 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5047 entry for that color already is in the color table, return the
5048 pixel color of that entry. Otherwise, allocate a new color for R,
5049 G, B, and make an entry in the color table. */
5051 static unsigned long
5052 lookup_rgb_color (f
, r
, g
, b
)
5056 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
5057 int i
= hash
% CT_SIZE
;
5059 Display_Info
*dpyinfo
;
5061 /* Handle TrueColor visuals specially, which improves performance by
5062 two orders of magnitude. Freeing colors on TrueColor visuals is
5063 a nop, and pixel colors specify RGB values directly. See also
5064 the Xlib spec, chapter 3.1. */
5065 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5066 if (dpyinfo
->red_bits
> 0)
5068 unsigned long pr
, pg
, pb
;
5070 /* Apply gamma-correction like normal color allocation does. */
5074 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
5075 gamma_correct (f
, &color
);
5076 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
5079 /* Scale down RGB values to the visual's bits per RGB, and shift
5080 them to the right position in the pixel color. Note that the
5081 original RGB values are 16-bit values, as usual in X. */
5082 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
5083 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
5084 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
5086 /* Assemble the pixel color. */
5087 return pr
| pg
| pb
;
5090 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5091 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
5097 #ifdef HAVE_X_WINDOWS
5106 cmap
= FRAME_X_COLORMAP (f
);
5107 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5110 ++ct_colors_allocated
;
5111 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5115 p
->pixel
= color
.pixel
;
5116 p
->next
= ct_table
[i
];
5120 return FRAME_FOREGROUND_PIXEL (f
);
5125 color
= PALETTERGB (r
, g
, b
);
5127 color
= RGB_TO_ULONG (r
, g
, b
);
5128 #endif /* HAVE_NTGUI */
5129 ++ct_colors_allocated
;
5130 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5135 p
->next
= ct_table
[i
];
5137 #endif /* HAVE_X_WINDOWS */
5145 /* Look up pixel color PIXEL which is used on frame F in the color
5146 table. If not already present, allocate it. Value is PIXEL. */
5148 static unsigned long
5149 lookup_pixel_color (f
, pixel
)
5151 unsigned long pixel
;
5153 int i
= pixel
% CT_SIZE
;
5156 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5157 if (p
->pixel
== pixel
)
5166 #ifdef HAVE_X_WINDOWS
5167 cmap
= FRAME_X_COLORMAP (f
);
5168 color
.pixel
= pixel
;
5169 x_query_color (f
, &color
);
5170 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5173 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
5174 color
.pixel
= pixel
;
5175 XQueryColor (NULL
, cmap
, &color
);
5176 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5178 #endif /* HAVE_X_WINDOWS */
5182 ++ct_colors_allocated
;
5184 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5189 p
->next
= ct_table
[i
];
5193 return FRAME_FOREGROUND_PIXEL (f
);
5199 /* Value is a vector of all pixel colors contained in the color table,
5200 allocated via xmalloc. Set *N to the number of colors. */
5202 static unsigned long *
5203 colors_in_color_table (n
)
5208 unsigned long *colors
;
5210 if (ct_colors_allocated
== 0)
5217 colors
= (unsigned long *) xmalloc (ct_colors_allocated
5219 *n
= ct_colors_allocated
;
5221 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
5222 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5223 colors
[j
++] = p
->pixel
;
5229 #else /* COLOR_TABLE_SUPPORT */
5231 static unsigned long
5232 lookup_rgb_color (f
, r
, g
, b
)
5236 unsigned long pixel
;
5239 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5240 gamma_correct (f
, &pixel
);
5244 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
5245 #endif /* HAVE_NTGUI */
5254 #endif /* COLOR_TABLE_SUPPORT */
5257 /***********************************************************************
5259 ***********************************************************************/
5261 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
5262 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
5263 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
5266 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
5267 #endif /* HAVE_NTGUI */
5269 /* Non-zero means draw a cross on images having `:conversion
5272 int cross_disabled_images
;
5274 /* Edge detection matrices for different edge-detection
5277 static int emboss_matrix
[9] = {
5279 2, -1, 0, /* y - 1 */
5281 0, 1, -2 /* y + 1 */
5284 static int laplace_matrix
[9] = {
5286 1, 0, 0, /* y - 1 */
5288 0, 0, -1 /* y + 1 */
5291 /* Value is the intensity of the color whose red/green/blue values
5294 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5297 /* On frame F, return an array of XColor structures describing image
5298 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5299 non-zero means also fill the red/green/blue members of the XColor
5300 structures. Value is a pointer to the array of XColors structures,
5301 allocated with xmalloc; it must be freed by the caller. */
5304 x_to_xcolors (f
, img
, rgb_p
)
5311 XImagePtr_or_DC ximg
;
5315 #endif /* HAVE_NTGUI */
5317 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5320 /* Get the X image IMG->pixmap. */
5321 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5322 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5324 /* Load the image into a memory device context. */
5325 hdc
= get_frame_dc (f
);
5326 ximg
= CreateCompatibleDC (hdc
);
5327 release_frame_dc (f
, hdc
);
5328 prev
= SelectObject (ximg
, img
->pixmap
);
5329 #endif /* HAVE_NTGUI */
5331 /* Fill the `pixel' members of the XColor array. I wished there
5332 were an easy and portable way to circumvent XGetPixel. */
5334 for (y
= 0; y
< img
->height
; ++y
)
5338 #ifdef HAVE_X_WINDOWS
5339 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5340 p
->pixel
= XGetPixel (ximg
, x
, y
);
5342 x_query_colors (f
, row
, img
->width
);
5346 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5348 /* W32_TODO: palette support needed here? */
5349 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5353 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5354 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5355 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5358 p
->red
= 256 * GetRValue (p
->pixel
);
5359 p
->green
= 256 * GetGValue (p
->pixel
);
5360 p
->blue
= 256 * GetBValue (p
->pixel
);
5361 #endif /* HAVE_NTGUI */
5364 #endif /* HAVE_X_WINDOWS */
5367 Destroy_Image (ximg
, prev
);
5374 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5375 created with CreateDIBSection, with the pointer to the bit values
5376 stored in ximg->data. */
5379 XPutPixel (ximg
, x
, y
, color
)
5384 int width
= ximg
->info
.bmiHeader
.biWidth
;
5385 int height
= ximg
->info
.bmiHeader
.biHeight
;
5386 unsigned char * pixel
;
5388 /* True color images. */
5389 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5391 int rowbytes
= width
* 3;
5392 /* Ensure scanlines are aligned on 4 byte boundaries. */
5394 rowbytes
+= 4 - (rowbytes
% 4);
5396 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5397 /* Windows bitmaps are in BGR order. */
5398 *pixel
= GetBValue (color
);
5399 *(pixel
+ 1) = GetGValue (color
);
5400 *(pixel
+ 2) = GetRValue (color
);
5402 /* Monochrome images. */
5403 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5405 int rowbytes
= width
/ 8;
5406 /* Ensure scanlines are aligned on 4 byte boundaries. */
5408 rowbytes
+= 4 - (rowbytes
% 4);
5409 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5410 /* Filter out palette info. */
5411 if (color
& 0x00ffffff)
5412 *pixel
= *pixel
| (1 << x
% 8);
5414 *pixel
= *pixel
& ~(1 << x
% 8);
5417 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5420 #endif /* HAVE_NTGUI */
5422 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5423 RGB members are set. F is the frame on which this all happens.
5424 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5427 x_from_xcolors (f
, img
, colors
)
5437 init_color_table ();
5439 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5442 for (y
= 0; y
< img
->height
; ++y
)
5443 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5445 unsigned long pixel
;
5446 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5447 XPutPixel (oimg
, x
, y
, pixel
);
5451 x_clear_image_1 (f
, img
, 1, 0, 1);
5453 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5454 x_destroy_x_image (oimg
);
5455 img
->pixmap
= pixmap
;
5456 #ifdef COLOR_TABLE_SUPPORT
5457 img
->colors
= colors_in_color_table (&img
->ncolors
);
5458 free_color_table ();
5459 #endif /* COLOR_TABLE_SUPPORT */
5463 /* On frame F, perform edge-detection on image IMG.
5465 MATRIX is a nine-element array specifying the transformation
5466 matrix. See emboss_matrix for an example.
5468 COLOR_ADJUST is a color adjustment added to each pixel of the
5472 x_detect_edges (f
, img
, matrix
, color_adjust
)
5475 int matrix
[9], color_adjust
;
5477 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5481 for (i
= sum
= 0; i
< 9; ++i
)
5482 sum
+= abs (matrix
[i
]);
5484 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5486 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5488 for (y
= 0; y
< img
->height
; ++y
)
5490 p
= COLOR (new, 0, y
);
5491 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5492 p
= COLOR (new, img
->width
- 1, y
);
5493 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5496 for (x
= 1; x
< img
->width
- 1; ++x
)
5498 p
= COLOR (new, x
, 0);
5499 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5500 p
= COLOR (new, x
, img
->height
- 1);
5501 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5504 for (y
= 1; y
< img
->height
- 1; ++y
)
5506 p
= COLOR (new, 1, y
);
5508 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5510 int r
, g
, b
, y1
, x1
;
5513 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5514 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5517 XColor
*t
= COLOR (colors
, x1
, y1
);
5518 r
+= matrix
[i
] * t
->red
;
5519 g
+= matrix
[i
] * t
->green
;
5520 b
+= matrix
[i
] * t
->blue
;
5523 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5524 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5525 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5526 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5531 x_from_xcolors (f
, img
, new);
5537 /* Perform the pre-defined `emboss' edge-detection on image IMG
5545 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5549 /* Transform image IMG which is used on frame F with a Laplace
5550 edge-detection algorithm. The result is an image that can be used
5551 to draw disabled buttons, for example. */
5558 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5562 /* Perform edge-detection on image IMG on frame F, with specified
5563 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5565 MATRIX must be either
5567 - a list of at least 9 numbers in row-major form
5568 - a vector of at least 9 numbers
5570 COLOR_ADJUST nil means use a default; otherwise it must be a
5574 x_edge_detection (f
, img
, matrix
, color_adjust
)
5577 Lisp_Object matrix
, color_adjust
;
5585 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5586 ++i
, matrix
= XCDR (matrix
))
5587 trans
[i
] = XFLOATINT (XCAR (matrix
));
5589 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5591 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5592 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5595 if (NILP (color_adjust
))
5596 color_adjust
= make_number (0xffff / 2);
5598 if (i
== 9 && NUMBERP (color_adjust
))
5599 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5603 /* Transform image IMG on frame F so that it looks disabled. */
5606 x_disable_image (f
, img
)
5610 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5612 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5614 int n_planes
= dpyinfo
->n_planes
;
5615 #endif /* HAVE_NTGUI */
5619 /* Color (or grayscale). Convert to gray, and equalize. Just
5620 drawing such images with a stipple can look very odd, so
5621 we're using this method instead. */
5622 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5624 const int h
= 15000;
5625 const int l
= 30000;
5627 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5631 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5632 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5633 p
->red
= p
->green
= p
->blue
= i2
;
5636 x_from_xcolors (f
, img
, colors
);
5639 /* Draw a cross over the disabled image, if we must or if we
5641 if (n_planes
< 2 || cross_disabled_images
)
5644 Display
*dpy
= FRAME_X_DISPLAY (f
);
5648 #define MaskForeground(f) PIX_MASK_DRAW
5650 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5653 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5654 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5655 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5656 img
->width
- 1, img
->height
- 1);
5657 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5663 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5664 XSetForeground (dpy
, gc
, MaskForeground (f
));
5665 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5666 img
->width
- 1, img
->height
- 1);
5667 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5675 hdc
= get_frame_dc (f
);
5676 bmpdc
= CreateCompatibleDC (hdc
);
5677 release_frame_dc (f
, hdc
);
5679 prev
= SelectObject (bmpdc
, img
->pixmap
);
5681 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5682 MoveToEx (bmpdc
, 0, 0, NULL
);
5683 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5684 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5685 LineTo (bmpdc
, img
->width
- 1, 0);
5689 SelectObject (bmpdc
, img
->mask
);
5690 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5691 MoveToEx (bmpdc
, 0, 0, NULL
);
5692 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5693 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5694 LineTo (bmpdc
, img
->width
- 1, 0);
5696 SelectObject (bmpdc
, prev
);
5698 #endif /* HAVE_NTGUI */
5703 /* Build a mask for image IMG which is used on frame F. FILE is the
5704 name of an image file, for error messages. HOW determines how to
5705 determine the background color of IMG. If it is a list '(R G B)',
5706 with R, G, and B being integers >= 0, take that as the color of the
5707 background. Otherwise, determine the background color of IMG
5708 heuristically. Value is non-zero if successful. */
5711 x_build_heuristic_mask (f
, img
, how
)
5716 XImagePtr_or_DC ximg
;
5724 #endif /* HAVE_NTGUI */
5725 int x
, y
, rc
, use_img_background
;
5726 unsigned long bg
= 0;
5730 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5731 img
->mask
= NO_PIXMAP
;
5732 img
->background_transparent_valid
= 0;
5736 /* Create an image and pixmap serving as mask. */
5737 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5738 &mask_img
, &img
->mask
);
5742 /* Get the X image of IMG->pixmap. */
5743 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5744 img
->width
, img
->height
,
5747 /* Create the bit array serving as mask. */
5748 row_width
= (img
->width
+ 7) / 8;
5749 mask_img
= xmalloc (row_width
* img
->height
);
5750 bzero (mask_img
, row_width
* img
->height
);
5752 /* Create a memory device context for IMG->pixmap. */
5753 frame_dc
= get_frame_dc (f
);
5754 ximg
= CreateCompatibleDC (frame_dc
);
5755 release_frame_dc (f
, frame_dc
);
5756 prev
= SelectObject (ximg
, img
->pixmap
);
5757 #endif /* HAVE_NTGUI */
5759 /* Determine the background color of ximg. If HOW is `(R G B)'
5760 take that as color. Otherwise, use the image's background color. */
5761 use_img_background
= 1;
5767 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5769 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5773 if (i
== 3 && NILP (how
))
5775 char color_name
[30];
5776 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5779 0x00ffffff & /* Filter out palette info. */
5780 #endif /* HAVE_NTGUI */
5781 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5782 use_img_background
= 0;
5786 if (use_img_background
)
5787 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5789 /* Set all bits in mask_img to 1 whose color in ximg is different
5790 from the background color bg. */
5792 for (y
= 0; y
< img
->height
; ++y
)
5793 for (x
= 0; x
< img
->width
; ++x
)
5794 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5795 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5797 /* Fill in the background_transparent field while we have the mask handy. */
5798 image_background_transparent (img
, f
, mask_img
);
5800 /* Put mask_img into img->mask. */
5801 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5802 x_destroy_x_image (mask_img
);
5805 for (y
= 0; y
< img
->height
; ++y
)
5806 for (x
= 0; x
< img
->width
; ++x
)
5808 COLORREF p
= GetPixel (ximg
, x
, y
);
5810 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5813 /* Create the mask image. */
5814 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5816 /* Fill in the background_transparent field while we have the mask handy. */
5817 SelectObject (ximg
, img
->mask
);
5818 image_background_transparent (img
, f
, ximg
);
5820 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5822 #endif /* HAVE_NTGUI */
5824 Destroy_Image (ximg
, prev
);
5830 /***********************************************************************
5831 PBM (mono, gray, color)
5832 ***********************************************************************/
5834 static int pbm_image_p
P_ ((Lisp_Object object
));
5835 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5836 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5838 /* The symbol `pbm' identifying images of this type. */
5842 /* Indices of image specification fields in gs_format, below. */
5844 enum pbm_keyword_index
5860 /* Vector of image_keyword structures describing the format
5861 of valid user-defined image specifications. */
5863 static struct image_keyword pbm_format
[PBM_LAST
] =
5865 {":type", IMAGE_SYMBOL_VALUE
, 1},
5866 {":file", IMAGE_STRING_VALUE
, 0},
5867 {":data", IMAGE_STRING_VALUE
, 0},
5868 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5869 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5870 {":relief", IMAGE_INTEGER_VALUE
, 0},
5871 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5872 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5873 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5874 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5875 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5878 /* Structure describing the image type `pbm'. */
5880 static struct image_type pbm_type
=
5890 /* Return non-zero if OBJECT is a valid PBM image specification. */
5893 pbm_image_p (object
)
5896 struct image_keyword fmt
[PBM_LAST
];
5898 bcopy (pbm_format
, fmt
, sizeof fmt
);
5900 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5903 /* Must specify either :data or :file. */
5904 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5908 /* Scan a decimal number from *S and return it. Advance *S while
5909 reading the number. END is the end of the string. Value is -1 at
5913 pbm_scan_number (s
, end
)
5914 unsigned char **s
, *end
;
5916 int c
= 0, val
= -1;
5920 /* Skip white-space. */
5921 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5926 /* Skip comment to end of line. */
5927 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5930 else if (isdigit (c
))
5932 /* Read decimal number. */
5934 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5935 val
= 10 * val
+ c
- '0';
5947 #if 0 /* Unused. ++kfs */
5949 /* Read FILE into memory. Value is a pointer to a buffer allocated
5950 with xmalloc holding FILE's contents. Value is null if an error
5951 occurred. *SIZE is set to the size of the file. */
5954 pbm_read_file (file
, size
)
5962 if (stat (SDATA (file
), &st
) == 0
5963 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5964 && (buf
= (char *) xmalloc (st
.st_size
),
5965 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5984 #endif /* HAVE_NTGUI */
5986 /* Load PBM image IMG for use on frame F. */
5994 int width
, height
, max_color_idx
= 0;
5996 Lisp_Object file
, specified_file
;
5997 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5998 struct gcpro gcpro1
;
5999 unsigned char *contents
= NULL
;
6000 unsigned char *end
, *p
;
6003 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6007 if (STRINGP (specified_file
))
6009 file
= x_find_image_file (specified_file
);
6010 if (!STRINGP (file
))
6012 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6017 contents
= slurp_file (SDATA (file
), &size
);
6018 if (contents
== NULL
)
6020 image_error ("Error reading `%s'", file
, Qnil
);
6026 end
= contents
+ size
;
6031 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6033 end
= p
+ SBYTES (data
);
6036 /* Check magic number. */
6037 if (end
- p
< 2 || *p
++ != 'P')
6039 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6049 raw_p
= 0, type
= PBM_MONO
;
6053 raw_p
= 0, type
= PBM_GRAY
;
6057 raw_p
= 0, type
= PBM_COLOR
;
6061 raw_p
= 1, type
= PBM_MONO
;
6065 raw_p
= 1, type
= PBM_GRAY
;
6069 raw_p
= 1, type
= PBM_COLOR
;
6073 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6077 /* Read width, height, maximum color-component. Characters
6078 starting with `#' up to the end of a line are ignored. */
6079 width
= pbm_scan_number (&p
, end
);
6080 height
= pbm_scan_number (&p
, end
);
6082 if (type
!= PBM_MONO
)
6084 max_color_idx
= pbm_scan_number (&p
, end
);
6085 if (max_color_idx
> 65535 || max_color_idx
< 0)
6087 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
6092 if (!check_image_size (f
, width
, height
))
6094 image_error ("Invalid image size", Qnil
, Qnil
);
6098 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
6099 &ximg
, &img
->pixmap
))
6102 /* Initialize the color hash table. */
6103 init_color_table ();
6105 if (type
== PBM_MONO
)
6108 struct image_keyword fmt
[PBM_LAST
];
6109 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
6110 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
6112 /* Parse the image specification. */
6113 bcopy (pbm_format
, fmt
, sizeof fmt
);
6114 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
6116 /* Get foreground and background colors, maybe allocate colors. */
6117 if (fmt
[PBM_FOREGROUND
].count
6118 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
6119 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
6120 if (fmt
[PBM_BACKGROUND
].count
6121 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
6123 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
6124 img
->background
= bg
;
6125 img
->background_valid
= 1;
6128 for (y
= 0; y
< height
; ++y
)
6129 for (x
= 0; x
< width
; ++x
)
6137 x_destroy_x_image (ximg
);
6138 x_clear_image (f
, img
);
6139 image_error ("Invalid image size in image `%s'",
6149 g
= pbm_scan_number (&p
, end
);
6151 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
6156 int expected_size
= height
* width
;
6157 if (max_color_idx
> 255)
6159 if (type
== PBM_COLOR
)
6162 if (raw_p
&& p
+ expected_size
> end
)
6164 x_destroy_x_image (ximg
);
6165 x_clear_image (f
, img
);
6166 image_error ("Invalid image size in image `%s'",
6171 for (y
= 0; y
< height
; ++y
)
6172 for (x
= 0; x
< width
; ++x
)
6176 if (type
== PBM_GRAY
&& raw_p
)
6179 if (max_color_idx
> 255)
6180 r
= g
= b
= r
* 256 + *p
++;
6182 else if (type
== PBM_GRAY
)
6183 r
= g
= b
= pbm_scan_number (&p
, end
);
6187 if (max_color_idx
> 255)
6190 if (max_color_idx
> 255)
6193 if (max_color_idx
> 255)
6198 r
= pbm_scan_number (&p
, end
);
6199 g
= pbm_scan_number (&p
, end
);
6200 b
= pbm_scan_number (&p
, end
);
6203 if (r
< 0 || g
< 0 || b
< 0)
6205 x_destroy_x_image (ximg
);
6206 image_error ("Invalid pixel value in image `%s'",
6211 /* RGB values are now in the range 0..max_color_idx.
6212 Scale this to the range 0..0xffff supported by X. */
6213 r
= (double) r
* 65535 / max_color_idx
;
6214 g
= (double) g
* 65535 / max_color_idx
;
6215 b
= (double) b
* 65535 / max_color_idx
;
6216 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6220 #ifdef COLOR_TABLE_SUPPORT
6221 /* Store in IMG->colors the colors allocated for the image, and
6222 free the color table. */
6223 img
->colors
= colors_in_color_table (&img
->ncolors
);
6224 free_color_table ();
6225 #endif /* COLOR_TABLE_SUPPORT */
6228 img
->height
= height
;
6230 /* Maybe fill in the background field while we have ximg handy. */
6232 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6233 /* Casting avoids a GCC warning. */
6234 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6236 /* Put the image into a pixmap. */
6237 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6238 x_destroy_x_image (ximg
);
6240 /* X and W32 versions did it here, MAC version above. ++kfs
6242 img->height = height; */
6250 /***********************************************************************
6252 ***********************************************************************/
6254 #if defined (HAVE_PNG) || defined (MAC_OS)
6256 /* Function prototypes. */
6258 static int png_image_p
P_ ((Lisp_Object object
));
6259 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
6261 /* The symbol `png' identifying images of this type. */
6265 /* Indices of image specification fields in png_format, below. */
6267 enum png_keyword_index
6282 /* Vector of image_keyword structures describing the format
6283 of valid user-defined image specifications. */
6285 static struct image_keyword png_format
[PNG_LAST
] =
6287 {":type", IMAGE_SYMBOL_VALUE
, 1},
6288 {":data", IMAGE_STRING_VALUE
, 0},
6289 {":file", IMAGE_STRING_VALUE
, 0},
6290 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6291 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6292 {":relief", IMAGE_INTEGER_VALUE
, 0},
6293 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6294 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6295 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6296 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6299 /* Structure describing the image type `png'. */
6301 static struct image_type png_type
=
6310 /* Return non-zero if OBJECT is a valid PNG image specification. */
6313 png_image_p (object
)
6316 struct image_keyword fmt
[PNG_LAST
];
6317 bcopy (png_format
, fmt
, sizeof fmt
);
6319 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
6322 /* Must specify either the :data or :file keyword. */
6323 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
6326 #endif /* HAVE_PNG || MAC_OS */
6331 #if defined HAVE_LIBPNG_PNG_H
6332 # include <libpng/png.h>
6338 /* PNG library details. */
6340 DEF_IMGLIB_FN (png_get_io_ptr
);
6341 DEF_IMGLIB_FN (png_check_sig
);
6342 DEF_IMGLIB_FN (png_create_read_struct
);
6343 DEF_IMGLIB_FN (png_create_info_struct
);
6344 DEF_IMGLIB_FN (png_destroy_read_struct
);
6345 DEF_IMGLIB_FN (png_set_read_fn
);
6346 DEF_IMGLIB_FN (png_set_sig_bytes
);
6347 DEF_IMGLIB_FN (png_read_info
);
6348 DEF_IMGLIB_FN (png_get_IHDR
);
6349 DEF_IMGLIB_FN (png_get_valid
);
6350 DEF_IMGLIB_FN (png_set_strip_16
);
6351 DEF_IMGLIB_FN (png_set_expand
);
6352 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6353 DEF_IMGLIB_FN (png_set_background
);
6354 DEF_IMGLIB_FN (png_get_bKGD
);
6355 DEF_IMGLIB_FN (png_read_update_info
);
6356 DEF_IMGLIB_FN (png_get_channels
);
6357 DEF_IMGLIB_FN (png_get_rowbytes
);
6358 DEF_IMGLIB_FN (png_read_image
);
6359 DEF_IMGLIB_FN (png_read_end
);
6360 DEF_IMGLIB_FN (png_error
);
6363 init_png_functions (Lisp_Object libraries
)
6367 /* Try loading libpng under probable names. */
6368 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6371 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6372 LOAD_IMGLIB_FN (library
, png_check_sig
);
6373 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6374 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6375 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6376 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6377 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6378 LOAD_IMGLIB_FN (library
, png_read_info
);
6379 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6380 LOAD_IMGLIB_FN (library
, png_get_valid
);
6381 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6382 LOAD_IMGLIB_FN (library
, png_set_expand
);
6383 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6384 LOAD_IMGLIB_FN (library
, png_set_background
);
6385 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6386 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6387 LOAD_IMGLIB_FN (library
, png_get_channels
);
6388 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6389 LOAD_IMGLIB_FN (library
, png_read_image
);
6390 LOAD_IMGLIB_FN (library
, png_read_end
);
6391 LOAD_IMGLIB_FN (library
, png_error
);
6396 #define fn_png_get_io_ptr png_get_io_ptr
6397 #define fn_png_check_sig png_check_sig
6398 #define fn_png_create_read_struct png_create_read_struct
6399 #define fn_png_create_info_struct png_create_info_struct
6400 #define fn_png_destroy_read_struct png_destroy_read_struct
6401 #define fn_png_set_read_fn png_set_read_fn
6402 #define fn_png_set_sig_bytes png_set_sig_bytes
6403 #define fn_png_read_info png_read_info
6404 #define fn_png_get_IHDR png_get_IHDR
6405 #define fn_png_get_valid png_get_valid
6406 #define fn_png_set_strip_16 png_set_strip_16
6407 #define fn_png_set_expand png_set_expand
6408 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6409 #define fn_png_set_background png_set_background
6410 #define fn_png_get_bKGD png_get_bKGD
6411 #define fn_png_read_update_info png_read_update_info
6412 #define fn_png_get_channels png_get_channels
6413 #define fn_png_get_rowbytes png_get_rowbytes
6414 #define fn_png_read_image png_read_image
6415 #define fn_png_read_end png_read_end
6416 #define fn_png_error png_error
6418 #endif /* HAVE_NTGUI */
6420 /* Error and warning handlers installed when the PNG library
6424 my_png_error (png_ptr
, msg
)
6425 png_struct
*png_ptr
;
6428 xassert (png_ptr
!= NULL
);
6429 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6430 longjmp (png_ptr
->jmpbuf
, 1);
6435 my_png_warning (png_ptr
, msg
)
6436 png_struct
*png_ptr
;
6439 xassert (png_ptr
!= NULL
);
6440 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6443 /* Memory source for PNG decoding. */
6445 struct png_memory_storage
6447 unsigned char *bytes
; /* The data */
6448 size_t len
; /* How big is it? */
6449 int index
; /* Where are we? */
6453 /* Function set as reader function when reading PNG image from memory.
6454 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6455 bytes from the input to DATA. */
6458 png_read_from_memory (png_ptr
, data
, length
)
6459 png_structp png_ptr
;
6463 struct png_memory_storage
*tbr
6464 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6466 if (length
> tbr
->len
- tbr
->index
)
6467 fn_png_error (png_ptr
, "Read error");
6469 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6470 tbr
->index
= tbr
->index
+ length
;
6474 /* Function set as reader function when reading PNG image from a file.
6475 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6476 bytes from the input to DATA. */
6479 png_read_from_file (png_ptr
, data
, length
)
6480 png_structp png_ptr
;
6484 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6486 if (fread (data
, 1, length
, fp
) < length
)
6487 fn_png_error (png_ptr
, "Read error");
6491 /* Load PNG image IMG for use on frame F. Value is non-zero if
6499 Lisp_Object file
, specified_file
;
6500 Lisp_Object specified_data
;
6502 XImagePtr ximg
, mask_img
= NULL
;
6503 struct gcpro gcpro1
;
6504 png_struct
*png_ptr
= NULL
;
6505 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6506 FILE *volatile fp
= NULL
;
6508 png_byte
* volatile pixels
= NULL
;
6509 png_byte
** volatile rows
= NULL
;
6510 png_uint_32 width
, height
;
6511 int bit_depth
, color_type
, interlace_type
;
6513 png_uint_32 row_bytes
;
6515 struct png_memory_storage tbr
; /* Data to be read */
6517 /* Find out what file to load. */
6518 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6519 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6523 if (NILP (specified_data
))
6525 file
= x_find_image_file (specified_file
);
6526 if (!STRINGP (file
))
6528 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6533 /* Open the image file. */
6534 fp
= fopen (SDATA (file
), "rb");
6537 image_error ("Cannot open image file `%s'", file
, Qnil
);
6542 /* Check PNG signature. */
6543 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6544 || !fn_png_check_sig (sig
, sizeof sig
))
6546 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6554 /* Read from memory. */
6555 tbr
.bytes
= SDATA (specified_data
);
6556 tbr
.len
= SBYTES (specified_data
);
6559 /* Check PNG signature. */
6560 if (tbr
.len
< sizeof sig
6561 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6563 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6568 /* Need to skip past the signature. */
6569 tbr
.bytes
+= sizeof (sig
);
6572 /* Initialize read and info structs for PNG lib. Casting return
6573 value avoids a GCC warning on W32. */
6574 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6579 if (fp
) fclose (fp
);
6584 /* Casting return value avoids a GCC warning on W32. */
6585 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6588 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6589 if (fp
) fclose (fp
);
6594 /* Casting return value avoids a GCC warning on W32. */
6595 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6598 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6599 if (fp
) fclose (fp
);
6604 /* Set error jump-back. We come back here when the PNG library
6605 detects an error. */
6606 if (setjmp (png_ptr
->jmpbuf
))
6610 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6613 if (fp
) fclose (fp
);
6618 /* Read image info. */
6619 if (!NILP (specified_data
))
6620 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6622 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6624 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6625 fn_png_read_info (png_ptr
, info_ptr
);
6626 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6627 &interlace_type
, NULL
, NULL
);
6629 if (!check_image_size (f
, width
, height
))
6632 /* If image contains simply transparency data, we prefer to
6633 construct a clipping mask. */
6634 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6639 /* This function is easier to write if we only have to handle
6640 one data format: RGB or RGBA with 8 bits per channel. Let's
6641 transform other formats into that format. */
6643 /* Strip more than 8 bits per channel. */
6644 if (bit_depth
== 16)
6645 fn_png_set_strip_16 (png_ptr
);
6647 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6649 fn_png_set_expand (png_ptr
);
6651 /* Convert grayscale images to RGB. */
6652 if (color_type
== PNG_COLOR_TYPE_GRAY
6653 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6654 fn_png_set_gray_to_rgb (png_ptr
);
6656 /* Handle alpha channel by combining the image with a background
6657 color. Do this only if a real alpha channel is supplied. For
6658 simple transparency, we prefer a clipping mask. */
6661 png_color_16
*image_bg
;
6662 Lisp_Object specified_bg
6663 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6664 int shift
= (bit_depth
== 16) ? 0 : 8;
6666 if (STRINGP (specified_bg
))
6667 /* The user specified `:background', use that. */
6669 /* W32 version incorrectly used COLORREF here!! ++kfs */
6671 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6673 png_color_16 user_bg
;
6675 bzero (&user_bg
, sizeof user_bg
);
6676 user_bg
.red
= color
.red
>> shift
;
6677 user_bg
.green
= color
.green
>> shift
;
6678 user_bg
.blue
= color
.blue
>> shift
;
6680 fn_png_set_background (png_ptr
, &user_bg
,
6681 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6686 /* We use the current frame background, ignoring any default
6687 background color set by the image. */
6688 #ifdef HAVE_X_WINDOWS
6690 png_color_16 frame_background
;
6692 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6693 x_query_color (f
, &color
);
6695 bzero (&frame_background
, sizeof frame_background
);
6696 frame_background
.red
= color
.red
>> shift
;
6697 frame_background
.green
= color
.green
>> shift
;
6698 frame_background
.blue
= color
.blue
>> shift
;
6699 #endif /* HAVE_X_WINDOWS */
6703 png_color_16 frame_background
;
6704 color
= FRAME_BACKGROUND_PIXEL (f
);
6705 #if 0 /* W32 TODO : Colormap support. */
6706 x_query_color (f
, &color
);
6708 bzero (&frame_background
, sizeof frame_background
);
6709 frame_background
.red
= GetRValue (color
);
6710 frame_background
.green
= GetGValue (color
);
6711 frame_background
.blue
= GetBValue (color
);
6712 #endif /* HAVE_NTGUI */
6715 unsigned long color
;
6716 png_color_16 frame_background
;
6717 color
= FRAME_BACKGROUND_PIXEL (f
);
6718 #if 0 /* MAC/W32 TODO : Colormap support. */
6719 x_query_color (f
, &color
);
6721 bzero (&frame_background
, sizeof frame_background
);
6722 frame_background
.red
= RED_FROM_ULONG (color
);
6723 frame_background
.green
= GREEN_FROM_ULONG (color
);
6724 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6727 fn_png_set_background (png_ptr
, &frame_background
,
6728 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6732 /* Update info structure. */
6733 fn_png_read_update_info (png_ptr
, info_ptr
);
6735 /* Get number of channels. Valid values are 1 for grayscale images
6736 and images with a palette, 2 for grayscale images with transparency
6737 information (alpha channel), 3 for RGB images, and 4 for RGB
6738 images with alpha channel, i.e. RGBA. If conversions above were
6739 sufficient we should only have 3 or 4 channels here. */
6740 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6741 xassert (channels
== 3 || channels
== 4);
6743 /* Number of bytes needed for one row of the image. */
6744 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6746 /* Allocate memory for the image. */
6747 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6748 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6749 for (i
= 0; i
< height
; ++i
)
6750 rows
[i
] = pixels
+ i
* row_bytes
;
6752 /* Read the entire image. */
6753 fn_png_read_image (png_ptr
, rows
);
6754 fn_png_read_end (png_ptr
, info_ptr
);
6761 /* Create the X image and pixmap. */
6762 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6766 /* Create an image and pixmap serving as mask if the PNG image
6767 contains an alpha channel. */
6770 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6771 &mask_img
, &img
->mask
))
6773 x_destroy_x_image (ximg
);
6774 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6775 img
->pixmap
= NO_PIXMAP
;
6779 /* Fill the X image and mask from PNG data. */
6780 init_color_table ();
6782 for (y
= 0; y
< height
; ++y
)
6784 png_byte
*p
= rows
[y
];
6786 for (x
= 0; x
< width
; ++x
)
6793 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6794 /* An alpha channel, aka mask channel, associates variable
6795 transparency with an image. Where other image formats
6796 support binary transparency---fully transparent or fully
6797 opaque---PNG allows up to 254 levels of partial transparency.
6798 The PNG library implements partial transparency by combining
6799 the image with a specified background color.
6801 I'm not sure how to handle this here nicely: because the
6802 background on which the image is displayed may change, for
6803 real alpha channel support, it would be necessary to create
6804 a new image for each possible background.
6806 What I'm doing now is that a mask is created if we have
6807 boolean transparency information. Otherwise I'm using
6808 the frame's background color to combine the image with. */
6813 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6819 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6820 /* Set IMG's background color from the PNG image, unless the user
6824 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6826 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6827 img
->background_valid
= 1;
6831 #ifdef COLOR_TABLE_SUPPORT
6832 /* Remember colors allocated for this image. */
6833 img
->colors
= colors_in_color_table (&img
->ncolors
);
6834 free_color_table ();
6835 #endif /* COLOR_TABLE_SUPPORT */
6838 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6843 img
->height
= height
;
6845 /* Maybe fill in the background field while we have ximg handy.
6846 Casting avoids a GCC warning. */
6847 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6849 /* Put the image into the pixmap, then free the X image and its buffer. */
6850 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6851 x_destroy_x_image (ximg
);
6853 /* Same for the mask. */
6856 /* Fill in the background_transparent field while we have the
6857 mask handy. Casting avoids a GCC warning. */
6858 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6860 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6861 x_destroy_x_image (mask_img
);
6868 #else /* HAVE_PNG */
6876 #if USE_MAC_IMAGE_IO
6877 return image_load_image_io (f
, img
, kUTTypePNG
);
6878 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6879 return image_load_quartz2d (f
, img
, 1);
6881 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6886 #endif /* !HAVE_PNG */
6890 /***********************************************************************
6892 ***********************************************************************/
6894 #if defined (HAVE_JPEG) || defined (MAC_OS)
6896 static int jpeg_image_p
P_ ((Lisp_Object object
));
6897 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6899 /* The symbol `jpeg' identifying images of this type. */
6903 /* Indices of image specification fields in gs_format, below. */
6905 enum jpeg_keyword_index
6914 JPEG_HEURISTIC_MASK
,
6920 /* Vector of image_keyword structures describing the format
6921 of valid user-defined image specifications. */
6923 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6925 {":type", IMAGE_SYMBOL_VALUE
, 1},
6926 {":data", IMAGE_STRING_VALUE
, 0},
6927 {":file", IMAGE_STRING_VALUE
, 0},
6928 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6929 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6930 {":relief", IMAGE_INTEGER_VALUE
, 0},
6931 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6932 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6933 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6934 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6937 /* Structure describing the image type `jpeg'. */
6939 static struct image_type jpeg_type
=
6948 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6951 jpeg_image_p (object
)
6954 struct image_keyword fmt
[JPEG_LAST
];
6956 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6958 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6961 /* Must specify either the :data or :file keyword. */
6962 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6965 #endif /* HAVE_JPEG || MAC_OS */
6969 /* Work around a warning about HAVE_STDLIB_H being redefined in
6971 #ifdef HAVE_STDLIB_H
6972 #define HAVE_STDLIB_H_1
6973 #undef HAVE_STDLIB_H
6974 #endif /* HAVE_STLIB_H */
6976 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6977 /* In older releases of the jpeg library, jpeglib.h will define boolean
6978 differently depending on __WIN32__, so make sure it is defined. */
6982 #include <jpeglib.h>
6986 #ifdef HAVE_STLIB_H_1
6987 #define HAVE_STDLIB_H 1
6992 /* JPEG library details. */
6993 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6994 DEF_IMGLIB_FN (jpeg_start_decompress
);
6995 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6996 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6997 DEF_IMGLIB_FN (jpeg_read_header
);
6998 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6999 DEF_IMGLIB_FN (jpeg_std_error
);
7000 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
7003 init_jpeg_functions (Lisp_Object libraries
)
7007 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
7010 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
7011 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
7012 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
7013 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
7014 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
7015 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
7016 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
7017 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
7021 /* Wrapper since we can't directly assign the function pointer
7022 to another function pointer that was declared more completely easily. */
7024 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
7025 j_decompress_ptr cinfo
;
7028 return fn_jpeg_resync_to_restart (cinfo
, desired
);
7033 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7034 #define fn_jpeg_start_decompress jpeg_start_decompress
7035 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7036 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7037 #define fn_jpeg_read_header jpeg_read_header
7038 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7039 #define fn_jpeg_std_error jpeg_std_error
7040 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7042 #endif /* HAVE_NTGUI */
7044 struct my_jpeg_error_mgr
7046 struct jpeg_error_mgr pub
;
7047 jmp_buf setjmp_buffer
;
7052 my_error_exit (cinfo
)
7055 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
7056 longjmp (mgr
->setjmp_buffer
, 1);
7060 /* Init source method for JPEG data source manager. Called by
7061 jpeg_read_header() before any data is actually read. See
7062 libjpeg.doc from the JPEG lib distribution. */
7065 our_common_init_source (cinfo
)
7066 j_decompress_ptr cinfo
;
7071 /* Method to terminate data source. Called by
7072 jpeg_finish_decompress() after all data has been processed. */
7075 our_common_term_source (cinfo
)
7076 j_decompress_ptr cinfo
;
7081 /* Fill input buffer method for JPEG data source manager. Called
7082 whenever more data is needed. We read the whole image in one step,
7083 so this only adds a fake end of input marker at the end. */
7085 static JOCTET our_memory_buffer
[2];
7088 our_memory_fill_input_buffer (cinfo
)
7089 j_decompress_ptr cinfo
;
7091 /* Insert a fake EOI marker. */
7092 struct jpeg_source_mgr
*src
= cinfo
->src
;
7094 our_memory_buffer
[0] = (JOCTET
) 0xFF;
7095 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
7097 src
->next_input_byte
= our_memory_buffer
;
7098 src
->bytes_in_buffer
= 2;
7103 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7104 is the JPEG data source manager. */
7107 our_memory_skip_input_data (cinfo
, num_bytes
)
7108 j_decompress_ptr cinfo
;
7111 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7115 if (num_bytes
> src
->bytes_in_buffer
)
7116 ERREXIT (cinfo
, JERR_INPUT_EOF
);
7118 src
->bytes_in_buffer
-= num_bytes
;
7119 src
->next_input_byte
+= num_bytes
;
7124 /* Set up the JPEG lib for reading an image from DATA which contains
7125 LEN bytes. CINFO is the decompression info structure created for
7126 reading the image. */
7129 jpeg_memory_src (cinfo
, data
, len
)
7130 j_decompress_ptr cinfo
;
7134 struct jpeg_source_mgr
*src
;
7136 if (cinfo
->src
== NULL
)
7138 /* First time for this JPEG object? */
7139 cinfo
->src
= (struct jpeg_source_mgr
*)
7140 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7141 sizeof (struct jpeg_source_mgr
));
7142 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7143 src
->next_input_byte
= data
;
7146 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7147 src
->init_source
= our_common_init_source
;
7148 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
7149 src
->skip_input_data
= our_memory_skip_input_data
;
7150 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7151 src
->term_source
= our_common_term_source
;
7152 src
->bytes_in_buffer
= len
;
7153 src
->next_input_byte
= data
;
7157 struct jpeg_stdio_mgr
7159 struct jpeg_source_mgr mgr
;
7166 /* Size of buffer to read JPEG from file.
7167 Not too big, as we want to use alloc_small. */
7168 #define JPEG_STDIO_BUFFER_SIZE 8192
7171 /* Fill input buffer method for JPEG data source manager. Called
7172 whenever more data is needed. The data is read from a FILE *. */
7175 our_stdio_fill_input_buffer (cinfo
)
7176 j_decompress_ptr cinfo
;
7178 struct jpeg_stdio_mgr
*src
;
7180 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7185 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
7187 src
->mgr
.bytes_in_buffer
= bytes
;
7190 WARNMS (cinfo
, JWRN_JPEG_EOF
);
7192 src
->buffer
[0] = (JOCTET
) 0xFF;
7193 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
7194 src
->mgr
.bytes_in_buffer
= 2;
7196 src
->mgr
.next_input_byte
= src
->buffer
;
7203 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7204 is the JPEG data source manager. */
7207 our_stdio_skip_input_data (cinfo
, num_bytes
)
7208 j_decompress_ptr cinfo
;
7211 struct jpeg_stdio_mgr
*src
;
7212 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7214 while (num_bytes
> 0 && !src
->finished
)
7216 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
7218 src
->mgr
.bytes_in_buffer
-= num_bytes
;
7219 src
->mgr
.next_input_byte
+= num_bytes
;
7224 num_bytes
-= src
->mgr
.bytes_in_buffer
;
7225 src
->mgr
.bytes_in_buffer
= 0;
7226 src
->mgr
.next_input_byte
= NULL
;
7228 our_stdio_fill_input_buffer (cinfo
);
7234 /* Set up the JPEG lib for reading an image from a FILE *.
7235 CINFO is the decompression info structure created for
7236 reading the image. */
7239 jpeg_file_src (cinfo
, fp
)
7240 j_decompress_ptr cinfo
;
7243 struct jpeg_stdio_mgr
*src
;
7245 if (cinfo
->src
!= NULL
)
7246 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7249 /* First time for this JPEG object? */
7250 cinfo
->src
= (struct jpeg_source_mgr
*)
7251 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7252 sizeof (struct jpeg_stdio_mgr
));
7253 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7254 src
->buffer
= (JOCTET
*)
7255 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7256 JPEG_STDIO_BUFFER_SIZE
);
7261 src
->mgr
.init_source
= our_common_init_source
;
7262 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
7263 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
7264 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7265 src
->mgr
.term_source
= our_common_term_source
;
7266 src
->mgr
.bytes_in_buffer
= 0;
7267 src
->mgr
.next_input_byte
= NULL
;
7271 /* Load image IMG for use on frame F. Patterned after example.c
7272 from the JPEG lib. */
7279 struct jpeg_decompress_struct cinfo
;
7280 struct my_jpeg_error_mgr mgr
;
7281 Lisp_Object file
, specified_file
;
7282 Lisp_Object specified_data
;
7283 FILE * volatile fp
= NULL
;
7285 int row_stride
, x
, y
;
7286 XImagePtr ximg
= NULL
;
7288 unsigned long *colors
;
7290 struct gcpro gcpro1
;
7292 /* Open the JPEG file. */
7293 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7294 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7298 if (NILP (specified_data
))
7300 file
= x_find_image_file (specified_file
);
7301 if (!STRINGP (file
))
7303 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7308 fp
= fopen (SDATA (file
), "rb");
7311 image_error ("Cannot open `%s'", file
, Qnil
);
7317 /* Customize libjpeg's error handling to call my_error_exit when an
7318 error is detected. This function will perform a longjmp.
7319 Casting return value avoids a GCC warning on W32. */
7320 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7321 mgr
.pub
.error_exit
= my_error_exit
;
7323 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7327 /* Called from my_error_exit. Display a JPEG error. */
7328 char buffer
[JMSG_LENGTH_MAX
];
7329 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7330 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7331 build_string (buffer
));
7334 /* Close the input file and destroy the JPEG object. */
7336 fclose ((FILE *) fp
);
7337 fn_jpeg_destroy_decompress (&cinfo
);
7339 /* If we already have an XImage, free that. */
7340 x_destroy_x_image (ximg
);
7342 /* Free pixmap and colors. */
7343 x_clear_image (f
, img
);
7349 /* Create the JPEG decompression object. Let it read from fp.
7350 Read the JPEG image header. */
7351 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7353 if (NILP (specified_data
))
7354 jpeg_file_src (&cinfo
, (FILE *) fp
);
7356 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7357 SBYTES (specified_data
));
7359 fn_jpeg_read_header (&cinfo
, 1);
7361 /* Customize decompression so that color quantization will be used.
7362 Start decompression. */
7363 cinfo
.quantize_colors
= 1;
7364 fn_jpeg_start_decompress (&cinfo
);
7365 width
= img
->width
= cinfo
.output_width
;
7366 height
= img
->height
= cinfo
.output_height
;
7368 if (!check_image_size (f
, width
, height
))
7370 image_error ("Invalid image size", Qnil
, Qnil
);
7371 longjmp (mgr
.setjmp_buffer
, 2);
7374 /* Create X image and pixmap. */
7375 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7376 longjmp (mgr
.setjmp_buffer
, 2);
7378 /* Allocate colors. When color quantization is used,
7379 cinfo.actual_number_of_colors has been set with the number of
7380 colors generated, and cinfo.colormap is a two-dimensional array
7381 of color indices in the range 0..cinfo.actual_number_of_colors.
7382 No more than 255 colors will be generated. */
7386 if (cinfo
.out_color_components
> 2)
7387 ir
= 0, ig
= 1, ib
= 2;
7388 else if (cinfo
.out_color_components
> 1)
7389 ir
= 0, ig
= 1, ib
= 0;
7391 ir
= 0, ig
= 0, ib
= 0;
7393 /* Use the color table mechanism because it handles colors that
7394 cannot be allocated nicely. Such colors will be replaced with
7395 a default color, and we don't have to care about which colors
7396 can be freed safely, and which can't. */
7397 init_color_table ();
7398 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7401 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7403 /* Multiply RGB values with 255 because X expects RGB values
7404 in the range 0..0xffff. */
7405 int r
= cinfo
.colormap
[ir
][i
] << 8;
7406 int g
= cinfo
.colormap
[ig
][i
] << 8;
7407 int b
= cinfo
.colormap
[ib
][i
] << 8;
7408 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7411 #ifdef COLOR_TABLE_SUPPORT
7412 /* Remember those colors actually allocated. */
7413 img
->colors
= colors_in_color_table (&img
->ncolors
);
7414 free_color_table ();
7415 #endif /* COLOR_TABLE_SUPPORT */
7419 row_stride
= width
* cinfo
.output_components
;
7420 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7422 for (y
= 0; y
< height
; ++y
)
7424 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7425 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7426 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7430 fn_jpeg_finish_decompress (&cinfo
);
7431 fn_jpeg_destroy_decompress (&cinfo
);
7433 fclose ((FILE *) fp
);
7435 /* Maybe fill in the background field while we have ximg handy. */
7436 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7437 /* Casting avoids a GCC warning. */
7438 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7440 /* Put the image into the pixmap. */
7441 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7442 x_destroy_x_image (ximg
);
7447 #else /* HAVE_JPEG */
7455 #if USE_MAC_IMAGE_IO
7456 return image_load_image_io (f
, img
, kUTTypeJPEG
);
7457 #elif defined (MAC_OSX)
7458 return image_load_quartz2d (f
, img
, 0);
7460 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7465 #endif /* !HAVE_JPEG */
7469 /***********************************************************************
7471 ***********************************************************************/
7473 #if defined (HAVE_TIFF) || defined (MAC_OS)
7475 static int tiff_image_p
P_ ((Lisp_Object object
));
7476 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7478 /* The symbol `tiff' identifying images of this type. */
7482 /* Indices of image specification fields in tiff_format, below. */
7484 enum tiff_keyword_index
7493 TIFF_HEURISTIC_MASK
,
7499 /* Vector of image_keyword structures describing the format
7500 of valid user-defined image specifications. */
7502 static struct image_keyword tiff_format
[TIFF_LAST
] =
7504 {":type", IMAGE_SYMBOL_VALUE
, 1},
7505 {":data", IMAGE_STRING_VALUE
, 0},
7506 {":file", IMAGE_STRING_VALUE
, 0},
7507 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7508 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7509 {":relief", IMAGE_INTEGER_VALUE
, 0},
7510 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7511 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7512 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7513 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7516 /* Structure describing the image type `tiff'. */
7518 static struct image_type tiff_type
=
7527 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7530 tiff_image_p (object
)
7533 struct image_keyword fmt
[TIFF_LAST
];
7534 bcopy (tiff_format
, fmt
, sizeof fmt
);
7536 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7539 /* Must specify either the :data or :file keyword. */
7540 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7543 #endif /* HAVE_TIFF || MAC_OS */
7551 /* TIFF library details. */
7552 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7553 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7554 DEF_IMGLIB_FN (TIFFOpen
);
7555 DEF_IMGLIB_FN (TIFFClientOpen
);
7556 DEF_IMGLIB_FN (TIFFGetField
);
7557 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7558 DEF_IMGLIB_FN (TIFFClose
);
7561 init_tiff_functions (Lisp_Object libraries
)
7565 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7568 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7569 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7570 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7571 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7572 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7573 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7574 LOAD_IMGLIB_FN (library
, TIFFClose
);
7580 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7581 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7582 #define fn_TIFFOpen TIFFOpen
7583 #define fn_TIFFClientOpen TIFFClientOpen
7584 #define fn_TIFFGetField TIFFGetField
7585 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7586 #define fn_TIFFClose TIFFClose
7588 #endif /* HAVE_NTGUI */
7591 /* Reading from a memory buffer for TIFF images Based on the PNG
7592 memory source, but we have to provide a lot of extra functions.
7595 We really only need to implement read and seek, but I am not
7596 convinced that the TIFF library is smart enough not to destroy
7597 itself if we only hand it the function pointers we need to
7602 unsigned char *bytes
;
7609 tiff_read_from_memory (data
, buf
, size
)
7614 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7616 if (size
> src
->len
- src
->index
)
7618 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7624 tiff_write_from_memory (data
, buf
, size
)
7633 tiff_seek_in_memory (data
, off
, whence
)
7638 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7643 case SEEK_SET
: /* Go from beginning of source. */
7647 case SEEK_END
: /* Go from end of source. */
7648 idx
= src
->len
+ off
;
7651 case SEEK_CUR
: /* Go from current position. */
7652 idx
= src
->index
+ off
;
7655 default: /* Invalid `whence'. */
7659 if (idx
> src
->len
|| idx
< 0)
7667 tiff_close_memory (data
)
7675 tiff_mmap_memory (data
, pbase
, psize
)
7680 /* It is already _IN_ memory. */
7685 tiff_unmap_memory (data
, base
, size
)
7690 /* We don't need to do this. */
7694 tiff_size_of_memory (data
)
7697 return ((tiff_memory_source
*) data
)->len
;
7702 tiff_error_handler (title
, format
, ap
)
7703 const char *title
, *format
;
7709 len
= sprintf (buf
, "TIFF error: %s ", title
);
7710 vsprintf (buf
+ len
, format
, ap
);
7711 add_to_log (buf
, Qnil
, Qnil
);
7716 tiff_warning_handler (title
, format
, ap
)
7717 const char *title
, *format
;
7723 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7724 vsprintf (buf
+ len
, format
, ap
);
7725 add_to_log (buf
, Qnil
, Qnil
);
7729 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7737 Lisp_Object file
, specified_file
;
7738 Lisp_Object specified_data
;
7740 int width
, height
, x
, y
;
7744 struct gcpro gcpro1
;
7745 tiff_memory_source memsrc
;
7747 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7748 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7752 fn_TIFFSetErrorHandler (tiff_error_handler
);
7753 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7755 if (NILP (specified_data
))
7757 /* Read from a file */
7758 file
= x_find_image_file (specified_file
);
7759 if (!STRINGP (file
))
7761 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7766 /* Try to open the image file. Casting return value avoids a
7767 GCC warning on W32. */
7768 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7771 image_error ("Cannot open `%s'", file
, Qnil
);
7778 /* Memory source! */
7779 memsrc
.bytes
= SDATA (specified_data
);
7780 memsrc
.len
= SBYTES (specified_data
);
7783 /* Casting return value avoids a GCC warning on W32. */
7784 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7785 (TIFFReadWriteProc
) tiff_read_from_memory
,
7786 (TIFFReadWriteProc
) tiff_write_from_memory
,
7787 tiff_seek_in_memory
,
7789 tiff_size_of_memory
,
7795 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7801 /* Get width and height of the image, and allocate a raster buffer
7802 of width x height 32-bit values. */
7803 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7804 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7806 if (!check_image_size (f
, width
, height
))
7808 image_error ("Invalid image size", Qnil
, Qnil
);
7813 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7815 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7816 fn_TIFFClose (tiff
);
7819 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7825 /* Create the X image and pixmap. */
7826 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7833 /* Initialize the color table. */
7834 init_color_table ();
7836 /* Process the pixel raster. Origin is in the lower-left corner. */
7837 for (y
= 0; y
< height
; ++y
)
7839 uint32
*row
= buf
+ y
* width
;
7841 for (x
= 0; x
< width
; ++x
)
7843 uint32 abgr
= row
[x
];
7844 int r
= TIFFGetR (abgr
) << 8;
7845 int g
= TIFFGetG (abgr
) << 8;
7846 int b
= TIFFGetB (abgr
) << 8;
7847 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7851 #ifdef COLOR_TABLE_SUPPORT
7852 /* Remember the colors allocated for the image. Free the color table. */
7853 img
->colors
= colors_in_color_table (&img
->ncolors
);
7854 free_color_table ();
7855 #endif /* COLOR_TABLE_SUPPORT */
7858 img
->height
= height
;
7860 /* Maybe fill in the background field while we have ximg handy. */
7861 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7862 /* Casting avoids a GCC warning on W32. */
7863 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7865 /* Put the image into the pixmap, then free the X image and its buffer. */
7866 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7867 x_destroy_x_image (ximg
);
7874 #else /* HAVE_TIFF */
7882 #if USE_MAC_IMAGE_IO
7883 return image_load_image_io (f
, img
, kUTTypeTIFF
);
7885 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7890 #endif /* !HAVE_TIFF */
7894 /***********************************************************************
7896 ***********************************************************************/
7898 #if defined (HAVE_GIF) || defined (MAC_OS)
7900 static int gif_image_p
P_ ((Lisp_Object object
));
7901 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7902 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7904 /* The symbol `gif' identifying images of this type. */
7908 /* Indices of image specification fields in gif_format, below. */
7910 enum gif_keyword_index
7926 /* Vector of image_keyword structures describing the format
7927 of valid user-defined image specifications. */
7929 static struct image_keyword gif_format
[GIF_LAST
] =
7931 {":type", IMAGE_SYMBOL_VALUE
, 1},
7932 {":data", IMAGE_STRING_VALUE
, 0},
7933 {":file", IMAGE_STRING_VALUE
, 0},
7934 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7935 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7936 {":relief", IMAGE_INTEGER_VALUE
, 0},
7937 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7938 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7939 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7940 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7941 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7944 /* Structure describing the image type `gif'. */
7946 static struct image_type gif_type
=
7955 /* Free X resources of GIF image IMG which is used on frame F. */
7958 gif_clear_image (f
, img
)
7962 /* IMG->data.ptr_val may contain extension data. */
7963 img
->data
.lisp_val
= Qnil
;
7964 x_clear_image (f
, img
);
7967 /* Return non-zero if OBJECT is a valid GIF image specification. */
7970 gif_image_p (object
)
7973 struct image_keyword fmt
[GIF_LAST
];
7974 bcopy (gif_format
, fmt
, sizeof fmt
);
7976 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7979 /* Must specify either the :data or :file keyword. */
7980 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7983 #endif /* HAVE_GIF || MAC_OS */
7987 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7988 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7989 Undefine before redefining to avoid a preprocessor warning. */
7993 /* avoid conflict with QuickdrawText.h */
7994 #define DrawText gif_DrawText
7995 #include <gif_lib.h>
7998 #else /* HAVE_NTGUI || MAC_OS */
8000 #include <gif_lib.h>
8002 #endif /* HAVE_NTGUI || MAC_OS */
8007 /* GIF library details. */
8008 DEF_IMGLIB_FN (DGifCloseFile
);
8009 DEF_IMGLIB_FN (DGifSlurp
);
8010 DEF_IMGLIB_FN (DGifOpen
);
8011 DEF_IMGLIB_FN (DGifOpenFileName
);
8014 init_gif_functions (Lisp_Object libraries
)
8018 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
8021 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
8022 LOAD_IMGLIB_FN (library
, DGifSlurp
);
8023 LOAD_IMGLIB_FN (library
, DGifOpen
);
8024 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
8030 #define fn_DGifCloseFile DGifCloseFile
8031 #define fn_DGifSlurp DGifSlurp
8032 #define fn_DGifOpen DGifOpen
8033 #define fn_DGifOpenFileName DGifOpenFileName
8035 #endif /* HAVE_NTGUI */
8037 /* Reading a GIF image from memory
8038 Based on the PNG memory stuff to a certain extent. */
8042 unsigned char *bytes
;
8048 /* Make the current memory source available to gif_read_from_memory.
8049 It's done this way because not all versions of libungif support
8050 a UserData field in the GifFileType structure. */
8051 static gif_memory_source
*current_gif_memory_src
;
8054 gif_read_from_memory (file
, buf
, len
)
8059 gif_memory_source
*src
= current_gif_memory_src
;
8061 if (len
> src
->len
- src
->index
)
8064 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8070 /* Load GIF image IMG for use on frame F. Value is non-zero if
8073 static int interlace_start
[] = {0, 4, 2, 1};
8074 static int interlace_increment
[] = {8, 8, 4, 2};
8081 Lisp_Object file
, specified_file
;
8082 Lisp_Object specified_data
;
8083 int rc
, width
, height
, x
, y
, i
;
8085 ColorMapObject
*gif_color_map
;
8086 unsigned long pixel_colors
[256];
8088 struct gcpro gcpro1
;
8090 int ino
, image_height
, image_width
;
8091 gif_memory_source memsrc
;
8092 unsigned char *raster
;
8094 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8095 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8099 if (NILP (specified_data
))
8101 file
= x_find_image_file (specified_file
);
8102 if (!STRINGP (file
))
8104 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8109 /* Open the GIF file. Casting return value avoids a GCC warning
8111 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
8114 image_error ("Cannot open `%s'", file
, Qnil
);
8121 /* Read from memory! */
8122 current_gif_memory_src
= &memsrc
;
8123 memsrc
.bytes
= SDATA (specified_data
);
8124 memsrc
.len
= SBYTES (specified_data
);
8127 /* Casting return value avoids a GCC warning on W32. */
8128 gif
= (GifFileType
*)fn_DGifOpen(&memsrc
, gif_read_from_memory
);
8131 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
8137 /* Before reading entire contents, check the declared image size. */
8138 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
8140 image_error ("Invalid image size", Qnil
, Qnil
);
8141 fn_DGifCloseFile (gif
);
8146 /* Read entire contents. */
8147 rc
= fn_DGifSlurp (gif
);
8148 if (rc
== GIF_ERROR
)
8150 image_error ("Error reading `%s'", img
->spec
, Qnil
);
8151 fn_DGifCloseFile (gif
);
8156 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8157 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8158 if (ino
>= gif
->ImageCount
)
8160 image_error ("Invalid image number `%s' in image `%s'",
8162 fn_DGifCloseFile (gif
);
8167 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
8168 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
8169 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8170 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
8171 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8172 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
8174 width
= img
->width
= max (gif
->SWidth
,
8175 max (gif
->Image
.Left
+ gif
->Image
.Width
,
8176 img
->corners
[RIGHT_CORNER
]));
8177 height
= img
->height
= max (gif
->SHeight
,
8178 max (gif
->Image
.Top
+ gif
->Image
.Height
,
8179 img
->corners
[BOT_CORNER
]));
8181 if (!check_image_size (f
, width
, height
))
8183 image_error ("Invalid image size", Qnil
, Qnil
);
8184 fn_DGifCloseFile (gif
);
8189 /* Create the X image and pixmap. */
8190 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8192 fn_DGifCloseFile (gif
);
8197 /* Allocate colors. */
8198 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8200 gif_color_map
= gif
->SColorMap
;
8201 init_color_table ();
8202 bzero (pixel_colors
, sizeof pixel_colors
);
8205 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8207 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8208 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8209 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8210 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8213 #ifdef COLOR_TABLE_SUPPORT
8214 img
->colors
= colors_in_color_table (&img
->ncolors
);
8215 free_color_table ();
8216 #endif /* COLOR_TABLE_SUPPORT */
8218 /* Clear the part of the screen image that are not covered by
8219 the image from the GIF file. Full animated GIF support
8220 requires more than can be done here (see the gif89 spec,
8221 disposal methods). Let's simply assume that the part
8222 not covered by a sub-image is in the frame's background color. */
8223 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
8224 for (x
= 0; x
< width
; ++x
)
8225 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8227 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
8228 for (x
= 0; x
< width
; ++x
)
8229 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8231 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
8233 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
8234 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8235 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
8236 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8239 /* Read the GIF image into the X image. We use a local variable
8240 `raster' here because RasterBits below is a char *, and invites
8241 problems with bytes >= 0x80. */
8242 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
8244 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8247 int row
= interlace_start
[0];
8251 for (y
= 0; y
< image_height
; y
++)
8253 if (row
>= image_height
)
8255 row
= interlace_start
[++pass
];
8256 while (row
>= image_height
)
8257 row
= interlace_start
[++pass
];
8260 for (x
= 0; x
< image_width
; x
++)
8262 int i
= raster
[(y
* image_width
) + x
];
8263 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8264 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8267 row
+= interlace_increment
[pass
];
8272 for (y
= 0; y
< image_height
; ++y
)
8273 for (x
= 0; x
< image_width
; ++x
)
8275 int i
= raster
[y
* image_width
+ x
];
8276 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8277 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8281 /* Save GIF image extension data for `image-extension-data'.
8282 Format is (count IMAGES FUNCTION "BYTES" ...). */
8283 img
->data
.lisp_val
= Qnil
;
8284 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
8286 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
8287 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
8288 /* Append (... FUNCTION "BYTES") */
8289 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
8290 Fcons (make_number (ext
->Function
),
8291 img
->data
.lisp_val
));
8292 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
8294 if (gif
->ImageCount
> 1)
8295 img
->data
.lisp_val
= Fcons (Qcount
,
8296 Fcons (make_number (gif
->ImageCount
),
8297 img
->data
.lisp_val
));
8299 fn_DGifCloseFile (gif
);
8301 /* Maybe fill in the background field while we have ximg handy. */
8302 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8303 /* Casting avoids a GCC warning. */
8304 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8306 /* Put the image into the pixmap, then free the X image and its buffer. */
8307 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8308 x_destroy_x_image (ximg
);
8314 #else /* !HAVE_GIF */
8322 #if USE_MAC_IMAGE_IO
8323 return image_load_image_io (f
, img
, kUTTypeGIF
);
8324 #else /* !USE_MAC_IMAGE_IO */
8325 Lisp_Object specified_file
, file
;
8326 Lisp_Object specified_data
;
8328 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8336 Lisp_Object specified_bg
;
8341 TimeScale time_scale
;
8342 TimeValue time
, duration
;
8347 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8348 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8350 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8353 if (NILP (specified_data
))
8355 /* Read from a file */
8359 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8363 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8368 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8369 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8373 if (!graphic_p
&& !movie_p
)
8375 if (prefer_graphic_p
)
8376 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8377 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8380 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8381 CloseMovieFile (refnum
);
8384 image_error ("Error reading `%s'", file
, Qnil
);
8390 /* Memory source! */
8392 long file_type_atom
[3];
8394 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8397 image_error ("Cannot allocate data handle for `%s'",
8402 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8403 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8404 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8405 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8408 err
= PtrAndHand ("\p", dref
, 1);
8410 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8413 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8416 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8417 &movie_p
, &prefer_graphic_p
, 0);
8421 if (!graphic_p
&& !movie_p
)
8423 if (prefer_graphic_p
)
8427 DisposeHandle (dref
);
8428 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8432 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8433 HandleDataHandlerSubType
);
8434 DisposeHandle (dref
);
8439 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8440 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8441 track
= GetMovieIndTrack (movie
, 1);
8442 media
= GetTrackMedia (track
);
8443 nsamples
= GetMediaSampleCount (media
);
8444 if (ino
>= nsamples
)
8446 image_error ("Invalid image number `%s' in image `%s'",
8450 time_scale
= GetMediaTimeScale (media
);
8452 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8453 if (!STRINGP (specified_bg
)
8454 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8456 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8457 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8458 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8459 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8461 GetMovieBox (movie
, &rect
);
8462 width
= img
->width
= rect
.right
- rect
.left
;
8463 height
= img
->height
= rect
.bottom
- rect
.top
;
8464 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8467 GetGWorld (&old_port
, &old_gdh
);
8468 SetGWorld (ximg
, NULL
);
8469 bg_color
.red
= color
.red
;
8470 bg_color
.green
= color
.green
;
8471 bg_color
.blue
= color
.blue
;
8472 RGBBackColor (&bg_color
);
8473 SetGWorld (old_port
, old_gdh
);
8474 SetMovieActive (movie
, 1);
8475 SetMovieGWorld (movie
, ximg
, NULL
);
8476 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8477 SetMovieTimeValue (movie
, time
);
8478 MoviesTask (movie
, 0L);
8479 DisposeTrackMedia (media
);
8480 DisposeMovieTrack (track
);
8481 DisposeMovie (movie
);
8485 /* Save GIF image extension data for `image-extension-data'.
8486 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8488 Lisp_Object gce
= make_uninit_string (4);
8489 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8491 /* Fill the delay time field. */
8492 SSET (gce
, 1, centisec
& 0xff);
8493 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8494 /* We don't know about other fields. */
8498 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8499 make_number (0xf9), gce
);
8502 /* Maybe fill in the background field while we have ximg handy. */
8503 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8504 IMAGE_BACKGROUND (img
, f
, ximg
);
8506 /* Put the image into the pixmap. */
8507 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8508 x_destroy_x_image (ximg
);
8512 image_error ("Cannot open `%s'", file
, Qnil
);
8515 DisposeTrackMedia (media
);
8517 DisposeMovieTrack (track
);
8519 DisposeMovie (movie
);
8523 #endif /* !USE_MAC_IMAGE_IO */
8527 #endif /* HAVE_GIF */
8531 /***********************************************************************
8533 ***********************************************************************/
8535 #ifdef HAVE_X_WINDOWS
8536 #define HAVE_GHOSTSCRIPT 1
8537 #endif /* HAVE_X_WINDOWS */
8539 /* The symbol `postscript' identifying images of this type. */
8541 Lisp_Object Qpostscript
;
8543 #ifdef HAVE_GHOSTSCRIPT
8545 static int gs_image_p
P_ ((Lisp_Object object
));
8546 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8547 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8549 /* Keyword symbols. */
8551 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8553 /* Indices of image specification fields in gs_format, below. */
8555 enum gs_keyword_index
8573 /* Vector of image_keyword structures describing the format
8574 of valid user-defined image specifications. */
8576 static struct image_keyword gs_format
[GS_LAST
] =
8578 {":type", IMAGE_SYMBOL_VALUE
, 1},
8579 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8580 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8581 {":file", IMAGE_STRING_VALUE
, 1},
8582 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8583 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8584 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8585 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8586 {":relief", IMAGE_INTEGER_VALUE
, 0},
8587 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8588 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8589 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8590 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8593 /* Structure describing the image type `ghostscript'. */
8595 static struct image_type gs_type
=
8605 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8608 gs_clear_image (f
, img
)
8612 /* IMG->data.ptr_val may contain a recorded colormap. */
8613 xfree (img
->data
.ptr_val
);
8614 x_clear_image (f
, img
);
8618 /* Return non-zero if OBJECT is a valid Ghostscript image
8625 struct image_keyword fmt
[GS_LAST
];
8629 bcopy (gs_format
, fmt
, sizeof fmt
);
8631 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8634 /* Bounding box must be a list or vector containing 4 integers. */
8635 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8638 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8639 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8644 else if (VECTORP (tem
))
8646 if (XVECTOR (tem
)->size
!= 4)
8648 for (i
= 0; i
< 4; ++i
)
8649 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8659 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8668 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8669 struct gcpro gcpro1
, gcpro2
;
8671 double in_width
, in_height
;
8672 Lisp_Object pixel_colors
= Qnil
;
8674 /* Compute pixel size of pixmap needed from the given size in the
8675 image specification. Sizes in the specification are in pt. 1 pt
8676 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8678 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8679 in_width
= XFASTINT (pt_width
) / 72.0;
8680 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8681 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8682 in_height
= XFASTINT (pt_height
) / 72.0;
8683 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8685 if (!check_image_size (f
, img
->width
, img
->height
))
8687 image_error ("Invalid image size", Qnil
, Qnil
);
8691 /* Create the pixmap. */
8692 xassert (img
->pixmap
== NO_PIXMAP
);
8694 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8696 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8697 img
->width
, img
->height
,
8698 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8703 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8707 /* Call the loader to fill the pixmap. It returns a process object
8708 if successful. We do not record_unwind_protect here because
8709 other places in redisplay like calling window scroll functions
8710 don't either. Let the Lisp loader use `unwind-protect' instead. */
8711 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8713 sprintf (buffer
, "%lu %lu",
8714 (unsigned long) FRAME_X_WINDOW (f
),
8715 (unsigned long) img
->pixmap
);
8716 window_and_pixmap_id
= build_string (buffer
);
8718 sprintf (buffer
, "%lu %lu",
8719 FRAME_FOREGROUND_PIXEL (f
),
8720 FRAME_BACKGROUND_PIXEL (f
));
8721 pixel_colors
= build_string (buffer
);
8723 XSETFRAME (frame
, f
);
8724 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8726 loader
= intern ("gs-load-image");
8728 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8729 make_number (img
->width
),
8730 make_number (img
->height
),
8731 window_and_pixmap_id
,
8734 return PROCESSP (img
->data
.lisp_val
);
8738 /* Kill the Ghostscript process that was started to fill PIXMAP on
8739 frame F. Called from XTread_socket when receiving an event
8740 telling Emacs that Ghostscript has finished drawing. */
8743 x_kill_gs_process (pixmap
, f
)
8747 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8751 /* Find the image containing PIXMAP. */
8752 for (i
= 0; i
< c
->used
; ++i
)
8753 if (c
->images
[i
]->pixmap
== pixmap
)
8756 /* Should someone in between have cleared the image cache, for
8757 instance, give up. */
8761 /* Kill the GS process. We should have found PIXMAP in the image
8762 cache and its image should contain a process object. */
8764 xassert (PROCESSP (img
->data
.lisp_val
));
8765 Fkill_process (img
->data
.lisp_val
, Qnil
);
8766 img
->data
.lisp_val
= Qnil
;
8768 #if defined (HAVE_X_WINDOWS)
8770 /* On displays with a mutable colormap, figure out the colors
8771 allocated for the image by looking at the pixels of an XImage for
8773 class = FRAME_X_VISUAL (f
)->class;
8774 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8780 /* Try to get an XImage for img->pixmep. */
8781 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8782 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8787 /* Initialize the color table. */
8788 init_color_table ();
8790 /* For each pixel of the image, look its color up in the
8791 color table. After having done so, the color table will
8792 contain an entry for each color used by the image. */
8793 for (y
= 0; y
< img
->height
; ++y
)
8794 for (x
= 0; x
< img
->width
; ++x
)
8796 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8797 lookup_pixel_color (f
, pixel
);
8800 /* Record colors in the image. Free color table and XImage. */
8801 #ifdef COLOR_TABLE_SUPPORT
8802 img
->colors
= colors_in_color_table (&img
->ncolors
);
8803 free_color_table ();
8805 XDestroyImage (ximg
);
8807 #if 0 /* This doesn't seem to be the case. If we free the colors
8808 here, we get a BadAccess later in x_clear_image when
8809 freeing the colors. */
8810 /* We have allocated colors once, but Ghostscript has also
8811 allocated colors on behalf of us. So, to get the
8812 reference counts right, free them once. */
8814 x_free_colors (f
, img
->colors
, img
->ncolors
);
8818 image_error ("Cannot get X image of `%s'; colors will not be freed",
8823 #endif /* HAVE_X_WINDOWS */
8825 /* Now that we have the pixmap, compute mask and transform the
8826 image if requested. */
8828 postprocess_image (f
, img
);
8832 #endif /* HAVE_GHOSTSCRIPT */
8835 /***********************************************************************
8837 ***********************************************************************/
8841 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8842 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8846 return valid_image_p (spec
) ? Qt
: Qnil
;
8850 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8856 if (valid_image_p (spec
))
8857 id
= lookup_image (SELECTED_FRAME (), spec
);
8860 return make_number (id
);
8863 #endif /* GLYPH_DEBUG != 0 */
8866 /***********************************************************************
8868 ***********************************************************************/
8871 /* Image types that rely on external libraries are loaded dynamically
8872 if the library is available. */
8873 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8874 define_image_type (image_type, init_lib_fn (libraries))
8876 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8877 define_image_type (image_type, 1)
8878 #endif /* HAVE_NTGUI */
8880 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8881 doc
: /* Initialize image library implementing image type TYPE.
8882 Return non-nil if TYPE is a supported image type.
8884 Image types pbm and xbm are prebuilt; other types are loaded here.
8885 Libraries to load are specified in alist LIBRARIES (usually, the value
8886 of `image-library-alist', which see). */)
8888 Lisp_Object type
, libraries
;
8892 /* Don't try to reload the library. */
8893 tested
= Fassq (type
, Vimage_type_cache
);
8895 return XCDR (tested
);
8897 #if defined (HAVE_XPM) || defined (MAC_OS)
8898 if (EQ (type
, Qxpm
))
8899 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8902 #if defined (HAVE_JPEG) || defined (MAC_OS)
8903 if (EQ (type
, Qjpeg
))
8904 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8907 #if defined (HAVE_TIFF) || defined (MAC_OS)
8908 if (EQ (type
, Qtiff
))
8909 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8912 #if defined (HAVE_GIF) || defined (MAC_OS)
8913 if (EQ (type
, Qgif
))
8914 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8917 #if defined (HAVE_PNG) || defined (MAC_OS)
8918 if (EQ (type
, Qpng
))
8919 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8922 #ifdef HAVE_GHOSTSCRIPT
8923 if (EQ (type
, Qpostscript
))
8924 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8927 /* If the type is not recognized, avoid testing it ever again. */
8928 CACHE_IMAGE_TYPE (type
, Qnil
);
8935 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8937 /* Initialize this only once, since that's what we do with Vimage_types
8938 and they are supposed to be in sync. Initializing here gives correct
8939 operation on GNU/Linux of calling dump-emacs after loading some images. */
8942 /* Must be defined now becase we're going to update it below, while
8943 defining the supported image types. */
8944 DEFVAR_LISP ("image-types", &Vimage_types
,
8945 doc
: /* List of potentially supported image types.
8946 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8947 To check whether it is really supported, use `image-type-available-p'. */);
8948 Vimage_types
= Qnil
;
8950 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8951 doc
: /* Alist of image types vs external libraries needed to display them.
8953 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8954 representing a supported image type, and the rest are strings giving
8955 alternate filenames for the corresponding external libraries.
8957 Emacs tries to load the libraries in the order they appear on the
8958 list; if none is loaded, the running session of Emacs won't
8959 support the image type. Types 'pbm and 'xbm don't need to be
8960 listed; they are always supported. */);
8961 Vimage_library_alist
= Qnil
;
8962 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8964 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8965 doc
: /* Maximum size of images.
8966 Emacs will not load an image into memory if its pixel width or
8967 pixel height exceeds this limit.
8969 If the value is an integer, it directly specifies the maximum
8970 image height and width, measured in pixels. If it is a floating
8971 point number, it specifies the maximum image height and width
8972 as a ratio to the frame height and width. If the value is
8973 non-numeric, there is no explicit limit on the size of images. */);
8974 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8976 Vimage_type_cache
= Qnil
;
8977 staticpro (&Vimage_type_cache
);
8979 Qpbm
= intern ("pbm");
8981 ADD_IMAGE_TYPE(Qpbm
);
8983 Qxbm
= intern ("xbm");
8985 ADD_IMAGE_TYPE(Qxbm
);
8987 define_image_type (&xbm_type
, 1);
8988 define_image_type (&pbm_type
, 1);
8990 QCascent
= intern (":ascent");
8991 staticpro (&QCascent
);
8992 QCmargin
= intern (":margin");
8993 staticpro (&QCmargin
);
8994 QCrelief
= intern (":relief");
8995 staticpro (&QCrelief
);
8996 QCconversion
= intern (":conversion");
8997 staticpro (&QCconversion
);
8998 QCcolor_symbols
= intern (":color-symbols");
8999 staticpro (&QCcolor_symbols
);
9000 QCheuristic_mask
= intern (":heuristic-mask");
9001 staticpro (&QCheuristic_mask
);
9002 QCindex
= intern (":index");
9003 staticpro (&QCindex
);
9004 QCmatrix
= intern (":matrix");
9005 staticpro (&QCmatrix
);
9006 QCcolor_adjustment
= intern (":color-adjustment");
9007 staticpro (&QCcolor_adjustment
);
9008 QCmask
= intern (":mask");
9009 staticpro (&QCmask
);
9011 Qlaplace
= intern ("laplace");
9012 staticpro (&Qlaplace
);
9013 Qemboss
= intern ("emboss");
9014 staticpro (&Qemboss
);
9015 Qedge_detection
= intern ("edge-detection");
9016 staticpro (&Qedge_detection
);
9017 Qheuristic
= intern ("heuristic");
9018 staticpro (&Qheuristic
);
9020 Qpostscript
= intern ("postscript");
9021 staticpro (&Qpostscript
);
9022 #ifdef HAVE_GHOSTSCRIPT
9023 ADD_IMAGE_TYPE(Qpostscript
);
9024 QCloader
= intern (":loader");
9025 staticpro (&QCloader
);
9026 QCbounding_box
= intern (":bounding-box");
9027 staticpro (&QCbounding_box
);
9028 QCpt_width
= intern (":pt-width");
9029 staticpro (&QCpt_width
);
9030 QCpt_height
= intern (":pt-height");
9031 staticpro (&QCpt_height
);
9032 #endif /* HAVE_GHOSTSCRIPT */
9034 #if defined (HAVE_XPM) || defined (MAC_OS)
9035 Qxpm
= intern ("xpm");
9037 ADD_IMAGE_TYPE(Qxpm
);
9040 #if defined (HAVE_JPEG) || defined (MAC_OS)
9041 Qjpeg
= intern ("jpeg");
9043 ADD_IMAGE_TYPE(Qjpeg
);
9046 #if defined (HAVE_TIFF) || defined (MAC_OS)
9047 Qtiff
= intern ("tiff");
9049 ADD_IMAGE_TYPE(Qtiff
);
9052 #if defined (HAVE_GIF) || defined (MAC_OS)
9053 Qgif
= intern ("gif");
9055 ADD_IMAGE_TYPE(Qgif
);
9058 #if defined (HAVE_PNG) || defined (MAC_OS)
9059 Qpng
= intern ("png");
9061 ADD_IMAGE_TYPE(Qpng
);
9064 defsubr (&Sinit_image_library
);
9065 defsubr (&Sclear_image_cache
);
9066 defsubr (&Simage_refresh
);
9067 defsubr (&Simage_size
);
9068 defsubr (&Simage_mask_p
);
9069 defsubr (&Simage_extension_data
);
9073 defsubr (&Slookup_image
);
9076 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9077 doc
: /* Non-nil means always draw a cross over disabled images.
9078 Disabled images are those having a `:conversion disabled' property.
9079 A cross is always drawn on black & white displays. */);
9080 cross_disabled_images
= 0;
9082 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9083 doc
: /* List of directories to search for window system bitmap files. */);
9084 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9086 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9087 doc
: /* Time after which cached images are removed from the cache.
9088 When an image has not been displayed this many seconds, remove it
9089 from the image cache. Value must be an integer or nil with nil
9090 meaning don't clear the cache. */);
9091 Vimage_cache_eviction_delay
= make_number (30 * 60);
9099 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9100 (do not change this comment) */