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"
43 #include "character.h"
45 #include "termhooks.h"
50 #include <sys/types.h>
53 #define COLOR_TABLE_SUPPORT 1
55 typedef struct x_bitmap_record Bitmap_Record
;
56 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
57 #define NO_PIXMAP None
59 #define RGB_PIXEL_COLOR unsigned long
61 #define PIX_MASK_RETAIN 0
62 #define PIX_MASK_DRAW 1
63 #endif /* HAVE_X_WINDOWS */
69 /* W32_TODO : Color tables on W32. */
70 #undef COLOR_TABLE_SUPPORT
72 typedef struct w32_bitmap_record Bitmap_Record
;
73 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
76 #define RGB_PIXEL_COLOR COLORREF
78 #define PIX_MASK_RETAIN 0
79 #define PIX_MASK_DRAW 1
81 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
82 #define x_defined_color w32_defined_color
83 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
84 #endif /* HAVE_NTGUI */
92 #include <sys/param.h>
94 #if TARGET_API_MAC_CARBON
96 #include <QuickTime/QuickTime.h>
97 #else /* not MAC_OSX */
98 #include <QuickTime.h>
99 #endif /* not MAC_OSX */
100 #else /* not TARGET_API_MAC_CARBON */
103 #include <TextUtils.h>
104 #include <ImageCompression.h>
105 #include <QuickTimeComponents.h>
106 #endif /* not TARGET_API_MAC_CARBON */
108 /* MAC_TODO : Color tables on Mac. */
109 #undef COLOR_TABLE_SUPPORT
111 #define ZPixmap 0 /* arbitrary */
112 typedef struct mac_bitmap_record Bitmap_Record
;
114 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
117 #define RGB_PIXEL_COLOR unsigned long
120 #define PIX_MASK_DRAW 255
121 #define PIX_MASK_RETAIN 0
123 /* A black pixel in a mask bitmap/pixmap means ``draw a source
124 pixel''. A white pixel means ``retain the current pixel''. */
125 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
126 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
129 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
130 #define x_defined_color mac_defined_color
131 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
136 /* Search path for bitmap files. */
138 Lisp_Object Vx_bitmap_file_path
;
141 static void x_disable_image
P_ ((struct frame
*, struct image
*));
142 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
145 static void init_color_table
P_ ((void));
146 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
147 #ifdef COLOR_TABLE_SUPPORT
148 static void free_color_table
P_ ((void));
149 static unsigned long *colors_in_color_table
P_ ((int *n
));
150 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
153 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
154 id, which is just an int that this section returns. Bitmaps are
155 reference counted so they can be shared among frames.
157 Bitmap indices are guaranteed to be > 0, so a negative number can
158 be used to indicate no bitmap.
160 If you use x_create_bitmap_from_data, then you must keep track of
161 the bitmaps yourself. That is, creating a bitmap from the same
162 data more than once will not be caught. */
167 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
168 Display
*display
; /* not used */
170 int x
, y
; /* not used */
171 unsigned int width
, height
; /* not used */
172 unsigned long plane_mask
; /* not used */
173 int format
; /* not used */
175 #if !USE_MAC_IMAGE_IO
177 xassert (x
== 0 && y
== 0);
180 SetRect (&ri
, 0, 0, width
, height
);
181 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
183 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
186 LockPixels (GetGWorldPixMap (pixmap
));
193 XPutPixel (ximage
, x
, y
, pixel
)
199 if (ximage
->bits_per_pixel
== 32)
200 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
202 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
204 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
205 short depth
= GetPixDepth (pixmap
);
207 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
210 char *base_addr
= GetPixBaseAddr (pixmap
);
211 short row_bytes
= GetPixRowBytes (pixmap
);
213 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
219 char *base_addr
= GetPixBaseAddr (pixmap
);
220 short row_bytes
= GetPixRowBytes (pixmap
);
222 if (pixel
== PIX_MASK_DRAW
)
223 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
225 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
233 GetGWorld (&old_port
, &old_gdh
);
234 SetGWorld (ximage
, NULL
);
236 color
.red
= RED16_FROM_ULONG (pixel
);
237 color
.green
= GREEN16_FROM_ULONG (pixel
);
238 color
.blue
= BLUE16_FROM_ULONG (pixel
);
240 SetCPixel (x
, y
, &color
);
242 SetGWorld (old_port
, old_gdh
);
248 XGetPixel (ximage
, x
, y
)
253 if (ximage
->bits_per_pixel
== 32)
254 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
256 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
258 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
259 short depth
= GetPixDepth (pixmap
);
261 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
264 char *base_addr
= GetPixBaseAddr (pixmap
);
265 short row_bytes
= GetPixRowBytes (pixmap
);
267 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
273 char *base_addr
= GetPixBaseAddr (pixmap
);
274 short row_bytes
= GetPixRowBytes (pixmap
);
276 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
277 return PIX_MASK_DRAW
;
279 return PIX_MASK_RETAIN
;
287 GetGWorld (&old_port
, &old_gdh
);
288 SetGWorld (ximage
, NULL
);
290 GetCPixel (x
, y
, &color
);
292 SetGWorld (old_port
, old_gdh
);
293 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
302 #if !USE_MAC_IMAGE_IO
303 UnlockPixels (GetGWorldPixMap (ximg
));
310 mac_data_provider_release_data (info
, data
, size
)
315 xfree ((void *)data
);
320 mac_create_cg_image_from_image (f
, img
)
325 XImagePtr ximg
= img
->pixmap
;
326 CGDataProviderRef provider
;
332 unsigned long color
, alpha
;
334 for (y
= 0; y
< ximg
->height
; y
++)
335 for (x
= 0; x
< ximg
->width
; x
++)
337 color
= XGetPixel (ximg
, x
, y
);
338 alpha
= XGetPixel (img
->mask
, x
, y
);
339 XPutPixel (ximg
, x
, y
,
340 ARGB_TO_ULONG (alpha
,
341 RED_FROM_ULONG (color
)
342 * alpha
/ PIX_MASK_DRAW
,
343 GREEN_FROM_ULONG (color
)
344 * alpha
/ PIX_MASK_DRAW
,
345 BLUE_FROM_ULONG (color
)
346 * alpha
/ PIX_MASK_DRAW
));
348 xfree (img
->mask
->data
);
349 img
->mask
->data
= NULL
;
352 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
353 ximg
->bytes_per_line
* ximg
->height
,
354 mac_data_provider_release_data
);
356 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
357 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
358 (img
->mask
? kCGImageAlphaPremultipliedFirst
359 : kCGImageAlphaNoneSkipFirst
)
360 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
361 | kCGBitmapByteOrder32Host
363 , provider
, NULL
, 0, kCGRenderingIntentDefault
);
364 CGDataProviderRelease (provider
);
370 CGImageRef result
= NULL
;
377 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
378 img
->width
, img
->height
, 1);
385 GetGWorld (&old_port
, &old_gdh
);
386 SetGWorld (mask
, NULL
);
387 BackColor (blackColor
); /* Don't mask. */
388 SetRect (&r
, 0, 0, img
->width
, img
->height
);
390 SetGWorld (old_port
, old_gdh
);
395 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
396 GetGWorldPixMap (mask
), &result
);
397 if (mask
!= img
->mask
)
398 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
405 #endif /* USE_CG_DRAWING */
409 /* Functions to access the contents of a bitmap, given an id. */
412 x_bitmap_height (f
, id
)
416 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
420 x_bitmap_width (f
, id
)
424 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
427 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
429 x_bitmap_pixmap (f
, id
)
433 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
437 #ifdef HAVE_X_WINDOWS
439 x_bitmap_mask (f
, id
)
443 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
447 /* Allocate a new bitmap record. Returns index of new record. */
450 x_allocate_bitmap_record (f
)
453 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
456 if (dpyinfo
->bitmaps
== NULL
)
458 dpyinfo
->bitmaps_size
= 10;
460 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
461 dpyinfo
->bitmaps_last
= 1;
465 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
466 return ++dpyinfo
->bitmaps_last
;
468 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
469 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
472 dpyinfo
->bitmaps_size
*= 2;
474 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
475 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
476 return ++dpyinfo
->bitmaps_last
;
479 /* Add one reference to the reference count of the bitmap with id ID. */
482 x_reference_bitmap (f
, id
)
486 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
489 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
492 x_create_bitmap_from_data (f
, bits
, width
, height
)
495 unsigned int width
, height
;
497 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
500 #ifdef HAVE_X_WINDOWS
502 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
503 bits
, width
, height
);
506 #endif /* HAVE_X_WINDOWS */
510 bitmap
= CreateBitmap (width
, height
,
511 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
512 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
516 #endif /* HAVE_NTGUI */
519 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
524 id
= x_allocate_bitmap_record (f
);
526 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
527 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
530 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
531 dpyinfo
->bitmaps
[id
- 1].height
= height
;
532 dpyinfo
->bitmaps
[id
- 1].width
= width
;
533 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
535 #ifdef HAVE_X_WINDOWS
536 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
537 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
538 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
539 #endif /* HAVE_X_WINDOWS */
542 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
543 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
544 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
545 #endif /* HAVE_NTGUI */
550 /* Create bitmap from file FILE for frame F. */
553 x_create_bitmap_from_file (f
, file
)
558 return -1; /* MAC_TODO : bitmap support */
562 return -1; /* W32_TODO : bitmap support */
563 #endif /* HAVE_NTGUI */
565 #ifdef HAVE_X_WINDOWS
566 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
567 unsigned int width
, height
;
569 int xhot
, yhot
, result
, id
;
574 /* Look for an existing bitmap with the same name. */
575 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
577 if (dpyinfo
->bitmaps
[id
].refcount
578 && dpyinfo
->bitmaps
[id
].file
579 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
581 ++dpyinfo
->bitmaps
[id
].refcount
;
586 /* Search bitmap-file-path for the file, if appropriate. */
587 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
592 filename
= (char *) SDATA (found
);
594 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
595 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
596 if (result
!= BitmapSuccess
)
599 id
= x_allocate_bitmap_record (f
);
600 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
601 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
602 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
603 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
604 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
605 dpyinfo
->bitmaps
[id
- 1].height
= height
;
606 dpyinfo
->bitmaps
[id
- 1].width
= width
;
607 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
610 #endif /* HAVE_X_WINDOWS */
616 free_bitmap_record (dpyinfo
, bm
)
617 Display_Info
*dpyinfo
;
620 #ifdef HAVE_X_WINDOWS
621 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
623 XFreePixmap (dpyinfo
->display
, bm
->mask
);
624 #endif /* HAVE_X_WINDOWS */
627 DeleteObject (bm
->pixmap
);
628 #endif /* HAVE_NTGUI */
631 xfree (bm
->bitmap_data
); /* Added ++kfs */
632 bm
->bitmap_data
= NULL
;
642 /* Remove reference to bitmap with id number ID. */
645 x_destroy_bitmap (f
, id
)
649 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
653 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
655 if (--bm
->refcount
== 0)
658 free_bitmap_record (dpyinfo
, bm
);
664 /* Free all the bitmaps for the display specified by DPYINFO. */
667 x_destroy_all_bitmaps (dpyinfo
)
668 Display_Info
*dpyinfo
;
671 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
673 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
674 if (bm
->refcount
> 0)
675 free_bitmap_record (dpyinfo
, bm
);
677 dpyinfo
->bitmaps_last
= 0;
681 #ifdef HAVE_X_WINDOWS
683 /* Useful functions defined in the section
684 `Image type independent image structures' below. */
686 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
689 unsigned long height
));
691 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
692 int depth
, XImagePtr
*ximg
,
695 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
698 /* Create a mask of a bitmap. Note is this not a perfect mask.
699 It's nicer with some borders in this context */
702 x_create_bitmap_mask (f
, id
)
707 XImagePtr ximg
, mask_img
;
708 unsigned long width
, height
;
711 unsigned long x
, y
, xp
, xm
, yp
, ym
;
714 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
719 pixmap
= x_bitmap_pixmap (f
, id
);
720 width
= x_bitmap_width (f
, id
);
721 height
= x_bitmap_height (f
, id
);
724 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
733 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
738 XDestroyImage (ximg
);
742 bg
= four_corners_best (ximg
, NULL
, width
, height
);
744 for (y
= 0; y
< ximg
->height
; ++y
)
746 for (x
= 0; x
< ximg
->width
; ++x
)
748 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
749 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
750 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
751 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
752 if (XGetPixel (ximg
, x
, y
) == bg
753 && XGetPixel (ximg
, x
, yp
) == bg
754 && XGetPixel (ximg
, x
, ym
) == bg
755 && XGetPixel (ximg
, xp
, y
) == bg
756 && XGetPixel (ximg
, xp
, yp
) == bg
757 && XGetPixel (ximg
, xp
, ym
) == bg
758 && XGetPixel (ximg
, xm
, y
) == bg
759 && XGetPixel (ximg
, xm
, yp
) == bg
760 && XGetPixel (ximg
, xm
, ym
) == bg
)
761 XPutPixel (mask_img
, x
, y
, 0);
763 XPutPixel (mask_img
, x
, y
, 1);
767 xassert (interrupt_input_blocked
);
768 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
769 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
771 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
773 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
774 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
776 XDestroyImage (ximg
);
777 x_destroy_x_image (mask_img
);
782 #endif /* HAVE_X_WINDOWS */
785 /***********************************************************************
787 ***********************************************************************/
789 /* Value is the number of elements of vector VECTOR. */
791 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
793 /* List of supported image types. Use define_image_type to add new
794 types. Use lookup_image_type to find a type for a given symbol. */
796 static struct image_type
*image_types
;
798 /* A list of symbols, one for each supported image type. */
800 Lisp_Object Vimage_types
;
802 /* An alist of image types and libraries that implement the type. */
804 Lisp_Object Vimage_library_alist
;
806 /* Cache for delayed-loading image types. */
808 static Lisp_Object Vimage_type_cache
;
810 /* The symbol `xbm' which is used as the type symbol for XBM images. */
816 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
817 extern Lisp_Object QCdata
, QCtype
;
818 extern Lisp_Object Qcenter
;
819 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
820 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
821 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
825 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
827 /* Time in seconds after which images should be removed from the cache
830 Lisp_Object Vimage_cache_eviction_delay
;
832 /* Function prototypes. */
834 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
835 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
836 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
837 static void x_laplace
P_ ((struct frame
*, struct image
*));
838 static void x_emboss
P_ ((struct frame
*, struct image
*));
839 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
842 #define CACHE_IMAGE_TYPE(type, status) \
843 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
845 #define ADD_IMAGE_TYPE(type) \
846 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
848 /* Define a new image type from TYPE. This adds a copy of TYPE to
849 image_types and caches the loading status of TYPE. */
852 define_image_type (type
, loaded
)
853 struct image_type
*type
;
862 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
863 The initialized data segment is read-only. */
864 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
865 bcopy (type
, p
, sizeof *p
);
866 p
->next
= image_types
;
871 CACHE_IMAGE_TYPE (*type
->type
, success
);
876 /* Look up image type SYMBOL, and return a pointer to its image_type
877 structure. Value is null if SYMBOL is not a known image type. */
879 static INLINE
struct image_type
*
880 lookup_image_type (symbol
)
883 struct image_type
*type
;
885 /* We must initialize the image-type if it hasn't been already. */
886 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
887 return 0; /* unimplemented */
889 for (type
= image_types
; type
; type
= type
->next
)
890 if (EQ (symbol
, *type
->type
))
897 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
898 valid image specification is a list whose car is the symbol
899 `image', and whose rest is a property list. The property list must
900 contain a value for key `:type'. That value must be the name of a
901 supported image type. The rest of the property list depends on the
905 valid_image_p (object
)
914 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
915 if (EQ (XCAR (tem
), QCtype
))
918 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
920 struct image_type
*type
;
921 type
= lookup_image_type (XCAR (tem
));
923 valid_p
= type
->valid_p (object
);
934 /* Log error message with format string FORMAT and argument ARG.
935 Signaling an error, e.g. when an image cannot be loaded, is not a
936 good idea because this would interrupt redisplay, and the error
937 message display would lead to another redisplay. This function
938 therefore simply displays a message. */
941 image_error (format
, arg1
, arg2
)
943 Lisp_Object arg1
, arg2
;
945 add_to_log (format
, arg1
, arg2
);
950 /***********************************************************************
952 ***********************************************************************/
954 enum image_value_type
956 IMAGE_DONT_CHECK_VALUE_TYPE
,
958 IMAGE_STRING_OR_NIL_VALUE
,
960 IMAGE_POSITIVE_INTEGER_VALUE
,
961 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
962 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
965 IMAGE_FUNCTION_VALUE
,
970 /* Structure used when parsing image specifications. */
974 /* Name of keyword. */
977 /* The type of value allowed. */
978 enum image_value_type type
;
980 /* Non-zero means key must be present. */
983 /* Used to recognize duplicate keywords in a property list. */
986 /* The value that was found. */
991 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
993 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
996 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
997 has the format (image KEYWORD VALUE ...). One of the keyword/
998 value pairs must be `:type TYPE'. KEYWORDS is a vector of
999 image_keywords structures of size NKEYWORDS describing other
1000 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1003 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1005 struct image_keyword
*keywords
;
1015 plist
= XCDR (spec
);
1016 while (CONSP (plist
))
1018 Lisp_Object key
, value
;
1020 /* First element of a pair must be a symbol. */
1022 plist
= XCDR (plist
);
1026 /* There must follow a value. */
1029 value
= XCAR (plist
);
1030 plist
= XCDR (plist
);
1032 /* Find key in KEYWORDS. Error if not found. */
1033 for (i
= 0; i
< nkeywords
; ++i
)
1034 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1040 /* Record that we recognized the keyword. If a keywords
1041 was found more than once, it's an error. */
1042 keywords
[i
].value
= value
;
1043 ++keywords
[i
].count
;
1045 if (keywords
[i
].count
> 1)
1048 /* Check type of value against allowed type. */
1049 switch (keywords
[i
].type
)
1051 case IMAGE_STRING_VALUE
:
1052 if (!STRINGP (value
))
1056 case IMAGE_STRING_OR_NIL_VALUE
:
1057 if (!STRINGP (value
) && !NILP (value
))
1061 case IMAGE_SYMBOL_VALUE
:
1062 if (!SYMBOLP (value
))
1066 case IMAGE_POSITIVE_INTEGER_VALUE
:
1067 if (!INTEGERP (value
) || XINT (value
) <= 0)
1071 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1072 if (INTEGERP (value
) && XINT (value
) >= 0)
1075 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1076 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1080 case IMAGE_ASCENT_VALUE
:
1081 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1083 else if (INTEGERP (value
)
1084 && XINT (value
) >= 0
1085 && XINT (value
) <= 100)
1089 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1090 if (!INTEGERP (value
) || XINT (value
) < 0)
1094 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1097 case IMAGE_FUNCTION_VALUE
:
1098 value
= indirect_function (value
);
1100 || COMPILEDP (value
)
1101 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1105 case IMAGE_NUMBER_VALUE
:
1106 if (!INTEGERP (value
) && !FLOATP (value
))
1110 case IMAGE_INTEGER_VALUE
:
1111 if (!INTEGERP (value
))
1115 case IMAGE_BOOL_VALUE
:
1116 if (!NILP (value
) && !EQ (value
, Qt
))
1125 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1129 /* Check that all mandatory fields are present. */
1130 for (i
= 0; i
< nkeywords
; ++i
)
1131 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1134 return NILP (plist
);
1138 /* Return the value of KEY in image specification SPEC. Value is nil
1139 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1140 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1143 image_spec_value (spec
, key
, found
)
1144 Lisp_Object spec
, key
;
1149 xassert (valid_image_p (spec
));
1151 for (tail
= XCDR (spec
);
1152 CONSP (tail
) && CONSP (XCDR (tail
));
1153 tail
= XCDR (XCDR (tail
)))
1155 if (EQ (XCAR (tail
), key
))
1159 return XCAR (XCDR (tail
));
1169 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1170 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1171 PIXELS non-nil means return the size in pixels, otherwise return the
1172 size in canonical character units.
1173 FRAME is the frame on which the image will be displayed. FRAME nil
1174 or omitted means use the selected frame. */)
1175 (spec
, pixels
, frame
)
1176 Lisp_Object spec
, pixels
, frame
;
1181 if (valid_image_p (spec
))
1183 struct frame
*f
= check_x_frame (frame
);
1184 int id
= lookup_image (f
, spec
);
1185 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1186 int width
= img
->width
+ 2 * img
->hmargin
;
1187 int height
= img
->height
+ 2 * img
->vmargin
;
1190 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1191 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1193 size
= Fcons (make_number (width
), make_number (height
));
1196 error ("Invalid image specification");
1202 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1203 doc
: /* Return t if image SPEC has a mask bitmap.
1204 FRAME is the frame on which the image will be displayed. FRAME nil
1205 or omitted means use the selected frame. */)
1207 Lisp_Object spec
, frame
;
1212 if (valid_image_p (spec
))
1214 struct frame
*f
= check_x_frame (frame
);
1215 int id
= lookup_image (f
, spec
);
1216 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1221 error ("Invalid image specification");
1226 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1227 doc
: /* Return extension data for image SPEC.
1228 FRAME is the frame on which the image will be displayed. FRAME nil
1229 or omitted means use the selected frame. */)
1231 Lisp_Object spec
, frame
;
1236 if (valid_image_p (spec
))
1238 struct frame
*f
= check_x_frame (frame
);
1239 int id
= lookup_image (f
, spec
);
1240 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1241 ext
= img
->data
.lisp_val
;
1248 /***********************************************************************
1249 Image type independent image structures
1250 ***********************************************************************/
1252 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1253 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1254 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1256 #define MAX_IMAGE_SIZE 6.0
1257 Lisp_Object Vmax_image_size
;
1259 /* Allocate and return a new image structure for image specification
1260 SPEC. SPEC has a hash value of HASH. */
1262 static struct image
*
1263 make_image (spec
, hash
)
1267 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1268 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1270 xassert (valid_image_p (spec
));
1271 bzero (img
, sizeof *img
);
1272 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1273 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1274 xassert (img
->type
!= NULL
);
1276 img
->data
.lisp_val
= Qnil
;
1277 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1279 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1284 /* Free image IMG which was used on frame F, including its resources. */
1293 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1295 /* Remove IMG from the hash table of its cache. */
1297 img
->prev
->next
= img
->next
;
1299 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1302 img
->next
->prev
= img
->prev
;
1304 c
->images
[img
->id
] = NULL
;
1306 /* Free resources, then free IMG. */
1307 img
->type
->free (f
, img
);
1312 /* Return 1 if the given widths and heights are valid for display;
1313 otherwise, return 0. */
1316 check_image_size (f
, width
, height
)
1323 if (width
<= 0 || height
<= 0)
1326 if (INTEGERP (Vmax_image_size
))
1327 w
= h
= XINT (Vmax_image_size
);
1328 else if (FLOATP (Vmax_image_size
))
1332 w
= FRAME_PIXEL_WIDTH (f
);
1333 h
= FRAME_PIXEL_HEIGHT (f
);
1336 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1337 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1338 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1343 return (width
<= w
&& height
<= h
);
1346 /* Prepare image IMG for display on frame F. Must be called before
1347 drawing an image. */
1350 prepare_image_for_display (f
, img
)
1356 /* We're about to display IMG, so set its timestamp to `now'. */
1358 img
->timestamp
= EMACS_SECS (t
);
1360 /* If IMG doesn't have a pixmap yet, load it now, using the image
1361 type dependent loader function. */
1362 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1363 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1365 #if defined (MAC_OS) && USE_CG_DRAWING
1366 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1368 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1369 if (img
->data
.ptr_val
== NULL
)
1371 img
->load_failed_p
= 1;
1372 img
->type
->free (f
, img
);
1379 /* Value is the number of pixels for the ascent of image IMG when
1380 drawn in face FACE. */
1383 image_ascent (img
, face
, slice
)
1386 struct glyph_slice
*slice
;
1391 if (slice
->height
== img
->height
)
1392 height
= img
->height
+ img
->vmargin
;
1393 else if (slice
->y
== 0)
1394 height
= slice
->height
+ img
->vmargin
;
1396 height
= slice
->height
;
1398 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1403 /* W32 specific version. Why?. ++kfs */
1404 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1405 - FONT_BASE (face
->font
)) / 2;
1407 /* This expression is arranged so that if the image can't be
1408 exactly centered, it will be moved slightly up. This is
1409 because a typical font is `top-heavy' (due to the presence
1410 uppercase letters), so the image placement should err towards
1411 being top-heavy too. It also just generally looks better. */
1412 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1413 #endif /* HAVE_NTGUI */
1416 ascent
= height
/ 2;
1419 ascent
= (int) (height
* img
->ascent
/ 100.0);
1425 /* Image background colors. */
1427 /* Find the "best" corner color of a bitmap.
1428 On W32, XIMG is assumed to a device context with the bitmap selected. */
1430 static RGB_PIXEL_COLOR
1431 four_corners_best (ximg
, corners
, width
, height
)
1432 XImagePtr_or_DC ximg
;
1434 unsigned long width
, height
;
1436 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1439 if (corners
&& corners
[BOT_CORNER
] >= 0)
1441 /* Get the colors at the corner_pixels of ximg. */
1442 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1443 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1444 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1445 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1449 /* Get the colors at the corner_pixels of ximg. */
1450 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1451 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1452 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1453 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1455 /* Choose the most frequently found color as background. */
1456 for (i
= best_count
= 0; i
< 4; ++i
)
1460 for (j
= n
= 0; j
< 4; ++j
)
1461 if (corner_pixels
[i
] == corner_pixels
[j
])
1465 best
= corner_pixels
[i
], best_count
= n
;
1471 /* Portability macros */
1475 #define Destroy_Image(img_dc, prev) \
1476 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1478 #define Free_Pixmap(display, pixmap) \
1479 DeleteObject (pixmap)
1483 #define Destroy_Image(ximg, dummy) \
1484 XDestroyImage (ximg)
1486 #define Free_Pixmap(display, pixmap) \
1487 XFreePixmap (display, pixmap)
1489 #endif /* HAVE_NTGUI */
1492 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1493 it is guessed heuristically. If non-zero, XIMG is an existing
1494 XImage object (or device context with the image selected on W32) to
1495 use for the heuristic. */
1498 image_background (img
, f
, ximg
)
1501 XImagePtr_or_DC ximg
;
1503 if (! img
->background_valid
)
1504 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1506 int free_ximg
= !ximg
;
1509 #endif /* HAVE_NTGUI */
1514 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1515 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1517 HDC frame_dc
= get_frame_dc (f
);
1518 ximg
= CreateCompatibleDC (frame_dc
);
1519 release_frame_dc (f
, frame_dc
);
1520 prev
= SelectObject (ximg
, img
->pixmap
);
1521 #endif /* !HAVE_NTGUI */
1524 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1527 Destroy_Image (ximg
, prev
);
1529 img
->background_valid
= 1;
1532 return img
->background
;
1535 /* Return the `background_transparent' field of IMG. If IMG doesn't
1536 have one yet, it is guessed heuristically. If non-zero, MASK is an
1537 existing XImage object to use for the heuristic. */
1540 image_background_transparent (img
, f
, mask
)
1543 XImagePtr_or_DC mask
;
1545 if (! img
->background_transparent_valid
)
1546 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1550 int free_mask
= !mask
;
1553 #endif /* HAVE_NTGUI */
1558 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1559 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1561 HDC frame_dc
= get_frame_dc (f
);
1562 mask
= CreateCompatibleDC (frame_dc
);
1563 release_frame_dc (f
, frame_dc
);
1564 prev
= SelectObject (mask
, img
->mask
);
1565 #endif /* HAVE_NTGUI */
1568 img
->background_transparent
1569 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1572 Destroy_Image (mask
, prev
);
1575 img
->background_transparent
= 0;
1577 img
->background_transparent_valid
= 1;
1580 return img
->background_transparent
;
1584 /***********************************************************************
1585 Helper functions for X image types
1586 ***********************************************************************/
1588 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1590 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1591 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1593 Lisp_Object color_name
,
1594 unsigned long dflt
));
1597 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1598 free the pixmap if any. MASK_P non-zero means clear the mask
1599 pixmap if any. COLORS_P non-zero means free colors allocated for
1600 the image, if any. */
1603 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1606 int pixmap_p
, mask_p
, colors_p
;
1608 if (pixmap_p
&& img
->pixmap
)
1610 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1611 img
->pixmap
= NO_PIXMAP
;
1612 img
->background_valid
= 0;
1615 if (mask_p
&& img
->mask
)
1617 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1618 img
->mask
= NO_PIXMAP
;
1619 img
->background_transparent_valid
= 0;
1622 if (colors_p
&& img
->ncolors
)
1624 /* MAC_TODO: color table support. */
1625 /* W32_TODO: color table support. */
1626 #ifdef HAVE_X_WINDOWS
1627 x_free_colors (f
, img
->colors
, img
->ncolors
);
1628 #endif /* HAVE_X_WINDOWS */
1629 xfree (img
->colors
);
1634 #if defined (MAC_OS) && USE_CG_DRAWING
1635 if (img
->data
.ptr_val
)
1637 CGImageRelease (img
->data
.ptr_val
);
1638 img
->data
.ptr_val
= NULL
;
1643 /* Free X resources of image IMG which is used on frame F. */
1646 x_clear_image (f
, img
)
1651 x_clear_image_1 (f
, img
, 1, 1, 1);
1656 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1657 cannot be allocated, use DFLT. Add a newly allocated color to
1658 IMG->colors, so that it can be freed again. Value is the pixel
1661 static unsigned long
1662 x_alloc_image_color (f
, img
, color_name
, dflt
)
1665 Lisp_Object color_name
;
1669 unsigned long result
;
1671 xassert (STRINGP (color_name
));
1673 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1675 /* This isn't called frequently so we get away with simply
1676 reallocating the color vector to the needed size, here. */
1679 (unsigned long *) xrealloc (img
->colors
,
1680 img
->ncolors
* sizeof *img
->colors
);
1681 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1682 result
= color
.pixel
;
1692 /***********************************************************************
1694 ***********************************************************************/
1696 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1697 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1698 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1700 /* Return a new, initialized image cache that is allocated from the
1701 heap. Call free_image_cache to free an image cache. */
1703 struct image_cache
*
1706 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1709 bzero (c
, sizeof *c
);
1711 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1712 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1713 c
->buckets
= (struct image
**) xmalloc (size
);
1714 bzero (c
->buckets
, size
);
1719 /* Find an image matching SPEC in the cache, and return it. If no
1720 image is found, return NULL. */
1721 static struct image
*
1722 search_image_cache (f
, spec
, hash
)
1728 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1729 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1731 if (!c
) return NULL
;
1733 /* If the image spec does not specify a background color, the cached
1734 image must have the same background color as the current frame.
1735 The foreground color must also match, for the sake of monochrome
1738 In fact, we could ignore the foreground color matching condition
1739 for color images, or if the image spec specifies :foreground;
1740 similarly we could ignore the background color matching condition
1741 for formats that don't use transparency (such as jpeg), or if the
1742 image spec specifies :background. However, the extra memory
1743 usage is probably negligible in practice, so we don't bother. */
1745 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1746 if (img
->hash
== hash
1747 && !NILP (Fequal (img
->spec
, spec
))
1748 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1749 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1755 /* Search frame F for an image with spec SPEC, and free it. */
1758 uncache_image (f
, spec
)
1762 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1764 free_image (f
, img
);
1768 /* Free image cache of frame F. Be aware that X frames share images
1772 free_image_cache (f
)
1775 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1780 /* Cache should not be referenced by any frame when freed. */
1781 xassert (c
->refcount
== 0);
1783 for (i
= 0; i
< c
->used
; ++i
)
1784 free_image (f
, c
->images
[i
]);
1788 FRAME_IMAGE_CACHE (f
) = NULL
;
1793 /* Clear image cache of frame F. FILTER=t means free all images.
1794 FILTER=nil means clear only images that haven't been
1795 displayed for some time.
1796 Else, only free the images which have FILTER in their `dependencies'.
1797 Should be called from time to time to reduce the number of loaded images.
1798 If image-cache-eviction-delay is non-nil, this frees images in the cache
1799 which weren't displayed for at least that many seconds. */
1802 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1804 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1806 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1813 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1815 /* Block input so that we won't be interrupted by a SIGIO
1816 while being in an inconsistent state. */
1819 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1821 struct image
*img
= c
->images
[i
];
1823 && (NILP (filter
) ? img
->timestamp
< old
1825 || !NILP (Fmember (filter
, img
->dependencies
)))))
1827 free_image (f
, img
);
1832 /* We may be clearing the image cache because, for example,
1833 Emacs was iconified for a longer period of time. In that
1834 case, current matrices may still contain references to
1835 images freed above. So, clear these matrices. */
1838 Lisp_Object tail
, frame
;
1840 FOR_EACH_FRAME (tail
, frame
)
1842 struct frame
*f
= XFRAME (frame
);
1843 if (FRAME_IMAGE_CACHE (f
) == c
)
1844 clear_current_matrices (f
);
1847 ++windows_or_buffers_changed
;
1855 clear_image_caches (Lisp_Object filter
)
1857 /* FIXME: We want to do
1858 * struct terminal *t;
1859 * for (t = terminal_list; t; t = t->next_terminal)
1860 * clear_image_cache (t, filter); */
1861 Lisp_Object tail
, frame
;
1862 FOR_EACH_FRAME (tail
, frame
)
1863 if (FRAME_WINDOW_P (XFRAME (frame
)))
1864 clear_image_cache (XFRAME (frame
), filter
);
1867 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1869 doc
: /* Clear the image cache.
1870 FILTER nil or a frame means clear all images in the selected frame.
1871 FILTER t means clear the image caches of all frames.
1872 Anything else, means only clear those images which refer to FILTER,
1873 which is then usually a filename. */)
1877 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1878 clear_image_caches (filter
);
1880 clear_image_cache (check_x_frame (filter
), Qt
);
1886 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1888 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1889 If SPEC specifies an image file, the displayed image is updated with
1890 the current contents of that file.
1891 FRAME nil or omitted means use the selected frame.
1892 FRAME t means refresh the image on all frames. */)
1894 Lisp_Object spec
, frame
;
1896 if (!valid_image_p (spec
))
1897 error ("Invalid image specification");
1902 FOR_EACH_FRAME (tail
, frame
)
1904 struct frame
*f
= XFRAME (frame
);
1905 if (FRAME_WINDOW_P (f
))
1906 uncache_image (f
, spec
);
1910 uncache_image (check_x_frame (frame
), spec
);
1916 /* Compute masks and transform image IMG on frame F, as specified
1917 by the image's specification, */
1920 postprocess_image (f
, img
)
1924 /* Manipulation of the image's mask. */
1927 Lisp_Object conversion
, spec
;
1932 /* `:heuristic-mask t'
1934 means build a mask heuristically.
1935 `:heuristic-mask (R G B)'
1936 `:mask (heuristic (R G B))'
1937 means build a mask from color (R G B) in the
1940 means remove a mask, if any. */
1942 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1944 x_build_heuristic_mask (f
, img
, mask
);
1949 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1951 if (EQ (mask
, Qheuristic
))
1952 x_build_heuristic_mask (f
, img
, Qt
);
1953 else if (CONSP (mask
)
1954 && EQ (XCAR (mask
), Qheuristic
))
1956 if (CONSP (XCDR (mask
)))
1957 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1959 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1961 else if (NILP (mask
) && found_p
&& img
->mask
)
1963 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1964 img
->mask
= NO_PIXMAP
;
1969 /* Should we apply an image transformation algorithm? */
1970 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1971 if (EQ (conversion
, Qdisabled
))
1972 x_disable_image (f
, img
);
1973 else if (EQ (conversion
, Qlaplace
))
1975 else if (EQ (conversion
, Qemboss
))
1977 else if (CONSP (conversion
)
1978 && EQ (XCAR (conversion
), Qedge_detection
))
1981 tem
= XCDR (conversion
);
1983 x_edge_detection (f
, img
,
1984 Fplist_get (tem
, QCmatrix
),
1985 Fplist_get (tem
, QCcolor_adjustment
));
1991 /* Return the id of image with Lisp specification SPEC on frame F.
1992 SPEC must be a valid Lisp image specification (see valid_image_p). */
1995 lookup_image (f
, spec
)
1999 struct image_cache
*c
;
2002 struct gcpro gcpro1
;
2005 /* F must be a window-system frame, and SPEC must be a valid image
2007 xassert (FRAME_WINDOW_P (f
));
2008 xassert (valid_image_p (spec
));
2010 c
= FRAME_IMAGE_CACHE (f
);
2014 /* Look up SPEC in the hash table of the image cache. */
2015 hash
= sxhash (spec
, 0);
2016 img
= search_image_cache (f
, spec
, hash
);
2017 if (img
&& img
->load_failed_p
)
2019 free_image (f
, img
);
2023 /* If not found, create a new image and cache it. */
2026 extern Lisp_Object Qpostscript
;
2029 img
= make_image (spec
, hash
);
2030 cache_image (f
, img
);
2031 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2032 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2033 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2035 /* If we can't load the image, and we don't have a width and
2036 height, use some arbitrary width and height so that we can
2037 draw a rectangle for it. */
2038 if (img
->load_failed_p
)
2042 value
= image_spec_value (spec
, QCwidth
, NULL
);
2043 img
->width
= (INTEGERP (value
)
2044 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2045 value
= image_spec_value (spec
, QCheight
, NULL
);
2046 img
->height
= (INTEGERP (value
)
2047 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2051 /* Handle image type independent image attributes
2052 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2053 `:background COLOR'. */
2054 Lisp_Object ascent
, margin
, relief
, bg
;
2056 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2057 if (INTEGERP (ascent
))
2058 img
->ascent
= XFASTINT (ascent
);
2059 else if (EQ (ascent
, Qcenter
))
2060 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2062 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2063 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2064 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2065 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2066 && INTEGERP (XCDR (margin
)))
2068 if (XINT (XCAR (margin
)) > 0)
2069 img
->hmargin
= XFASTINT (XCAR (margin
));
2070 if (XINT (XCDR (margin
)) > 0)
2071 img
->vmargin
= XFASTINT (XCDR (margin
));
2074 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2075 if (INTEGERP (relief
))
2077 img
->relief
= XINT (relief
);
2078 img
->hmargin
+= eabs (img
->relief
);
2079 img
->vmargin
+= eabs (img
->relief
);
2082 if (! img
->background_valid
)
2084 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2088 = x_alloc_image_color (f
, img
, bg
,
2089 FRAME_BACKGROUND_PIXEL (f
));
2090 img
->background_valid
= 1;
2094 /* Do image transformations and compute masks, unless we
2095 don't have the image yet. */
2096 if (!EQ (*img
->type
->type
, Qpostscript
))
2097 postprocess_image (f
, img
);
2103 /* We're using IMG, so set its timestamp to `now'. */
2104 EMACS_GET_TIME (now
);
2105 img
->timestamp
= EMACS_SECS (now
);
2109 /* Value is the image id. */
2114 /* Cache image IMG in the image cache of frame F. */
2117 cache_image (f
, img
)
2121 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2124 /* Find a free slot in c->images. */
2125 for (i
= 0; i
< c
->used
; ++i
)
2126 if (c
->images
[i
] == NULL
)
2129 /* If no free slot found, maybe enlarge c->images. */
2130 if (i
== c
->used
&& c
->used
== c
->size
)
2133 c
->images
= (struct image
**) xrealloc (c
->images
,
2134 c
->size
* sizeof *c
->images
);
2137 /* Add IMG to c->images, and assign IMG an id. */
2143 /* Add IMG to the cache's hash table. */
2144 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2145 img
->next
= c
->buckets
[i
];
2147 img
->next
->prev
= img
;
2149 c
->buckets
[i
] = img
;
2153 /* Call FN on every image in the image cache of frame F. Used to mark
2154 Lisp Objects in the image cache. */
2156 /* Mark Lisp objects in image IMG. */
2162 mark_object (img
->spec
);
2163 mark_object (img
->dependencies
);
2165 if (!NILP (img
->data
.lisp_val
))
2166 mark_object (img
->data
.lisp_val
);
2171 mark_image_cache (struct image_cache
*c
)
2176 for (i
= 0; i
< c
->used
; ++i
)
2178 mark_image (c
->images
[i
]);
2184 /***********************************************************************
2185 X / MAC / W32 support code
2186 ***********************************************************************/
2190 /* Macro for defining functions that will be loaded from image DLLs. */
2191 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2193 /* Macro for loading those image functions from the library. */
2194 #define LOAD_IMGLIB_FN(lib,func) { \
2195 fn_##func = (void *) GetProcAddress (lib, #func); \
2196 if (!fn_##func) return 0; \
2199 /* Load a DLL implementing an image type.
2200 The `image-library-alist' variable associates a symbol,
2201 identifying an image type, to a list of possible filenames.
2202 The function returns NULL if no library could be loaded for
2203 the given image type, or if the library was previously loaded;
2204 else the handle of the DLL. */
2206 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2208 HMODULE library
= NULL
;
2210 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2212 Lisp_Object dlls
= Fassq (type
, libraries
);
2215 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2217 CHECK_STRING_CAR (dlls
);
2218 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2226 #endif /* HAVE_NTGUI */
2228 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2229 XImagePtr
*, Pixmap
*));
2230 static void x_destroy_x_image
P_ ((XImagePtr
));
2231 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2234 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2235 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2236 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2237 via xmalloc. Print error messages via image_error if an error
2238 occurs. Value is non-zero if successful.
2240 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2241 should indicate the bit depth of the image. */
2244 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2246 int width
, height
, depth
;
2250 #ifdef HAVE_X_WINDOWS
2251 Display
*display
= FRAME_X_DISPLAY (f
);
2252 Window window
= FRAME_X_WINDOW (f
);
2253 Screen
*screen
= FRAME_X_SCREEN (f
);
2255 xassert (interrupt_input_blocked
);
2258 depth
= DefaultDepthOfScreen (screen
);
2259 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2260 depth
, ZPixmap
, 0, NULL
, width
, height
,
2261 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2264 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2268 /* Allocate image raster. */
2269 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2271 /* Allocate a pixmap of the same size. */
2272 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2273 if (*pixmap
== NO_PIXMAP
)
2275 x_destroy_x_image (*ximg
);
2277 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2282 #endif /* HAVE_X_WINDOWS */
2286 BITMAPINFOHEADER
*header
;
2288 int scanline_width_bits
;
2290 int palette_colors
= 0;
2295 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2296 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2298 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2302 scanline_width_bits
= width
* depth
;
2303 remainder
= scanline_width_bits
% 32;
2306 scanline_width_bits
+= 32 - remainder
;
2308 /* Bitmaps with a depth less than 16 need a palette. */
2309 /* BITMAPINFO structure already contains the first RGBQUAD. */
2311 palette_colors
= 1 << depth
- 1;
2313 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2316 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2320 header
= &((*ximg
)->info
.bmiHeader
);
2321 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2322 header
->biSize
= sizeof (*header
);
2323 header
->biWidth
= width
;
2324 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2325 header
->biPlanes
= 1;
2326 header
->biBitCount
= depth
;
2327 header
->biCompression
= BI_RGB
;
2328 header
->biClrUsed
= palette_colors
;
2330 /* TODO: fill in palette. */
2333 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2334 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2335 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2336 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2337 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2338 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2339 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2340 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2343 hdc
= get_frame_dc (f
);
2345 /* Create a DIBSection and raster array for the bitmap,
2346 and store its handle in *pixmap. */
2347 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2348 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2349 /* casting avoids a GCC warning */
2350 (void **)&((*ximg
)->data
), NULL
, 0);
2352 /* Realize display palette and garbage all frames. */
2353 release_frame_dc (f
, hdc
);
2355 if (*pixmap
== NULL
)
2357 DWORD err
= GetLastError ();
2358 Lisp_Object errcode
;
2359 /* All system errors are < 10000, so the following is safe. */
2360 XSETINT (errcode
, (int) err
);
2361 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2362 x_destroy_x_image (*ximg
);
2368 #endif /* HAVE_NTGUI */
2371 Display
*display
= FRAME_X_DISPLAY (f
);
2372 Window window
= FRAME_X_WINDOW (f
);
2374 xassert (interrupt_input_blocked
);
2376 /* Allocate a pixmap of the same size. */
2377 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2378 if (*pixmap
== NO_PIXMAP
)
2381 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2385 #if !USE_MAC_IMAGE_IO
2386 LockPixels (GetGWorldPixMap (*pixmap
));
2395 /* Destroy XImage XIMG. Free XIMG->data. */
2398 x_destroy_x_image (ximg
)
2401 xassert (interrupt_input_blocked
);
2404 #ifdef HAVE_X_WINDOWS
2407 XDestroyImage (ximg
);
2408 #endif /* HAVE_X_WINDOWS */
2410 /* Data will be freed by DestroyObject. */
2413 #endif /* HAVE_NTGUI */
2415 XDestroyImage (ximg
);
2421 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2422 are width and height of both the image and pixmap. */
2425 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2431 #ifdef HAVE_X_WINDOWS
2434 xassert (interrupt_input_blocked
);
2435 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2436 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2437 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2438 #endif /* HAVE_X_WINDOWS */
2441 #if 0 /* I don't think this is necessary looking at where it is used. */
2442 HDC hdc
= get_frame_dc (f
);
2443 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2444 release_frame_dc (f
, hdc
);
2446 #endif /* HAVE_NTGUI */
2449 xassert (ximg
== pixmap
);
2454 /***********************************************************************
2456 ***********************************************************************/
2458 static unsigned char *slurp_file
P_ ((char *, int *));
2461 /* Find image file FILE. Look in data-directory/images, then
2462 x-bitmap-file-path. Value is the encoded full name of the file
2463 found, or nil if not found. */
2466 x_find_image_file (file
)
2469 Lisp_Object file_found
, search_path
;
2470 struct gcpro gcpro1
, gcpro2
;
2474 /* TODO I think this should use something like image-load-path
2475 instead. Unfortunately, that can contain non-string elements. */
2476 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2478 Vx_bitmap_file_path
);
2479 GCPRO2 (file_found
, search_path
);
2481 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2482 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2488 file_found
= ENCODE_FILE (file_found
);
2497 /* Read FILE into memory. Value is a pointer to a buffer allocated
2498 with xmalloc holding FILE's contents. Value is null if an error
2499 occurred. *SIZE is set to the size of the file. */
2501 static unsigned char *
2502 slurp_file (file
, size
)
2507 unsigned char *buf
= NULL
;
2510 if (stat (file
, &st
) == 0
2511 && (fp
= fopen (file
, "rb")) != NULL
2512 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2513 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2536 /***********************************************************************
2537 MAC Image Load Functions
2538 ***********************************************************************/
2540 #if USE_MAC_IMAGE_IO
2542 image_load_image_io (f
, img
, type
)
2547 CFDictionaryRef options
, src_props
= NULL
, props
= NULL
;
2548 CFStringRef keys
[2];
2549 CFTypeRef values
[2];
2550 Lisp_Object specified_file
, specified_data
;
2551 CGImageSourceRef source
= NULL
;
2553 CGImageRef image
= NULL
;
2554 int loop_count
= -1;
2555 double delay_time
= -1.0;
2557 XImagePtr ximg
= NULL
;
2558 CGContextRef context
;
2560 int has_alpha_p
, gif_p
;
2562 gif_p
= UTTypeEqual (type
, kUTTypeGIF
);
2564 keys
[0] = kCGImageSourceTypeIdentifierHint
;
2565 values
[0] = (CFTypeRef
) type
;
2566 keys
[1] = kCGImageSourceShouldCache
;
2567 values
[1] = (CFTypeRef
) kCFBooleanFalse
;
2568 options
= CFDictionaryCreate (NULL
, (const void **) keys
,
2569 (const void **) values
,
2570 sizeof (keys
) / sizeof (keys
[0]),
2571 &kCFTypeDictionaryKeyCallBacks
,
2572 &kCFTypeDictionaryValueCallBacks
);
2573 if (options
== NULL
)
2575 image_error ("Error creating options for image `%s'", img
->spec
, Qnil
);
2579 /* Open the file. */
2580 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2581 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2583 if (NILP (specified_data
))
2589 file
= x_find_image_file (specified_file
);
2590 if (!STRINGP (file
))
2592 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2595 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2598 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2599 kCFURLPOSIXPathStyle
, 0);
2603 source
= CGImageSourceCreateWithURL (url
, NULL
);
2610 CFDataRef data
= CFDataCreate (NULL
, SDATA (specified_data
),
2611 SBYTES (specified_data
));
2615 source
= CGImageSourceCreateWithData (data
, options
);
2619 CFRelease (options
);
2623 CFStringRef real_type
= CGImageSourceGetType (source
);
2625 if (real_type
&& UTTypeEqual (type
, real_type
))
2626 src_props
= CGImageSourceCopyProperties (source
, NULL
);
2631 count
= CGImageSourceGetCount (source
);
2634 Lisp_Object image
= image_spec_value (img
->spec
, QCindex
, NULL
);
2636 if (INTEGERP (image
))
2637 ino
= XFASTINT (image
);
2639 if (ino
>= 0 && ino
< count
)
2641 props
= CGImageSourceCopyPropertiesAtIndex (source
, ino
, NULL
);
2643 image
= CGImageSourceCreateImageAtIndex (source
, ino
, NULL
);
2652 CFRelease (src_props
);
2655 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2660 CFBooleanRef boolean
;
2662 if (CFDictionaryGetValueIfPresent (props
, kCGImagePropertyHasAlpha
,
2663 (const void **) &boolean
))
2664 has_alpha_p
= CFBooleanGetValue (boolean
);
2667 CFDictionaryRef dict
;
2670 dict
= CFDictionaryGetValue (src_props
,
2671 kCGImagePropertyGIFDictionary
);
2673 && CFDictionaryGetValueIfPresent (dict
,
2674 kCGImagePropertyGIFLoopCount
,
2675 (const void **) &number
))
2676 CFNumberGetValue (number
, kCFNumberIntType
, &loop_count
);
2678 dict
= CFDictionaryGetValue (props
, kCGImagePropertyGIFDictionary
);
2680 && CFDictionaryGetValueIfPresent (dict
,
2681 kCGImagePropertyGIFDelayTime
,
2682 (const void **) &number
))
2683 CFNumberGetValue (number
, kCFNumberDoubleType
, &delay_time
);
2685 CFRelease (src_props
);
2689 width
= img
->width
= CGImageGetWidth (image
);
2690 height
= img
->height
= CGImageGetHeight (image
);
2692 if (!check_image_size (f
, width
, height
))
2694 CGImageRelease (image
);
2695 image_error ("Invalid image size", Qnil
, Qnil
);
2699 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2701 CGImageRelease (image
);
2702 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
2705 rectangle
= CGRectMake (0, 0, width
, height
);
2707 context
= CGBitmapContextCreate (ximg
->data
, ximg
->width
, ximg
->height
, 8,
2708 ximg
->bytes_per_line
,
2709 mac_cg_color_space_rgb
,
2710 kCGImageAlphaNoneSkipFirst
2711 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
2712 | kCGBitmapByteOrder32Host
2717 Lisp_Object specified_bg
;
2720 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2721 if (!STRINGP (specified_bg
)
2722 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2724 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2725 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2726 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2727 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2729 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2730 color
.green
/ 65535.0,
2731 color
.blue
/ 65535.0, 1.0);
2732 CGContextFillRect (context
, rectangle
);
2734 CGContextDrawImage (context
, rectangle
, image
);
2735 CGContextRelease (context
);
2736 CGImageRelease (image
);
2738 /* Save GIF image extension data for `image-extension-data'.
2739 Format is (count IMAGES
2740 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2741 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2744 img
->data
.lisp_val
= Qnil
;
2745 if (delay_time
>= 0)
2747 Lisp_Object gce
= make_uninit_string (4);
2748 int centisec
= delay_time
* 100.0 + 0.5;
2750 /* Fill the delay time field. */
2751 SSET (gce
, 1, centisec
& 0xff);
2752 SSET (gce
, 2, (centisec
>> 8) & 0xff);
2753 /* We don't know about other fields. */
2756 img
->data
.lisp_val
= Fcons (make_number (0xf9),
2758 img
->data
.lisp_val
));
2760 if (loop_count
>= 0)
2762 Lisp_Object data_sub_block
= make_uninit_string (3);
2764 SSET (data_sub_block
, 0, 0x01);
2765 SSET (data_sub_block
, 1, loop_count
& 0xff);
2766 SSET (data_sub_block
, 2, (loop_count
>> 8) & 0xff);
2767 img
->data
.lisp_val
= Fcons (make_number (0),
2768 Fcons (data_sub_block
,
2769 img
->data
.lisp_val
));
2770 img
->data
.lisp_val
= Fcons (make_number (0xff),
2771 Fcons (build_string ("NETSCAPE2.0"),
2772 img
->data
.lisp_val
));
2775 img
->data
.lisp_val
= Fcons (Qcount
,
2776 Fcons (make_number (count
),
2777 img
->data
.lisp_val
));
2780 /* Maybe fill in the background field while we have ximg handy. */
2781 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2782 IMAGE_BACKGROUND (img
, f
, ximg
);
2784 /* Put the image into the pixmap. */
2785 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2786 x_destroy_x_image (ximg
);
2789 #else /* !USE_MAC_IMAGE_IO */
2790 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2793 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2797 find_image_fsspec (specified_file
, file
, fss
)
2798 Lisp_Object specified_file
, *file
;
2804 *file
= x_find_image_file (specified_file
);
2805 if (!STRINGP (*file
))
2806 return fnfErr
; /* file or directory not found;
2807 incomplete pathname */
2808 /* Try to open the image file. */
2809 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2810 SBYTES (*file
), typeFSS
, &desc
);
2813 #if TARGET_API_MAC_CARBON
2814 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2816 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2818 AEDisposeDesc (&desc
);
2824 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2831 ComponentResult err
;
2832 GraphicsImportComponent gi
;
2835 ImageDescriptionHandle desc_handle
;
2836 short draw_all_pixels
;
2837 Lisp_Object specified_bg
;
2842 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2845 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2850 /* read from file system spec */
2851 err
= GraphicsImportSetDataFile (gi
, fss
);
2854 image_error ("Cannot set fsspec to graphics importer for '%s'",
2861 /* read from data handle */
2862 err
= GraphicsImportSetDataHandle (gi
, dh
);
2865 image_error ("Cannot set data handle to graphics importer for `%s'",
2870 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2871 if (err
!= noErr
|| desc_handle
== NULL
)
2873 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2876 width
= img
->width
= (*desc_handle
)->width
;
2877 height
= img
->height
= (*desc_handle
)->height
;
2878 DisposeHandle ((Handle
)desc_handle
);
2880 if (!check_image_size (f
, width
, height
))
2882 image_error ("Invalid image size", Qnil
, Qnil
);
2886 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2888 /* Don't check the error code here. It may have an undocumented
2892 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2896 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2898 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2899 if (!STRINGP (specified_bg
) ||
2900 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2902 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2903 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2904 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2905 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2909 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2911 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2916 GetGWorld (&old_port
, &old_gdh
);
2917 SetGWorld (ximg
, NULL
);
2918 bg_color
.red
= color
.red
;
2919 bg_color
.green
= color
.green
;
2920 bg_color
.blue
= color
.blue
;
2921 RGBBackColor (&bg_color
);
2922 #if TARGET_API_MAC_CARBON
2923 GetPortBounds (ximg
, &rect
);
2926 EraseRect (&(ximg
->portRect
));
2928 SetGWorld (old_port
, old_gdh
);
2930 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2931 GraphicsImportDraw (gi
);
2932 CloseComponent (gi
);
2934 /* Maybe fill in the background field while we have ximg handy. */
2935 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2936 IMAGE_BACKGROUND (img
, f
, ximg
);
2938 /* Put the image into the pixmap. */
2939 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2940 x_destroy_x_image (ximg
);
2944 CloseComponent (gi
);
2949 /* Load an image using the QuickTime Graphics Importer.
2950 Note: The alpha channel does not work for PNG images. */
2952 image_load_quicktime (f
, img
, type
)
2957 Lisp_Object specified_file
;
2958 Lisp_Object specified_data
;
2961 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2962 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2964 if (NILP (specified_data
))
2966 /* Read from a file */
2970 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2974 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2976 image_error ("Cannot open `%s'", file
, Qnil
);
2979 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2983 /* Memory source! */
2987 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2990 image_error ("Cannot allocate data handle for `%s'",
2994 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
3003 image_load_quartz2d (f
, img
, png_p
)
3008 Lisp_Object file
, specified_file
;
3009 Lisp_Object specified_data
, specified_bg
;
3010 struct gcpro gcpro1
;
3011 CGDataProviderRef source
;
3015 XImagePtr ximg
= NULL
;
3016 CGContextRef context
;
3019 /* Open the file. */
3020 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3021 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3026 if (NILP (specified_data
))
3031 file
= x_find_image_file (specified_file
);
3032 if (!STRINGP (file
))
3034 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3038 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
3039 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
3040 kCFURLPOSIXPathStyle
, 0);
3042 source
= CGDataProviderCreateWithURL (url
);
3046 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
3047 SBYTES (specified_data
), NULL
);
3049 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3051 image
= CGImageCreateWithPNGDataProvider (source
, NULL
, false,
3052 kCGRenderingIntentDefault
);
3055 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, false,
3056 kCGRenderingIntentDefault
);
3058 CGDataProviderRelease (source
);
3062 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
3065 width
= img
->width
= CGImageGetWidth (image
);
3066 height
= img
->height
= CGImageGetHeight (image
);
3068 if (!check_image_size (f
, width
, height
))
3070 CGImageRelease (image
);
3072 image_error ("Invalid image size", Qnil
, Qnil
);
3078 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3079 if (!STRINGP (specified_bg
) ||
3080 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
3082 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
3083 color
.red
= RED16_FROM_ULONG (color
.pixel
);
3084 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
3085 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
3089 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
3091 CGImageRelease (image
);
3095 rectangle
= CGRectMake (0, 0, width
, height
);
3096 QDBeginCGContext (ximg
, &context
);
3099 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
3100 color
.green
/ 65535.0,
3101 color
.blue
/ 65535.0, 1.0);
3102 CGContextFillRect (context
, rectangle
);
3104 CGContextDrawImage (context
, rectangle
, image
);
3105 QDEndCGContext (ximg
, &context
);
3106 CGImageRelease (image
);
3108 /* Maybe fill in the background field while we have ximg handy. */
3109 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
3110 IMAGE_BACKGROUND (img
, f
, ximg
);
3112 /* Put the image into the pixmap. */
3113 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
3114 x_destroy_x_image (ximg
);
3119 #endif /* !USE_MAC_IMAGE_IO */
3124 /***********************************************************************
3126 ***********************************************************************/
3128 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
3129 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
3130 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
3131 unsigned char *, unsigned char *));
3132 static int xbm_image_p
P_ ((Lisp_Object object
));
3133 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
3134 unsigned char *, unsigned char *,
3135 int *, int *, unsigned char **));
3136 static int xbm_file_p
P_ ((Lisp_Object
));
3139 /* Indices of image specification fields in xbm_format, below. */
3141 enum xbm_keyword_index
3159 /* Vector of image_keyword structures describing the format
3160 of valid XBM image specifications. */
3162 static struct image_keyword xbm_format
[XBM_LAST
] =
3164 {":type", IMAGE_SYMBOL_VALUE
, 1},
3165 {":file", IMAGE_STRING_VALUE
, 0},
3166 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3167 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
3168 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3169 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
3170 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
3171 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3172 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3173 {":relief", IMAGE_INTEGER_VALUE
, 0},
3174 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3175 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3176 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
3179 /* Structure describing the image type XBM. */
3181 static struct image_type xbm_type
=
3190 /* Tokens returned from xbm_scan. */
3199 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3200 A valid specification is a list starting with the symbol `image'
3201 The rest of the list is a property list which must contain an
3204 If the specification specifies a file to load, it must contain
3205 an entry `:file FILENAME' where FILENAME is a string.
3207 If the specification is for a bitmap loaded from memory it must
3208 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3209 WIDTH and HEIGHT are integers > 0. DATA may be:
3211 1. a string large enough to hold the bitmap data, i.e. it must
3212 have a size >= (WIDTH + 7) / 8 * HEIGHT
3214 2. a bool-vector of size >= WIDTH * HEIGHT
3216 3. a vector of strings or bool-vectors, one for each line of the
3219 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3220 may not be specified in this case because they are defined in the
3223 Both the file and data forms may contain the additional entries
3224 `:background COLOR' and `:foreground COLOR'. If not present,
3225 foreground and background of the frame on which the image is
3226 displayed is used. */
3229 xbm_image_p (object
)
3232 struct image_keyword kw
[XBM_LAST
];
3234 bcopy (xbm_format
, kw
, sizeof kw
);
3235 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
3238 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
3240 if (kw
[XBM_FILE
].count
)
3242 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
3245 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
3247 /* In-memory XBM file. */
3248 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
3256 /* Entries for `:width', `:height' and `:data' must be present. */
3257 if (!kw
[XBM_WIDTH
].count
3258 || !kw
[XBM_HEIGHT
].count
3259 || !kw
[XBM_DATA
].count
)
3262 data
= kw
[XBM_DATA
].value
;
3263 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
3264 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
3266 /* Check type of data, and width and height against contents of
3272 /* Number of elements of the vector must be >= height. */
3273 if (XVECTOR (data
)->size
< height
)
3276 /* Each string or bool-vector in data must be large enough
3277 for one line of the image. */
3278 for (i
= 0; i
< height
; ++i
)
3280 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
3285 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
3288 else if (BOOL_VECTOR_P (elt
))
3290 if (XBOOL_VECTOR (elt
)->size
< width
)
3297 else if (STRINGP (data
))
3300 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
3303 else if (BOOL_VECTOR_P (data
))
3305 if (XBOOL_VECTOR (data
)->size
< width
* height
)
3316 /* Scan a bitmap file. FP is the stream to read from. Value is
3317 either an enumerator from enum xbm_token, or a character for a
3318 single-character token, or 0 at end of file. If scanning an
3319 identifier, store the lexeme of the identifier in SVAL. If
3320 scanning a number, store its value in *IVAL. */
3323 xbm_scan (s
, end
, sval
, ival
)
3324 unsigned char **s
, *end
;
3332 /* Skip white space. */
3333 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3338 else if (isdigit (c
))
3340 int value
= 0, digit
;
3342 if (c
== '0' && *s
< end
)
3345 if (c
== 'x' || c
== 'X')
3352 else if (c
>= 'a' && c
<= 'f')
3353 digit
= c
- 'a' + 10;
3354 else if (c
>= 'A' && c
<= 'F')
3355 digit
= c
- 'A' + 10;
3358 value
= 16 * value
+ digit
;
3361 else if (isdigit (c
))
3365 && (c
= *(*s
)++, isdigit (c
)))
3366 value
= 8 * value
+ c
- '0';
3373 && (c
= *(*s
)++, isdigit (c
)))
3374 value
= 10 * value
+ c
- '0';
3382 else if (isalpha (c
) || c
== '_')
3386 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3393 else if (c
== '/' && **s
== '*')
3395 /* C-style comment. */
3397 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3411 /* Create a Windows bitmap from X bitmap data. */
3413 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3415 static unsigned char swap_nibble
[16]
3416 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3417 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3418 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3419 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3421 unsigned char *bits
, *p
;
3424 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3425 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3426 bits
= (unsigned char *) alloca (height
* w2
);
3427 bzero (bits
, height
* w2
);
3428 for (i
= 0; i
< height
; i
++)
3431 for (j
= 0; j
< w1
; j
++)
3433 /* Bitswap XBM bytes to match how Windows does things. */
3434 unsigned char c
= *data
++;
3435 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3436 | (swap_nibble
[(c
>>4) & 0xf]));
3439 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3445 convert_mono_to_color_image (f
, img
, foreground
, background
)
3448 COLORREF foreground
, background
;
3450 HDC hdc
, old_img_dc
, new_img_dc
;
3451 HGDIOBJ old_prev
, new_prev
;
3454 hdc
= get_frame_dc (f
);
3455 old_img_dc
= CreateCompatibleDC (hdc
);
3456 new_img_dc
= CreateCompatibleDC (hdc
);
3457 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3458 release_frame_dc (f
, hdc
);
3459 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3460 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3461 /* Windows convention for mono bitmaps is black = background,
3462 white = foreground. */
3463 SetTextColor (new_img_dc
, background
);
3464 SetBkColor (new_img_dc
, foreground
);
3466 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3469 SelectObject (old_img_dc
, old_prev
);
3470 SelectObject (new_img_dc
, new_prev
);
3471 DeleteDC (old_img_dc
);
3472 DeleteDC (new_img_dc
);
3473 DeleteObject (img
->pixmap
);
3474 if (new_pixmap
== 0)
3475 fprintf (stderr
, "Failed to convert image to color.\n");
3477 img
->pixmap
= new_pixmap
;
3480 #define XBM_BIT_SHUFFLE(b) (~(b))
3484 #define XBM_BIT_SHUFFLE(b) (b)
3486 #endif /* HAVE_NTGUI */
3490 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
3494 RGB_PIXEL_COLOR fg
, bg
;
3495 int non_default_colors
;
3499 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3501 /* If colors were specified, transfer the bitmap to a color one. */
3502 if (non_default_colors
)
3503 convert_mono_to_color_image (f
, img
, fg
, bg
);
3506 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3509 img
->width
, img
->height
,
3511 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3512 #endif /* HAVE_NTGUI */
3517 /* Replacement for XReadBitmapFileData which isn't available under old
3518 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3519 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3520 the image. Return in *DATA the bitmap data allocated with xmalloc.
3521 Value is non-zero if successful. DATA null means just test if
3522 CONTENTS looks like an in-memory XBM file. */
3525 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3527 unsigned char *contents
, *end
;
3528 int *width
, *height
;
3529 unsigned char **data
;
3531 unsigned char *s
= contents
;
3532 char buffer
[BUFSIZ
];
3535 int bytes_per_line
, i
, nbytes
;
3541 LA1 = xbm_scan (&s, end, buffer, &value)
3543 #define expect(TOKEN) \
3544 if (LA1 != (TOKEN)) \
3549 #define expect_ident(IDENT) \
3550 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3555 *width
= *height
= -1;
3558 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3560 /* Parse defines for width, height and hot-spots. */
3564 expect_ident ("define");
3565 expect (XBM_TK_IDENT
);
3567 if (LA1
== XBM_TK_NUMBER
)
3569 char *p
= strrchr (buffer
, '_');
3570 p
= p
? p
+ 1 : buffer
;
3571 if (strcmp (p
, "width") == 0)
3573 else if (strcmp (p
, "height") == 0)
3576 expect (XBM_TK_NUMBER
);
3579 if (!check_image_size (f
, *width
, *height
))
3581 else if (data
== NULL
)
3584 /* Parse bits. Must start with `static'. */
3585 expect_ident ("static");
3586 if (LA1
== XBM_TK_IDENT
)
3588 if (strcmp (buffer
, "unsigned") == 0)
3591 expect_ident ("char");
3593 else if (strcmp (buffer
, "short") == 0)
3597 if (*width
% 16 && *width
% 16 < 9)
3600 else if (strcmp (buffer
, "char") == 0)
3608 expect (XBM_TK_IDENT
);
3614 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3615 nbytes
= bytes_per_line
* *height
;
3616 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3620 for (i
= 0; i
< nbytes
; i
+= 2)
3623 expect (XBM_TK_NUMBER
);
3625 *p
++ = XBM_BIT_SHUFFLE (val
);
3626 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3627 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3629 if (LA1
== ',' || LA1
== '}')
3637 for (i
= 0; i
< nbytes
; ++i
)
3640 expect (XBM_TK_NUMBER
);
3642 *p
++ = XBM_BIT_SHUFFLE (val
);
3644 if (LA1
== ',' || LA1
== '}')
3669 /* Load XBM image IMG which will be displayed on frame F from buffer
3670 CONTENTS. END is the end of the buffer. Value is non-zero if
3674 xbm_load_image (f
, img
, contents
, end
)
3677 unsigned char *contents
, *end
;
3680 unsigned char *data
;
3683 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3686 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3687 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3688 int non_default_colors
= 0;
3691 xassert (img
->width
> 0 && img
->height
> 0);
3693 /* Get foreground and background colors, maybe allocate colors. */
3694 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3697 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3698 non_default_colors
= 1;
3700 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3703 background
= x_alloc_image_color (f
, img
, value
, background
);
3704 img
->background
= background
;
3705 img
->background_valid
= 1;
3706 non_default_colors
= 1;
3709 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3710 foreground
, background
,
3711 non_default_colors
);
3714 if (img
->pixmap
== NO_PIXMAP
)
3716 x_clear_image (f
, img
);
3717 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3723 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3729 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3736 return (STRINGP (data
)
3737 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3744 /* Fill image IMG which is used on frame F with pixmap data. Value is
3745 non-zero if successful. */
3753 Lisp_Object file_name
;
3755 xassert (xbm_image_p (img
->spec
));
3757 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3758 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3759 if (STRINGP (file_name
))
3762 unsigned char *contents
;
3764 struct gcpro gcpro1
;
3766 file
= x_find_image_file (file_name
);
3768 if (!STRINGP (file
))
3770 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3775 contents
= slurp_file (SDATA (file
), &size
);
3776 if (contents
== NULL
)
3778 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3783 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3788 struct image_keyword fmt
[XBM_LAST
];
3790 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3791 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3792 int non_default_colors
= 0;
3795 int in_memory_file_p
= 0;
3797 /* See if data looks like an in-memory XBM file. */
3798 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3799 in_memory_file_p
= xbm_file_p (data
);
3801 /* Parse the image specification. */
3802 bcopy (xbm_format
, fmt
, sizeof fmt
);
3803 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3806 /* Get specified width, and height. */
3807 if (!in_memory_file_p
)
3809 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3810 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3811 xassert (img
->width
> 0 && img
->height
> 0);
3814 /* Get foreground and background colors, maybe allocate colors. */
3815 if (fmt
[XBM_FOREGROUND
].count
3816 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3818 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3820 non_default_colors
= 1;
3823 if (fmt
[XBM_BACKGROUND
].count
3824 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3826 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3828 non_default_colors
= 1;
3831 if (in_memory_file_p
)
3832 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3841 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3843 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3844 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3846 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3848 bcopy (SDATA (line
), p
, nbytes
);
3850 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3853 else if (STRINGP (data
))
3854 bits
= SDATA (data
);
3856 bits
= XBOOL_VECTOR (data
)->data
;
3862 /* Windows mono bitmaps are reversed compared with X. */
3863 invertedBits
= bits
;
3864 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3866 bits
= (char *) alloca(nbytes
);
3867 for (i
= 0; i
< nbytes
; i
++)
3868 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3871 /* Create the pixmap. */
3873 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3874 foreground
, background
,
3875 non_default_colors
);
3880 image_error ("Unable to create pixmap for XBM image `%s'",
3882 x_clear_image (f
, img
);
3892 /***********************************************************************
3894 ***********************************************************************/
3896 #if defined (HAVE_XPM) || defined (MAC_OS)
3898 static int xpm_image_p
P_ ((Lisp_Object object
));
3899 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3900 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3902 #endif /* HAVE_XPM || MAC_OS */
3906 /* Indicate to xpm.h that we don't have Xlib. */
3908 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3909 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3910 #define XColor xpm_XColor
3911 #define XImage xpm_XImage
3912 #define Display xpm_Display
3913 #define PIXEL_ALREADY_TYPEDEFED
3914 #include "X11/xpm.h"
3919 #undef PIXEL_ALREADY_TYPEDEFED
3921 #include "X11/xpm.h"
3922 #endif /* HAVE_NTGUI */
3923 #endif /* HAVE_XPM */
3925 #if defined (HAVE_XPM) || defined (MAC_OS)
3926 /* The symbol `xpm' identifying XPM-format images. */
3930 /* Indices of image specification fields in xpm_format, below. */
3932 enum xpm_keyword_index
3948 /* Vector of image_keyword structures describing the format
3949 of valid XPM image specifications. */
3951 static struct image_keyword xpm_format
[XPM_LAST
] =
3953 {":type", IMAGE_SYMBOL_VALUE
, 1},
3954 {":file", IMAGE_STRING_VALUE
, 0},
3955 {":data", IMAGE_STRING_VALUE
, 0},
3956 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3957 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3958 {":relief", IMAGE_INTEGER_VALUE
, 0},
3959 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3960 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3961 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3962 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3963 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3966 /* Structure describing the image type XPM. */
3968 static struct image_type xpm_type
=
3977 #ifdef HAVE_X_WINDOWS
3979 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3980 functions for allocating image colors. Our own functions handle
3981 color allocation failures more gracefully than the ones on the XPM
3984 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3985 #define ALLOC_XPM_COLORS
3987 #endif /* HAVE_X_WINDOWS */
3989 #ifdef ALLOC_XPM_COLORS
3991 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3992 static void xpm_free_color_cache
P_ ((void));
3993 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3994 static int xpm_color_bucket
P_ ((char *));
3995 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3998 /* An entry in a hash table used to cache color definitions of named
3999 colors. This cache is necessary to speed up XPM image loading in
4000 case we do color allocations ourselves. Without it, we would need
4001 a call to XParseColor per pixel in the image. */
4003 struct xpm_cached_color
4005 /* Next in collision chain. */
4006 struct xpm_cached_color
*next
;
4008 /* Color definition (RGB and pixel color). */
4015 /* The hash table used for the color cache, and its bucket vector
4018 #define XPM_COLOR_CACHE_BUCKETS 1001
4019 struct xpm_cached_color
**xpm_color_cache
;
4021 /* Initialize the color cache. */
4024 xpm_init_color_cache (f
, attrs
)
4026 XpmAttributes
*attrs
;
4028 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
4029 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
4030 memset (xpm_color_cache
, 0, nbytes
);
4031 init_color_table ();
4033 if (attrs
->valuemask
& XpmColorSymbols
)
4038 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
4039 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4040 attrs
->colorsymbols
[i
].value
, &color
))
4042 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
4044 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
4049 /* Free the color cache. */
4052 xpm_free_color_cache ()
4054 struct xpm_cached_color
*p
, *next
;
4057 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
4058 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
4064 xfree (xpm_color_cache
);
4065 xpm_color_cache
= NULL
;
4066 free_color_table ();
4069 /* Return the bucket index for color named COLOR_NAME in the color
4073 xpm_color_bucket (color_name
)
4079 for (s
= color_name
; *s
; ++s
)
4081 return h
%= XPM_COLOR_CACHE_BUCKETS
;
4085 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4086 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4089 static struct xpm_cached_color
*
4090 xpm_cache_color (f
, color_name
, color
, bucket
)
4097 struct xpm_cached_color
*p
;
4100 bucket
= xpm_color_bucket (color_name
);
4102 nbytes
= sizeof *p
+ strlen (color_name
);
4103 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
4104 strcpy (p
->name
, color_name
);
4106 p
->next
= xpm_color_cache
[bucket
];
4107 xpm_color_cache
[bucket
] = p
;
4111 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4112 return the cached definition in *COLOR. Otherwise, make a new
4113 entry in the cache and allocate the color. Value is zero if color
4114 allocation failed. */
4117 xpm_lookup_color (f
, color_name
, color
)
4122 struct xpm_cached_color
*p
;
4123 int h
= xpm_color_bucket (color_name
);
4125 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
4126 if (strcmp (p
->name
, color_name
) == 0)
4131 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
4134 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
4136 p
= xpm_cache_color (f
, color_name
, color
, h
);
4138 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4139 with transparency, and it's useful. */
4140 else if (strcmp ("opaque", color_name
) == 0)
4142 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
4143 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
4144 p
= xpm_cache_color (f
, color_name
, color
, h
);
4151 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4152 CLOSURE is a pointer to the frame on which we allocate the
4153 color. Return in *COLOR the allocated color. Value is non-zero
4157 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
4164 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
4168 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4169 is a pointer to the frame on which we allocate the color. Value is
4170 non-zero if successful. */
4173 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
4183 #endif /* ALLOC_XPM_COLORS */
4188 /* XPM library details. */
4190 DEF_IMGLIB_FN (XpmFreeAttributes
);
4191 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
4192 DEF_IMGLIB_FN (XpmReadFileToImage
);
4193 DEF_IMGLIB_FN (XImageFree
);
4196 init_xpm_functions (Lisp_Object libraries
)
4200 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
4203 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
4204 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
4205 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
4206 LOAD_IMGLIB_FN (library
, XImageFree
);
4210 #endif /* HAVE_NTGUI */
4213 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4214 for XPM images. Such a list must consist of conses whose car and
4218 xpm_valid_color_symbols_p (color_symbols
)
4219 Lisp_Object color_symbols
;
4221 while (CONSP (color_symbols
))
4223 Lisp_Object sym
= XCAR (color_symbols
);
4225 || !STRINGP (XCAR (sym
))
4226 || !STRINGP (XCDR (sym
)))
4228 color_symbols
= XCDR (color_symbols
);
4231 return NILP (color_symbols
);
4235 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4238 xpm_image_p (object
)
4241 struct image_keyword fmt
[XPM_LAST
];
4242 bcopy (xpm_format
, fmt
, sizeof fmt
);
4243 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
4244 /* Either `:file' or `:data' must be present. */
4245 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
4246 /* Either no `:color-symbols' or it's a list of conses
4247 whose car and cdr are strings. */
4248 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
4249 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
4252 #endif /* HAVE_XPM || MAC_OS */
4254 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4256 x_create_bitmap_from_xpm_data (f
, bits
)
4260 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4262 XpmAttributes attrs
;
4263 Pixmap bitmap
, mask
;
4265 bzero (&attrs
, sizeof attrs
);
4267 attrs
.visual
= FRAME_X_VISUAL (f
);
4268 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4269 attrs
.valuemask
|= XpmVisual
;
4270 attrs
.valuemask
|= XpmColormap
;
4272 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4273 bits
, &bitmap
, &mask
, &attrs
);
4274 if (rc
!= XpmSuccess
)
4276 XpmFreeAttributes (&attrs
);
4280 id
= x_allocate_bitmap_record (f
);
4281 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
4282 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
4283 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
4284 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
4285 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
4286 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
4287 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
4288 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
4290 XpmFreeAttributes (&attrs
);
4293 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4295 /* Load image IMG which will be displayed on frame F. Value is
4296 non-zero if successful. */
4306 XpmAttributes attrs
;
4307 Lisp_Object specified_file
, color_symbols
;
4310 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
4311 #endif /* HAVE_NTGUI */
4313 /* Configure the XPM lib. Use the visual of frame F. Allocate
4314 close colors. Return colors allocated. */
4315 bzero (&attrs
, sizeof attrs
);
4318 attrs
.visual
= FRAME_X_VISUAL (f
);
4319 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4320 attrs
.valuemask
|= XpmVisual
;
4321 attrs
.valuemask
|= XpmColormap
;
4322 #endif /* HAVE_NTGUI */
4324 #ifdef ALLOC_XPM_COLORS
4325 /* Allocate colors with our own functions which handle
4326 failing color allocation more gracefully. */
4327 attrs
.color_closure
= f
;
4328 attrs
.alloc_color
= xpm_alloc_color
;
4329 attrs
.free_colors
= xpm_free_colors
;
4330 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
4331 #else /* not ALLOC_XPM_COLORS */
4332 /* Let the XPM lib allocate colors. */
4333 attrs
.valuemask
|= XpmReturnAllocPixels
;
4334 #ifdef XpmAllocCloseColors
4335 attrs
.alloc_close_colors
= 1;
4336 attrs
.valuemask
|= XpmAllocCloseColors
;
4337 #else /* not XpmAllocCloseColors */
4338 attrs
.closeness
= 600;
4339 attrs
.valuemask
|= XpmCloseness
;
4340 #endif /* not XpmAllocCloseColors */
4341 #endif /* ALLOC_XPM_COLORS */
4343 /* If image specification contains symbolic color definitions, add
4344 these to `attrs'. */
4345 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4346 if (CONSP (color_symbols
))
4349 XpmColorSymbol
*xpm_syms
;
4352 attrs
.valuemask
|= XpmColorSymbols
;
4354 /* Count number of symbols. */
4355 attrs
.numsymbols
= 0;
4356 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4359 /* Allocate an XpmColorSymbol array. */
4360 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4361 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4362 bzero (xpm_syms
, size
);
4363 attrs
.colorsymbols
= xpm_syms
;
4365 /* Fill the color symbol array. */
4366 for (tail
= color_symbols
, i
= 0;
4368 ++i
, tail
= XCDR (tail
))
4370 Lisp_Object name
= XCAR (XCAR (tail
));
4371 Lisp_Object color
= XCDR (XCAR (tail
));
4372 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4373 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4374 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4375 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4379 /* Create a pixmap for the image, either from a file, or from a
4380 string buffer containing data in the same format as an XPM file. */
4381 #ifdef ALLOC_XPM_COLORS
4382 xpm_init_color_cache (f
, &attrs
);
4385 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4389 HDC frame_dc
= get_frame_dc (f
);
4390 hdc
= CreateCompatibleDC (frame_dc
);
4391 release_frame_dc (f
, frame_dc
);
4393 #endif /* HAVE_NTGUI */
4395 if (STRINGP (specified_file
))
4397 Lisp_Object file
= x_find_image_file (specified_file
);
4398 if (!STRINGP (file
))
4400 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4405 /* XpmReadFileToPixmap is not available in the Windows port of
4406 libxpm. But XpmReadFileToImage almost does what we want. */
4407 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4408 &xpm_image
, &xpm_mask
,
4411 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4412 SDATA (file
), &img
->pixmap
, &img
->mask
,
4414 #endif /* HAVE_NTGUI */
4418 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4420 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4421 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4422 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4423 &xpm_image
, &xpm_mask
,
4426 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4428 &img
->pixmap
, &img
->mask
,
4430 #endif /* HAVE_NTGUI */
4433 if (rc
== XpmSuccess
)
4435 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4436 img
->colors
= colors_in_color_table (&img
->ncolors
);
4437 #else /* not ALLOC_XPM_COLORS */
4441 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4442 plus some duplicate attributes. */
4443 if (xpm_image
&& xpm_image
->bitmap
)
4445 img
->pixmap
= xpm_image
->bitmap
;
4446 /* XImageFree in libXpm frees XImage struct without destroying
4447 the bitmap, which is what we want. */
4448 fn_XImageFree (xpm_image
);
4450 if (xpm_mask
&& xpm_mask
->bitmap
)
4452 /* The mask appears to be inverted compared with what we expect.
4453 TODO: invert our expectations. See other places where we
4454 have to invert bits because our idea of masks is backwards. */
4456 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4458 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4459 SelectObject (hdc
, old_obj
);
4461 img
->mask
= xpm_mask
->bitmap
;
4462 fn_XImageFree (xpm_mask
);
4467 #endif /* HAVE_NTGUI */
4469 /* Remember allocated colors. */
4470 img
->ncolors
= attrs
.nalloc_pixels
;
4471 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4472 * sizeof *img
->colors
);
4473 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4475 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4476 #ifdef DEBUG_X_COLORS
4477 register_color (img
->colors
[i
]);
4480 #endif /* not ALLOC_XPM_COLORS */
4482 img
->width
= attrs
.width
;
4483 img
->height
= attrs
.height
;
4484 xassert (img
->width
> 0 && img
->height
> 0);
4486 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4488 fn_XpmFreeAttributes (&attrs
);
4490 XpmFreeAttributes (&attrs
);
4491 #endif /* HAVE_NTGUI */
4497 #endif /* HAVE_NTGUI */
4502 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4505 case XpmFileInvalid
:
4506 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4510 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4513 case XpmColorFailed
:
4514 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4518 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4523 #ifdef ALLOC_XPM_COLORS
4524 xpm_free_color_cache ();
4526 return rc
== XpmSuccess
;
4529 #endif /* HAVE_XPM */
4533 /* XPM support functions for Mac OS where libxpm is not available.
4534 Only XPM version 3 (without any extensions) is supported. */
4536 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4537 const unsigned char **, int *));
4538 static Lisp_Object xpm_make_color_table_v
4539 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4540 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4541 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4543 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4544 const unsigned char *, int));
4545 static Lisp_Object xpm_make_color_table_h
4546 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4547 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4548 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4550 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4551 const unsigned char *, int));
4552 static int xpm_str_to_color_key
P_ ((const char *));
4553 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4554 const unsigned char *, const unsigned char *));
4556 /* Tokens returned from xpm_scan. */
4565 /* Scan an XPM data and return a character (< 256) or a token defined
4566 by enum xpm_token above. *S and END are the start (inclusive) and
4567 the end (exclusive) addresses of the data, respectively. Advance
4568 *S while scanning. If token is either XPM_TK_IDENT or
4569 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4570 length of the corresponding token, respectively. */
4573 xpm_scan (s
, end
, beg
, len
)
4574 const unsigned char **s
, *end
, **beg
;
4581 /* Skip white-space. */
4582 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4585 /* gnus-pointer.xpm uses '-' in its identifier.
4586 sb-dir-plus.xpm uses '+' in its identifier. */
4587 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4591 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4594 return XPM_TK_IDENT
;
4599 while (*s
< end
&& **s
!= '"')
4604 return XPM_TK_STRING
;
4608 if (*s
< end
&& **s
== '*')
4610 /* C-style comment. */
4614 while (*s
< end
&& *(*s
)++ != '*')
4617 while (*s
< end
&& **s
!= '/');
4631 /* Functions for color table lookup in XPM data. A key is a string
4632 specifying the color of each pixel in XPM data. A value is either
4633 an integer that specifies a pixel color, Qt that specifies
4634 transparency, or Qnil for the unspecified color. If the length of
4635 the key string is one, a vector is used as a table. Otherwise, a
4636 hash table is used. */
4639 xpm_make_color_table_v (put_func
, get_func
)
4640 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4641 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4643 *put_func
= xpm_put_color_table_v
;
4644 *get_func
= xpm_get_color_table_v
;
4645 return Fmake_vector (make_number (256), Qnil
);
4649 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4650 Lisp_Object color_table
;
4651 const unsigned char *chars_start
;
4655 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4659 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4660 Lisp_Object color_table
;
4661 const unsigned char *chars_start
;
4664 return XVECTOR (color_table
)->contents
[*chars_start
];
4668 xpm_make_color_table_h (put_func
, get_func
)
4669 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4670 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4672 *put_func
= xpm_put_color_table_h
;
4673 *get_func
= xpm_get_color_table_h
;
4674 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4675 make_float (DEFAULT_REHASH_SIZE
),
4676 make_float (DEFAULT_REHASH_THRESHOLD
),
4681 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4682 Lisp_Object color_table
;
4683 const unsigned char *chars_start
;
4687 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4689 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4691 hash_lookup (table
, chars
, &hash_code
);
4692 hash_put (table
, chars
, color
, hash_code
);
4696 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4697 Lisp_Object color_table
;
4698 const unsigned char *chars_start
;
4701 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4702 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4705 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4708 enum xpm_color_key
{
4716 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4719 xpm_str_to_color_key (s
)
4725 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4727 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4733 xpm_load_image (f
, img
, contents
, end
)
4736 const unsigned char *contents
, *end
;
4738 const unsigned char *s
= contents
, *beg
, *str
;
4739 unsigned char buffer
[BUFSIZ
];
4740 int width
, height
, x
, y
;
4741 int num_colors
, chars_per_pixel
;
4743 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4744 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4745 Lisp_Object frame
, color_symbols
, color_table
;
4746 int best_key
, have_mask
= 0;
4747 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4750 LA1 = xpm_scan (&s, end, &beg, &len)
4752 #define expect(TOKEN) \
4753 if (LA1 != (TOKEN)) \
4758 #define expect_ident(IDENT) \
4759 if (LA1 == XPM_TK_IDENT \
4760 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4765 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4769 expect_ident ("static");
4770 expect_ident ("char");
4772 expect (XPM_TK_IDENT
);
4777 expect (XPM_TK_STRING
);
4780 memcpy (buffer
, beg
, len
);
4782 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4783 &num_colors
, &chars_per_pixel
) != 4
4784 || width
<= 0 || height
<= 0
4785 || num_colors
<= 0 || chars_per_pixel
<= 0)
4788 if (!check_image_size (f
, width
, height
))
4790 image_error ("Invalid image size", Qnil
, Qnil
);
4796 XSETFRAME (frame
, f
);
4797 if (!NILP (Fxw_display_color_p (frame
)))
4798 best_key
= XPM_COLOR_KEY_C
;
4799 else if (!NILP (Fx_display_grayscale_p (frame
)))
4800 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4801 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4803 best_key
= XPM_COLOR_KEY_M
;
4805 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4806 if (chars_per_pixel
== 1)
4807 color_table
= xpm_make_color_table_v (&put_color_table
,
4810 color_table
= xpm_make_color_table_h (&put_color_table
,
4813 while (num_colors
-- > 0)
4815 unsigned char *color
, *max_color
;
4816 int key
, next_key
, max_key
= 0;
4817 Lisp_Object symbol_color
= Qnil
, color_val
;
4820 expect (XPM_TK_STRING
);
4821 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4823 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4824 buffer
[len
- chars_per_pixel
] = '\0';
4826 str
= strtok (buffer
, " \t");
4829 key
= xpm_str_to_color_key (str
);
4834 color
= strtok (NULL
, " \t");
4838 while ((str
= strtok (NULL
, " \t")) != NULL
)
4840 next_key
= xpm_str_to_color_key (str
);
4843 color
[strlen (color
)] = ' ';
4846 if (key
== XPM_COLOR_KEY_S
)
4848 if (NILP (symbol_color
))
4849 symbol_color
= build_string (color
);
4851 else if (max_key
< key
&& key
<= best_key
)
4861 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4863 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4865 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4867 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4869 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4871 color_val
= make_number (cdef
.pixel
);
4874 if (NILP (color_val
) && max_key
> 0)
4876 if (xstricmp (max_color
, "None") == 0)
4878 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4879 color_val
= make_number (cdef
.pixel
);
4881 if (!NILP (color_val
))
4882 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4887 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4888 &ximg
, &img
->pixmap
)
4889 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4890 &mask_img
, &img
->mask
))
4892 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4896 for (y
= 0; y
< height
; y
++)
4898 expect (XPM_TK_STRING
);
4900 if (len
< width
* chars_per_pixel
)
4902 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4904 Lisp_Object color_val
=
4905 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4907 XPutPixel (ximg
, x
, y
,
4908 (INTEGERP (color_val
) ? XINT (color_val
)
4909 : FRAME_FOREGROUND_PIXEL (f
)));
4910 XPutPixel (mask_img
, x
, y
,
4911 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4912 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4919 img
->height
= height
;
4921 /* Maybe fill in the background field while we have ximg handy. */
4922 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4923 IMAGE_BACKGROUND (img
, f
, ximg
);
4925 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4926 x_destroy_x_image (ximg
);
4929 /* Fill in the background_transparent field while we have the
4931 image_background_transparent (img
, f
, mask_img
);
4933 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4934 x_destroy_x_image (mask_img
);
4938 x_destroy_x_image (mask_img
);
4939 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4940 img
->mask
= NO_PIXMAP
;
4946 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4948 x_destroy_x_image (ximg
);
4949 x_destroy_x_image (mask_img
);
4950 x_clear_image (f
, img
);
4964 Lisp_Object file_name
;
4966 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4967 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4968 if (STRINGP (file_name
))
4971 unsigned char *contents
;
4973 struct gcpro gcpro1
;
4975 file
= x_find_image_file (file_name
);
4977 if (!STRINGP (file
))
4979 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4984 contents
= slurp_file (SDATA (file
), &size
);
4985 if (contents
== NULL
)
4987 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4992 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
5000 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5001 success_p
= xpm_load_image (f
, img
, SDATA (data
),
5002 SDATA (data
) + SBYTES (data
));
5012 /***********************************************************************
5014 ***********************************************************************/
5016 #ifdef COLOR_TABLE_SUPPORT
5018 /* An entry in the color table mapping an RGB color to a pixel color. */
5023 unsigned long pixel
;
5025 /* Next in color table collision list. */
5026 struct ct_color
*next
;
5029 /* The bucket vector size to use. Must be prime. */
5033 /* Value is a hash of the RGB color given by R, G, and B. */
5035 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5037 /* The color hash table. */
5039 struct ct_color
**ct_table
;
5041 /* Number of entries in the color table. */
5043 int ct_colors_allocated
;
5045 /* Initialize the color table. */
5050 int size
= CT_SIZE
* sizeof (*ct_table
);
5051 ct_table
= (struct ct_color
**) xmalloc (size
);
5052 bzero (ct_table
, size
);
5053 ct_colors_allocated
= 0;
5057 /* Free memory associated with the color table. */
5063 struct ct_color
*p
, *next
;
5065 for (i
= 0; i
< CT_SIZE
; ++i
)
5066 for (p
= ct_table
[i
]; p
; p
= next
)
5077 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5078 entry for that color already is in the color table, return the
5079 pixel color of that entry. Otherwise, allocate a new color for R,
5080 G, B, and make an entry in the color table. */
5082 static unsigned long
5083 lookup_rgb_color (f
, r
, g
, b
)
5087 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
5088 int i
= hash
% CT_SIZE
;
5090 Display_Info
*dpyinfo
;
5092 /* Handle TrueColor visuals specially, which improves performance by
5093 two orders of magnitude. Freeing colors on TrueColor visuals is
5094 a nop, and pixel colors specify RGB values directly. See also
5095 the Xlib spec, chapter 3.1. */
5096 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5097 if (dpyinfo
->red_bits
> 0)
5099 unsigned long pr
, pg
, pb
;
5101 /* Apply gamma-correction like normal color allocation does. */
5105 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
5106 gamma_correct (f
, &color
);
5107 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
5110 /* Scale down RGB values to the visual's bits per RGB, and shift
5111 them to the right position in the pixel color. Note that the
5112 original RGB values are 16-bit values, as usual in X. */
5113 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
5114 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
5115 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
5117 /* Assemble the pixel color. */
5118 return pr
| pg
| pb
;
5121 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5122 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
5128 #ifdef HAVE_X_WINDOWS
5137 cmap
= FRAME_X_COLORMAP (f
);
5138 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5141 ++ct_colors_allocated
;
5142 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5146 p
->pixel
= color
.pixel
;
5147 p
->next
= ct_table
[i
];
5151 return FRAME_FOREGROUND_PIXEL (f
);
5156 color
= PALETTERGB (r
, g
, b
);
5158 color
= RGB_TO_ULONG (r
, g
, b
);
5159 #endif /* HAVE_NTGUI */
5160 ++ct_colors_allocated
;
5161 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5166 p
->next
= ct_table
[i
];
5168 #endif /* HAVE_X_WINDOWS */
5176 /* Look up pixel color PIXEL which is used on frame F in the color
5177 table. If not already present, allocate it. Value is PIXEL. */
5179 static unsigned long
5180 lookup_pixel_color (f
, pixel
)
5182 unsigned long pixel
;
5184 int i
= pixel
% CT_SIZE
;
5187 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5188 if (p
->pixel
== pixel
)
5197 #ifdef HAVE_X_WINDOWS
5198 cmap
= FRAME_X_COLORMAP (f
);
5199 color
.pixel
= pixel
;
5200 x_query_color (f
, &color
);
5201 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5204 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
5205 color
.pixel
= pixel
;
5206 XQueryColor (NULL
, cmap
, &color
);
5207 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
5209 #endif /* HAVE_X_WINDOWS */
5213 ++ct_colors_allocated
;
5215 p
= (struct ct_color
*) xmalloc (sizeof *p
);
5220 p
->next
= ct_table
[i
];
5224 return FRAME_FOREGROUND_PIXEL (f
);
5230 /* Value is a vector of all pixel colors contained in the color table,
5231 allocated via xmalloc. Set *N to the number of colors. */
5233 static unsigned long *
5234 colors_in_color_table (n
)
5239 unsigned long *colors
;
5241 if (ct_colors_allocated
== 0)
5248 colors
= (unsigned long *) xmalloc (ct_colors_allocated
5250 *n
= ct_colors_allocated
;
5252 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
5253 for (p
= ct_table
[i
]; p
; p
= p
->next
)
5254 colors
[j
++] = p
->pixel
;
5260 #else /* COLOR_TABLE_SUPPORT */
5262 static unsigned long
5263 lookup_rgb_color (f
, r
, g
, b
)
5267 unsigned long pixel
;
5270 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
5271 gamma_correct (f
, &pixel
);
5275 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
5276 #endif /* HAVE_NTGUI */
5285 #endif /* COLOR_TABLE_SUPPORT */
5288 /***********************************************************************
5290 ***********************************************************************/
5292 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
5293 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
5294 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
5297 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
5298 #endif /* HAVE_NTGUI */
5300 /* Non-zero means draw a cross on images having `:conversion
5303 int cross_disabled_images
;
5305 /* Edge detection matrices for different edge-detection
5308 static int emboss_matrix
[9] = {
5310 2, -1, 0, /* y - 1 */
5312 0, 1, -2 /* y + 1 */
5315 static int laplace_matrix
[9] = {
5317 1, 0, 0, /* y - 1 */
5319 0, 0, -1 /* y + 1 */
5322 /* Value is the intensity of the color whose red/green/blue values
5325 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5328 /* On frame F, return an array of XColor structures describing image
5329 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5330 non-zero means also fill the red/green/blue members of the XColor
5331 structures. Value is a pointer to the array of XColors structures,
5332 allocated with xmalloc; it must be freed by the caller. */
5335 x_to_xcolors (f
, img
, rgb_p
)
5342 XImagePtr_or_DC ximg
;
5346 #endif /* HAVE_NTGUI */
5348 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5351 /* Get the X image IMG->pixmap. */
5352 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5353 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5355 /* Load the image into a memory device context. */
5356 hdc
= get_frame_dc (f
);
5357 ximg
= CreateCompatibleDC (hdc
);
5358 release_frame_dc (f
, hdc
);
5359 prev
= SelectObject (ximg
, img
->pixmap
);
5360 #endif /* HAVE_NTGUI */
5362 /* Fill the `pixel' members of the XColor array. I wished there
5363 were an easy and portable way to circumvent XGetPixel. */
5365 for (y
= 0; y
< img
->height
; ++y
)
5369 #ifdef HAVE_X_WINDOWS
5370 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5371 p
->pixel
= XGetPixel (ximg
, x
, y
);
5373 x_query_colors (f
, row
, img
->width
);
5377 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5379 /* W32_TODO: palette support needed here? */
5380 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5384 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5385 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5386 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5389 p
->red
= 256 * GetRValue (p
->pixel
);
5390 p
->green
= 256 * GetGValue (p
->pixel
);
5391 p
->blue
= 256 * GetBValue (p
->pixel
);
5392 #endif /* HAVE_NTGUI */
5395 #endif /* HAVE_X_WINDOWS */
5398 Destroy_Image (ximg
, prev
);
5405 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5406 created with CreateDIBSection, with the pointer to the bit values
5407 stored in ximg->data. */
5410 XPutPixel (ximg
, x
, y
, color
)
5415 int width
= ximg
->info
.bmiHeader
.biWidth
;
5416 int height
= ximg
->info
.bmiHeader
.biHeight
;
5417 unsigned char * pixel
;
5419 /* True color images. */
5420 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5422 int rowbytes
= width
* 3;
5423 /* Ensure scanlines are aligned on 4 byte boundaries. */
5425 rowbytes
+= 4 - (rowbytes
% 4);
5427 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5428 /* Windows bitmaps are in BGR order. */
5429 *pixel
= GetBValue (color
);
5430 *(pixel
+ 1) = GetGValue (color
);
5431 *(pixel
+ 2) = GetRValue (color
);
5433 /* Monochrome images. */
5434 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5436 int rowbytes
= width
/ 8;
5437 /* Ensure scanlines are aligned on 4 byte boundaries. */
5439 rowbytes
+= 4 - (rowbytes
% 4);
5440 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5441 /* Filter out palette info. */
5442 if (color
& 0x00ffffff)
5443 *pixel
= *pixel
| (1 << x
% 8);
5445 *pixel
= *pixel
& ~(1 << x
% 8);
5448 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5451 #endif /* HAVE_NTGUI */
5453 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5454 RGB members are set. F is the frame on which this all happens.
5455 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5458 x_from_xcolors (f
, img
, colors
)
5468 init_color_table ();
5470 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5473 for (y
= 0; y
< img
->height
; ++y
)
5474 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5476 unsigned long pixel
;
5477 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5478 XPutPixel (oimg
, x
, y
, pixel
);
5482 x_clear_image_1 (f
, img
, 1, 0, 1);
5484 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5485 x_destroy_x_image (oimg
);
5486 img
->pixmap
= pixmap
;
5487 #ifdef COLOR_TABLE_SUPPORT
5488 img
->colors
= colors_in_color_table (&img
->ncolors
);
5489 free_color_table ();
5490 #endif /* COLOR_TABLE_SUPPORT */
5494 /* On frame F, perform edge-detection on image IMG.
5496 MATRIX is a nine-element array specifying the transformation
5497 matrix. See emboss_matrix for an example.
5499 COLOR_ADJUST is a color adjustment added to each pixel of the
5503 x_detect_edges (f
, img
, matrix
, color_adjust
)
5506 int matrix
[9], color_adjust
;
5508 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5512 for (i
= sum
= 0; i
< 9; ++i
)
5513 sum
+= eabs (matrix
[i
]);
5515 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5517 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5519 for (y
= 0; y
< img
->height
; ++y
)
5521 p
= COLOR (new, 0, y
);
5522 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5523 p
= COLOR (new, img
->width
- 1, y
);
5524 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5527 for (x
= 1; x
< img
->width
- 1; ++x
)
5529 p
= COLOR (new, x
, 0);
5530 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5531 p
= COLOR (new, x
, img
->height
- 1);
5532 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5535 for (y
= 1; y
< img
->height
- 1; ++y
)
5537 p
= COLOR (new, 1, y
);
5539 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5541 int r
, g
, b
, y1
, x1
;
5544 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5545 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5548 XColor
*t
= COLOR (colors
, x1
, y1
);
5549 r
+= matrix
[i
] * t
->red
;
5550 g
+= matrix
[i
] * t
->green
;
5551 b
+= matrix
[i
] * t
->blue
;
5554 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5555 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5556 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5557 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5562 x_from_xcolors (f
, img
, new);
5568 /* Perform the pre-defined `emboss' edge-detection on image IMG
5576 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5580 /* Transform image IMG which is used on frame F with a Laplace
5581 edge-detection algorithm. The result is an image that can be used
5582 to draw disabled buttons, for example. */
5589 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5593 /* Perform edge-detection on image IMG on frame F, with specified
5594 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5596 MATRIX must be either
5598 - a list of at least 9 numbers in row-major form
5599 - a vector of at least 9 numbers
5601 COLOR_ADJUST nil means use a default; otherwise it must be a
5605 x_edge_detection (f
, img
, matrix
, color_adjust
)
5608 Lisp_Object matrix
, color_adjust
;
5616 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5617 ++i
, matrix
= XCDR (matrix
))
5618 trans
[i
] = XFLOATINT (XCAR (matrix
));
5620 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5622 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5623 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5626 if (NILP (color_adjust
))
5627 color_adjust
= make_number (0xffff / 2);
5629 if (i
== 9 && NUMBERP (color_adjust
))
5630 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5634 /* Transform image IMG on frame F so that it looks disabled. */
5637 x_disable_image (f
, img
)
5641 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5643 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5645 int n_planes
= dpyinfo
->n_planes
;
5646 #endif /* HAVE_NTGUI */
5650 /* Color (or grayscale). Convert to gray, and equalize. Just
5651 drawing such images with a stipple can look very odd, so
5652 we're using this method instead. */
5653 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5655 const int h
= 15000;
5656 const int l
= 30000;
5658 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5662 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5663 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5664 p
->red
= p
->green
= p
->blue
= i2
;
5667 x_from_xcolors (f
, img
, colors
);
5670 /* Draw a cross over the disabled image, if we must or if we
5672 if (n_planes
< 2 || cross_disabled_images
)
5675 Display
*dpy
= FRAME_X_DISPLAY (f
);
5679 #define MaskForeground(f) PIX_MASK_DRAW
5681 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5684 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5685 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5686 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5687 img
->width
- 1, img
->height
- 1);
5688 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5694 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5695 XSetForeground (dpy
, gc
, MaskForeground (f
));
5696 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5697 img
->width
- 1, img
->height
- 1);
5698 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5706 hdc
= get_frame_dc (f
);
5707 bmpdc
= CreateCompatibleDC (hdc
);
5708 release_frame_dc (f
, hdc
);
5710 prev
= SelectObject (bmpdc
, img
->pixmap
);
5712 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5713 MoveToEx (bmpdc
, 0, 0, NULL
);
5714 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5715 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5716 LineTo (bmpdc
, img
->width
- 1, 0);
5720 SelectObject (bmpdc
, img
->mask
);
5721 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5722 MoveToEx (bmpdc
, 0, 0, NULL
);
5723 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5724 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5725 LineTo (bmpdc
, img
->width
- 1, 0);
5727 SelectObject (bmpdc
, prev
);
5729 #endif /* HAVE_NTGUI */
5734 /* Build a mask for image IMG which is used on frame F. FILE is the
5735 name of an image file, for error messages. HOW determines how to
5736 determine the background color of IMG. If it is a list '(R G B)',
5737 with R, G, and B being integers >= 0, take that as the color of the
5738 background. Otherwise, determine the background color of IMG
5739 heuristically. Value is non-zero if successful. */
5742 x_build_heuristic_mask (f
, img
, how
)
5747 XImagePtr_or_DC ximg
;
5755 #endif /* HAVE_NTGUI */
5756 int x
, y
, rc
, use_img_background
;
5757 unsigned long bg
= 0;
5761 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5762 img
->mask
= NO_PIXMAP
;
5763 img
->background_transparent_valid
= 0;
5767 /* Create an image and pixmap serving as mask. */
5768 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5769 &mask_img
, &img
->mask
);
5773 /* Get the X image of IMG->pixmap. */
5774 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5775 img
->width
, img
->height
,
5778 /* Create the bit array serving as mask. */
5779 row_width
= (img
->width
+ 7) / 8;
5780 mask_img
= xmalloc (row_width
* img
->height
);
5781 bzero (mask_img
, row_width
* img
->height
);
5783 /* Create a memory device context for IMG->pixmap. */
5784 frame_dc
= get_frame_dc (f
);
5785 ximg
= CreateCompatibleDC (frame_dc
);
5786 release_frame_dc (f
, frame_dc
);
5787 prev
= SelectObject (ximg
, img
->pixmap
);
5788 #endif /* HAVE_NTGUI */
5790 /* Determine the background color of ximg. If HOW is `(R G B)'
5791 take that as color. Otherwise, use the image's background color. */
5792 use_img_background
= 1;
5798 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5800 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5804 if (i
== 3 && NILP (how
))
5806 char color_name
[30];
5807 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5810 0x00ffffff & /* Filter out palette info. */
5811 #endif /* HAVE_NTGUI */
5812 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5813 use_img_background
= 0;
5817 if (use_img_background
)
5818 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5820 /* Set all bits in mask_img to 1 whose color in ximg is different
5821 from the background color bg. */
5823 for (y
= 0; y
< img
->height
; ++y
)
5824 for (x
= 0; x
< img
->width
; ++x
)
5825 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5826 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5828 /* Fill in the background_transparent field while we have the mask handy. */
5829 image_background_transparent (img
, f
, mask_img
);
5831 /* Put mask_img into img->mask. */
5832 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5833 x_destroy_x_image (mask_img
);
5836 for (y
= 0; y
< img
->height
; ++y
)
5837 for (x
= 0; x
< img
->width
; ++x
)
5839 COLORREF p
= GetPixel (ximg
, x
, y
);
5841 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5844 /* Create the mask image. */
5845 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5847 /* Fill in the background_transparent field while we have the mask handy. */
5848 SelectObject (ximg
, img
->mask
);
5849 image_background_transparent (img
, f
, ximg
);
5851 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5853 #endif /* HAVE_NTGUI */
5855 Destroy_Image (ximg
, prev
);
5861 /***********************************************************************
5862 PBM (mono, gray, color)
5863 ***********************************************************************/
5865 static int pbm_image_p
P_ ((Lisp_Object object
));
5866 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5867 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5869 /* The symbol `pbm' identifying images of this type. */
5873 /* Indices of image specification fields in gs_format, below. */
5875 enum pbm_keyword_index
5891 /* Vector of image_keyword structures describing the format
5892 of valid user-defined image specifications. */
5894 static struct image_keyword pbm_format
[PBM_LAST
] =
5896 {":type", IMAGE_SYMBOL_VALUE
, 1},
5897 {":file", IMAGE_STRING_VALUE
, 0},
5898 {":data", IMAGE_STRING_VALUE
, 0},
5899 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5900 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5901 {":relief", IMAGE_INTEGER_VALUE
, 0},
5902 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5903 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5904 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5905 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5906 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5909 /* Structure describing the image type `pbm'. */
5911 static struct image_type pbm_type
=
5921 /* Return non-zero if OBJECT is a valid PBM image specification. */
5924 pbm_image_p (object
)
5927 struct image_keyword fmt
[PBM_LAST
];
5929 bcopy (pbm_format
, fmt
, sizeof fmt
);
5931 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5934 /* Must specify either :data or :file. */
5935 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5939 /* Scan a decimal number from *S and return it. Advance *S while
5940 reading the number. END is the end of the string. Value is -1 at
5944 pbm_scan_number (s
, end
)
5945 unsigned char **s
, *end
;
5947 int c
= 0, val
= -1;
5951 /* Skip white-space. */
5952 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5957 /* Skip comment to end of line. */
5958 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5961 else if (isdigit (c
))
5963 /* Read decimal number. */
5965 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5966 val
= 10 * val
+ c
- '0';
5978 #if 0 /* Unused. ++kfs */
5980 /* Read FILE into memory. Value is a pointer to a buffer allocated
5981 with xmalloc holding FILE's contents. Value is null if an error
5982 occurred. *SIZE is set to the size of the file. */
5985 pbm_read_file (file
, size
)
5993 if (stat (SDATA (file
), &st
) == 0
5994 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5995 && (buf
= (char *) xmalloc (st
.st_size
),
5996 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
6015 #endif /* HAVE_NTGUI */
6017 /* Load PBM image IMG for use on frame F. */
6025 int width
, height
, max_color_idx
= 0;
6027 Lisp_Object file
, specified_file
;
6028 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
6029 struct gcpro gcpro1
;
6030 unsigned char *contents
= NULL
;
6031 unsigned char *end
, *p
;
6034 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6038 if (STRINGP (specified_file
))
6040 file
= x_find_image_file (specified_file
);
6041 if (!STRINGP (file
))
6043 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6048 contents
= slurp_file (SDATA (file
), &size
);
6049 if (contents
== NULL
)
6051 image_error ("Error reading `%s'", file
, Qnil
);
6057 end
= contents
+ size
;
6062 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6064 end
= p
+ SBYTES (data
);
6067 /* Check magic number. */
6068 if (end
- p
< 2 || *p
++ != 'P')
6070 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6080 raw_p
= 0, type
= PBM_MONO
;
6084 raw_p
= 0, type
= PBM_GRAY
;
6088 raw_p
= 0, type
= PBM_COLOR
;
6092 raw_p
= 1, type
= PBM_MONO
;
6096 raw_p
= 1, type
= PBM_GRAY
;
6100 raw_p
= 1, type
= PBM_COLOR
;
6104 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
6108 /* Read width, height, maximum color-component. Characters
6109 starting with `#' up to the end of a line are ignored. */
6110 width
= pbm_scan_number (&p
, end
);
6111 height
= pbm_scan_number (&p
, end
);
6113 if (type
!= PBM_MONO
)
6115 max_color_idx
= pbm_scan_number (&p
, end
);
6116 if (max_color_idx
> 65535 || max_color_idx
< 0)
6118 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
6123 if (!check_image_size (f
, width
, height
))
6125 image_error ("Invalid image size", Qnil
, Qnil
);
6129 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
6130 &ximg
, &img
->pixmap
))
6133 /* Initialize the color hash table. */
6134 init_color_table ();
6136 if (type
== PBM_MONO
)
6139 struct image_keyword fmt
[PBM_LAST
];
6140 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
6141 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
6143 /* Parse the image specification. */
6144 bcopy (pbm_format
, fmt
, sizeof fmt
);
6145 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
6147 /* Get foreground and background colors, maybe allocate colors. */
6148 if (fmt
[PBM_FOREGROUND
].count
6149 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
6150 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
6151 if (fmt
[PBM_BACKGROUND
].count
6152 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
6154 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
6155 img
->background
= bg
;
6156 img
->background_valid
= 1;
6159 for (y
= 0; y
< height
; ++y
)
6160 for (x
= 0; x
< width
; ++x
)
6168 x_destroy_x_image (ximg
);
6169 x_clear_image (f
, img
);
6170 image_error ("Invalid image size in image `%s'",
6180 g
= pbm_scan_number (&p
, end
);
6182 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
6187 int expected_size
= height
* width
;
6188 if (max_color_idx
> 255)
6190 if (type
== PBM_COLOR
)
6193 if (raw_p
&& p
+ expected_size
> end
)
6195 x_destroy_x_image (ximg
);
6196 x_clear_image (f
, img
);
6197 image_error ("Invalid image size in image `%s'",
6202 for (y
= 0; y
< height
; ++y
)
6203 for (x
= 0; x
< width
; ++x
)
6207 if (type
== PBM_GRAY
&& raw_p
)
6210 if (max_color_idx
> 255)
6211 r
= g
= b
= r
* 256 + *p
++;
6213 else if (type
== PBM_GRAY
)
6214 r
= g
= b
= pbm_scan_number (&p
, end
);
6218 if (max_color_idx
> 255)
6221 if (max_color_idx
> 255)
6224 if (max_color_idx
> 255)
6229 r
= pbm_scan_number (&p
, end
);
6230 g
= pbm_scan_number (&p
, end
);
6231 b
= pbm_scan_number (&p
, end
);
6234 if (r
< 0 || g
< 0 || b
< 0)
6236 x_destroy_x_image (ximg
);
6237 image_error ("Invalid pixel value in image `%s'",
6242 /* RGB values are now in the range 0..max_color_idx.
6243 Scale this to the range 0..0xffff supported by X. */
6244 r
= (double) r
* 65535 / max_color_idx
;
6245 g
= (double) g
* 65535 / max_color_idx
;
6246 b
= (double) b
* 65535 / max_color_idx
;
6247 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6251 #ifdef COLOR_TABLE_SUPPORT
6252 /* Store in IMG->colors the colors allocated for the image, and
6253 free the color table. */
6254 img
->colors
= colors_in_color_table (&img
->ncolors
);
6255 free_color_table ();
6256 #endif /* COLOR_TABLE_SUPPORT */
6259 img
->height
= height
;
6261 /* Maybe fill in the background field while we have ximg handy. */
6263 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6264 /* Casting avoids a GCC warning. */
6265 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6267 /* Put the image into a pixmap. */
6268 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6269 x_destroy_x_image (ximg
);
6271 /* X and W32 versions did it here, MAC version above. ++kfs
6273 img->height = height; */
6281 /***********************************************************************
6283 ***********************************************************************/
6285 #if defined (HAVE_PNG) || defined (MAC_OS)
6287 /* Function prototypes. */
6289 static int png_image_p
P_ ((Lisp_Object object
));
6290 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
6292 /* The symbol `png' identifying images of this type. */
6296 /* Indices of image specification fields in png_format, below. */
6298 enum png_keyword_index
6313 /* Vector of image_keyword structures describing the format
6314 of valid user-defined image specifications. */
6316 static struct image_keyword png_format
[PNG_LAST
] =
6318 {":type", IMAGE_SYMBOL_VALUE
, 1},
6319 {":data", IMAGE_STRING_VALUE
, 0},
6320 {":file", IMAGE_STRING_VALUE
, 0},
6321 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6322 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6323 {":relief", IMAGE_INTEGER_VALUE
, 0},
6324 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6325 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6326 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6327 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6330 /* Structure describing the image type `png'. */
6332 static struct image_type png_type
=
6341 /* Return non-zero if OBJECT is a valid PNG image specification. */
6344 png_image_p (object
)
6347 struct image_keyword fmt
[PNG_LAST
];
6348 bcopy (png_format
, fmt
, sizeof fmt
);
6350 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
6353 /* Must specify either the :data or :file keyword. */
6354 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
6357 #endif /* HAVE_PNG || MAC_OS */
6362 #if defined HAVE_LIBPNG_PNG_H
6363 # include <libpng/png.h>
6369 /* PNG library details. */
6371 DEF_IMGLIB_FN (png_get_io_ptr
);
6372 DEF_IMGLIB_FN (png_check_sig
);
6373 DEF_IMGLIB_FN (png_create_read_struct
);
6374 DEF_IMGLIB_FN (png_create_info_struct
);
6375 DEF_IMGLIB_FN (png_destroy_read_struct
);
6376 DEF_IMGLIB_FN (png_set_read_fn
);
6377 DEF_IMGLIB_FN (png_set_sig_bytes
);
6378 DEF_IMGLIB_FN (png_read_info
);
6379 DEF_IMGLIB_FN (png_get_IHDR
);
6380 DEF_IMGLIB_FN (png_get_valid
);
6381 DEF_IMGLIB_FN (png_set_strip_16
);
6382 DEF_IMGLIB_FN (png_set_expand
);
6383 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6384 DEF_IMGLIB_FN (png_set_background
);
6385 DEF_IMGLIB_FN (png_get_bKGD
);
6386 DEF_IMGLIB_FN (png_read_update_info
);
6387 DEF_IMGLIB_FN (png_get_channels
);
6388 DEF_IMGLIB_FN (png_get_rowbytes
);
6389 DEF_IMGLIB_FN (png_read_image
);
6390 DEF_IMGLIB_FN (png_read_end
);
6391 DEF_IMGLIB_FN (png_error
);
6394 init_png_functions (Lisp_Object libraries
)
6398 /* Try loading libpng under probable names. */
6399 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6402 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6403 LOAD_IMGLIB_FN (library
, png_check_sig
);
6404 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6405 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6406 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6407 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6408 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6409 LOAD_IMGLIB_FN (library
, png_read_info
);
6410 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6411 LOAD_IMGLIB_FN (library
, png_get_valid
);
6412 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6413 LOAD_IMGLIB_FN (library
, png_set_expand
);
6414 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6415 LOAD_IMGLIB_FN (library
, png_set_background
);
6416 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6417 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6418 LOAD_IMGLIB_FN (library
, png_get_channels
);
6419 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6420 LOAD_IMGLIB_FN (library
, png_read_image
);
6421 LOAD_IMGLIB_FN (library
, png_read_end
);
6422 LOAD_IMGLIB_FN (library
, png_error
);
6427 #define fn_png_get_io_ptr png_get_io_ptr
6428 #define fn_png_check_sig png_check_sig
6429 #define fn_png_create_read_struct png_create_read_struct
6430 #define fn_png_create_info_struct png_create_info_struct
6431 #define fn_png_destroy_read_struct png_destroy_read_struct
6432 #define fn_png_set_read_fn png_set_read_fn
6433 #define fn_png_set_sig_bytes png_set_sig_bytes
6434 #define fn_png_read_info png_read_info
6435 #define fn_png_get_IHDR png_get_IHDR
6436 #define fn_png_get_valid png_get_valid
6437 #define fn_png_set_strip_16 png_set_strip_16
6438 #define fn_png_set_expand png_set_expand
6439 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6440 #define fn_png_set_background png_set_background
6441 #define fn_png_get_bKGD png_get_bKGD
6442 #define fn_png_read_update_info png_read_update_info
6443 #define fn_png_get_channels png_get_channels
6444 #define fn_png_get_rowbytes png_get_rowbytes
6445 #define fn_png_read_image png_read_image
6446 #define fn_png_read_end png_read_end
6447 #define fn_png_error png_error
6449 #endif /* HAVE_NTGUI */
6451 /* Error and warning handlers installed when the PNG library
6455 my_png_error (png_ptr
, msg
)
6456 png_struct
*png_ptr
;
6459 xassert (png_ptr
!= NULL
);
6460 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6461 longjmp (png_ptr
->jmpbuf
, 1);
6466 my_png_warning (png_ptr
, msg
)
6467 png_struct
*png_ptr
;
6470 xassert (png_ptr
!= NULL
);
6471 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6474 /* Memory source for PNG decoding. */
6476 struct png_memory_storage
6478 unsigned char *bytes
; /* The data */
6479 size_t len
; /* How big is it? */
6480 int index
; /* Where are we? */
6484 /* Function set as reader function when reading PNG image from memory.
6485 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6486 bytes from the input to DATA. */
6489 png_read_from_memory (png_ptr
, data
, length
)
6490 png_structp png_ptr
;
6494 struct png_memory_storage
*tbr
6495 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6497 if (length
> tbr
->len
- tbr
->index
)
6498 fn_png_error (png_ptr
, "Read error");
6500 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6501 tbr
->index
= tbr
->index
+ length
;
6505 /* Function set as reader function when reading PNG image from a file.
6506 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6507 bytes from the input to DATA. */
6510 png_read_from_file (png_ptr
, data
, length
)
6511 png_structp png_ptr
;
6515 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6517 if (fread (data
, 1, length
, fp
) < length
)
6518 fn_png_error (png_ptr
, "Read error");
6522 /* Load PNG image IMG for use on frame F. Value is non-zero if
6530 Lisp_Object file
, specified_file
;
6531 Lisp_Object specified_data
;
6533 XImagePtr ximg
, mask_img
= NULL
;
6534 struct gcpro gcpro1
;
6535 png_struct
*png_ptr
= NULL
;
6536 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6537 FILE *volatile fp
= NULL
;
6539 png_byte
* volatile pixels
= NULL
;
6540 png_byte
** volatile rows
= NULL
;
6541 png_uint_32 width
, height
;
6542 int bit_depth
, color_type
, interlace_type
;
6544 png_uint_32 row_bytes
;
6546 struct png_memory_storage tbr
; /* Data to be read */
6548 /* Find out what file to load. */
6549 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6550 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6554 if (NILP (specified_data
))
6556 file
= x_find_image_file (specified_file
);
6557 if (!STRINGP (file
))
6559 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6564 /* Open the image file. */
6565 fp
= fopen (SDATA (file
), "rb");
6568 image_error ("Cannot open image file `%s'", file
, Qnil
);
6573 /* Check PNG signature. */
6574 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6575 || !fn_png_check_sig (sig
, sizeof sig
))
6577 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6585 /* Read from memory. */
6586 tbr
.bytes
= SDATA (specified_data
);
6587 tbr
.len
= SBYTES (specified_data
);
6590 /* Check PNG signature. */
6591 if (tbr
.len
< sizeof sig
6592 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6594 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6599 /* Need to skip past the signature. */
6600 tbr
.bytes
+= sizeof (sig
);
6603 /* Initialize read and info structs for PNG lib. Casting return
6604 value avoids a GCC warning on W32. */
6605 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6610 if (fp
) fclose (fp
);
6615 /* Casting return value avoids a GCC warning on W32. */
6616 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6619 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6620 if (fp
) fclose (fp
);
6625 /* Casting return value avoids a GCC warning on W32. */
6626 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6629 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6630 if (fp
) fclose (fp
);
6635 /* Set error jump-back. We come back here when the PNG library
6636 detects an error. */
6637 if (setjmp (png_ptr
->jmpbuf
))
6641 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6644 if (fp
) fclose (fp
);
6649 /* Read image info. */
6650 if (!NILP (specified_data
))
6651 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6653 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6655 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6656 fn_png_read_info (png_ptr
, info_ptr
);
6657 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6658 &interlace_type
, NULL
, NULL
);
6660 if (!check_image_size (f
, width
, height
))
6663 /* If image contains simply transparency data, we prefer to
6664 construct a clipping mask. */
6665 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6670 /* This function is easier to write if we only have to handle
6671 one data format: RGB or RGBA with 8 bits per channel. Let's
6672 transform other formats into that format. */
6674 /* Strip more than 8 bits per channel. */
6675 if (bit_depth
== 16)
6676 fn_png_set_strip_16 (png_ptr
);
6678 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6680 fn_png_set_expand (png_ptr
);
6682 /* Convert grayscale images to RGB. */
6683 if (color_type
== PNG_COLOR_TYPE_GRAY
6684 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6685 fn_png_set_gray_to_rgb (png_ptr
);
6687 /* Handle alpha channel by combining the image with a background
6688 color. Do this only if a real alpha channel is supplied. For
6689 simple transparency, we prefer a clipping mask. */
6692 /* png_color_16 *image_bg; */
6693 Lisp_Object specified_bg
6694 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6695 int shift
= (bit_depth
== 16) ? 0 : 8;
6697 if (STRINGP (specified_bg
))
6698 /* The user specified `:background', use that. */
6700 /* W32 version incorrectly used COLORREF here!! ++kfs */
6702 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6704 png_color_16 user_bg
;
6706 bzero (&user_bg
, sizeof user_bg
);
6707 user_bg
.red
= color
.red
>> shift
;
6708 user_bg
.green
= color
.green
>> shift
;
6709 user_bg
.blue
= color
.blue
>> shift
;
6711 fn_png_set_background (png_ptr
, &user_bg
,
6712 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6717 /* We use the current frame background, ignoring any default
6718 background color set by the image. */
6719 #ifdef HAVE_X_WINDOWS
6721 png_color_16 frame_background
;
6723 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6724 x_query_color (f
, &color
);
6726 bzero (&frame_background
, sizeof frame_background
);
6727 frame_background
.red
= color
.red
>> shift
;
6728 frame_background
.green
= color
.green
>> shift
;
6729 frame_background
.blue
= color
.blue
>> shift
;
6730 #endif /* HAVE_X_WINDOWS */
6734 png_color_16 frame_background
;
6735 color
= FRAME_BACKGROUND_PIXEL (f
);
6736 #if 0 /* W32 TODO : Colormap support. */
6737 x_query_color (f
, &color
);
6739 bzero (&frame_background
, sizeof frame_background
);
6740 frame_background
.red
= GetRValue (color
);
6741 frame_background
.green
= GetGValue (color
);
6742 frame_background
.blue
= GetBValue (color
);
6743 #endif /* HAVE_NTGUI */
6746 unsigned long color
;
6747 png_color_16 frame_background
;
6748 color
= FRAME_BACKGROUND_PIXEL (f
);
6749 #if 0 /* MAC/W32 TODO : Colormap support. */
6750 x_query_color (f
, &color
);
6752 bzero (&frame_background
, sizeof frame_background
);
6753 frame_background
.red
= RED_FROM_ULONG (color
);
6754 frame_background
.green
= GREEN_FROM_ULONG (color
);
6755 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6758 fn_png_set_background (png_ptr
, &frame_background
,
6759 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6763 /* Update info structure. */
6764 fn_png_read_update_info (png_ptr
, info_ptr
);
6766 /* Get number of channels. Valid values are 1 for grayscale images
6767 and images with a palette, 2 for grayscale images with transparency
6768 information (alpha channel), 3 for RGB images, and 4 for RGB
6769 images with alpha channel, i.e. RGBA. If conversions above were
6770 sufficient we should only have 3 or 4 channels here. */
6771 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6772 xassert (channels
== 3 || channels
== 4);
6774 /* Number of bytes needed for one row of the image. */
6775 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6777 /* Allocate memory for the image. */
6778 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6779 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6780 for (i
= 0; i
< height
; ++i
)
6781 rows
[i
] = pixels
+ i
* row_bytes
;
6783 /* Read the entire image. */
6784 fn_png_read_image (png_ptr
, rows
);
6785 fn_png_read_end (png_ptr
, info_ptr
);
6792 /* Create the X image and pixmap. */
6793 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6797 /* Create an image and pixmap serving as mask if the PNG image
6798 contains an alpha channel. */
6801 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6802 &mask_img
, &img
->mask
))
6804 x_destroy_x_image (ximg
);
6805 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6806 img
->pixmap
= NO_PIXMAP
;
6810 /* Fill the X image and mask from PNG data. */
6811 init_color_table ();
6813 for (y
= 0; y
< height
; ++y
)
6815 png_byte
*p
= rows
[y
];
6817 for (x
= 0; x
< width
; ++x
)
6824 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6825 /* An alpha channel, aka mask channel, associates variable
6826 transparency with an image. Where other image formats
6827 support binary transparency---fully transparent or fully
6828 opaque---PNG allows up to 254 levels of partial transparency.
6829 The PNG library implements partial transparency by combining
6830 the image with a specified background color.
6832 I'm not sure how to handle this here nicely: because the
6833 background on which the image is displayed may change, for
6834 real alpha channel support, it would be necessary to create
6835 a new image for each possible background.
6837 What I'm doing now is that a mask is created if we have
6838 boolean transparency information. Otherwise I'm using
6839 the frame's background color to combine the image with. */
6844 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6850 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6851 /* Set IMG's background color from the PNG image, unless the user
6855 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6857 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6858 img
->background_valid
= 1;
6862 #ifdef COLOR_TABLE_SUPPORT
6863 /* Remember colors allocated for this image. */
6864 img
->colors
= colors_in_color_table (&img
->ncolors
);
6865 free_color_table ();
6866 #endif /* COLOR_TABLE_SUPPORT */
6869 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6874 img
->height
= height
;
6876 /* Maybe fill in the background field while we have ximg handy.
6877 Casting avoids a GCC warning. */
6878 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6880 /* Put the image into the pixmap, then free the X image and its buffer. */
6881 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6882 x_destroy_x_image (ximg
);
6884 /* Same for the mask. */
6887 /* Fill in the background_transparent field while we have the
6888 mask handy. Casting avoids a GCC warning. */
6889 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6891 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6892 x_destroy_x_image (mask_img
);
6899 #else /* HAVE_PNG */
6907 #if USE_MAC_IMAGE_IO
6908 return image_load_image_io (f
, img
, kUTTypePNG
);
6909 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6910 return image_load_quartz2d (f
, img
, 1);
6912 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6917 #endif /* !HAVE_PNG */
6921 /***********************************************************************
6923 ***********************************************************************/
6925 #if defined (HAVE_JPEG) || defined (MAC_OS)
6927 static int jpeg_image_p
P_ ((Lisp_Object object
));
6928 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6930 /* The symbol `jpeg' identifying images of this type. */
6934 /* Indices of image specification fields in gs_format, below. */
6936 enum jpeg_keyword_index
6945 JPEG_HEURISTIC_MASK
,
6951 /* Vector of image_keyword structures describing the format
6952 of valid user-defined image specifications. */
6954 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6956 {":type", IMAGE_SYMBOL_VALUE
, 1},
6957 {":data", IMAGE_STRING_VALUE
, 0},
6958 {":file", IMAGE_STRING_VALUE
, 0},
6959 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6960 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6961 {":relief", IMAGE_INTEGER_VALUE
, 0},
6962 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6963 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6964 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6965 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6968 /* Structure describing the image type `jpeg'. */
6970 static struct image_type jpeg_type
=
6979 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6982 jpeg_image_p (object
)
6985 struct image_keyword fmt
[JPEG_LAST
];
6987 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6989 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6992 /* Must specify either the :data or :file keyword. */
6993 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6996 #endif /* HAVE_JPEG || MAC_OS */
7000 /* Work around a warning about HAVE_STDLIB_H being redefined in
7002 #ifdef HAVE_STDLIB_H
7003 #define HAVE_STDLIB_H_1
7004 #undef HAVE_STDLIB_H
7005 #endif /* HAVE_STLIB_H */
7007 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
7008 /* In older releases of the jpeg library, jpeglib.h will define boolean
7009 differently depending on __WIN32__, so make sure it is defined. */
7013 #include <jpeglib.h>
7017 #ifdef HAVE_STLIB_H_1
7018 #define HAVE_STDLIB_H 1
7023 /* JPEG library details. */
7024 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
7025 DEF_IMGLIB_FN (jpeg_start_decompress
);
7026 DEF_IMGLIB_FN (jpeg_finish_decompress
);
7027 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
7028 DEF_IMGLIB_FN (jpeg_read_header
);
7029 DEF_IMGLIB_FN (jpeg_read_scanlines
);
7030 DEF_IMGLIB_FN (jpeg_std_error
);
7031 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
7034 init_jpeg_functions (Lisp_Object libraries
)
7038 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
7041 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
7042 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
7043 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
7044 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
7045 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
7046 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
7047 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
7048 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
7052 /* Wrapper since we can't directly assign the function pointer
7053 to another function pointer that was declared more completely easily. */
7055 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
7056 j_decompress_ptr cinfo
;
7059 return fn_jpeg_resync_to_restart (cinfo
, desired
);
7064 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7065 #define fn_jpeg_start_decompress jpeg_start_decompress
7066 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7067 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7068 #define fn_jpeg_read_header jpeg_read_header
7069 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7070 #define fn_jpeg_std_error jpeg_std_error
7071 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7073 #endif /* HAVE_NTGUI */
7075 struct my_jpeg_error_mgr
7077 struct jpeg_error_mgr pub
;
7078 jmp_buf setjmp_buffer
;
7083 my_error_exit (cinfo
)
7086 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
7087 longjmp (mgr
->setjmp_buffer
, 1);
7091 /* Init source method for JPEG data source manager. Called by
7092 jpeg_read_header() before any data is actually read. See
7093 libjpeg.doc from the JPEG lib distribution. */
7096 our_common_init_source (cinfo
)
7097 j_decompress_ptr cinfo
;
7102 /* Method to terminate data source. Called by
7103 jpeg_finish_decompress() after all data has been processed. */
7106 our_common_term_source (cinfo
)
7107 j_decompress_ptr cinfo
;
7112 /* Fill input buffer method for JPEG data source manager. Called
7113 whenever more data is needed. We read the whole image in one step,
7114 so this only adds a fake end of input marker at the end. */
7116 static JOCTET our_memory_buffer
[2];
7119 our_memory_fill_input_buffer (cinfo
)
7120 j_decompress_ptr cinfo
;
7122 /* Insert a fake EOI marker. */
7123 struct jpeg_source_mgr
*src
= cinfo
->src
;
7125 our_memory_buffer
[0] = (JOCTET
) 0xFF;
7126 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
7128 src
->next_input_byte
= our_memory_buffer
;
7129 src
->bytes_in_buffer
= 2;
7134 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7135 is the JPEG data source manager. */
7138 our_memory_skip_input_data (cinfo
, num_bytes
)
7139 j_decompress_ptr cinfo
;
7142 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7146 if (num_bytes
> src
->bytes_in_buffer
)
7147 ERREXIT (cinfo
, JERR_INPUT_EOF
);
7149 src
->bytes_in_buffer
-= num_bytes
;
7150 src
->next_input_byte
+= num_bytes
;
7155 /* Set up the JPEG lib for reading an image from DATA which contains
7156 LEN bytes. CINFO is the decompression info structure created for
7157 reading the image. */
7160 jpeg_memory_src (cinfo
, data
, len
)
7161 j_decompress_ptr cinfo
;
7165 struct jpeg_source_mgr
*src
;
7167 if (cinfo
->src
== NULL
)
7169 /* First time for this JPEG object? */
7170 cinfo
->src
= (struct jpeg_source_mgr
*)
7171 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7172 sizeof (struct jpeg_source_mgr
));
7173 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7174 src
->next_input_byte
= data
;
7177 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
7178 src
->init_source
= our_common_init_source
;
7179 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
7180 src
->skip_input_data
= our_memory_skip_input_data
;
7181 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7182 src
->term_source
= our_common_term_source
;
7183 src
->bytes_in_buffer
= len
;
7184 src
->next_input_byte
= data
;
7188 struct jpeg_stdio_mgr
7190 struct jpeg_source_mgr mgr
;
7197 /* Size of buffer to read JPEG from file.
7198 Not too big, as we want to use alloc_small. */
7199 #define JPEG_STDIO_BUFFER_SIZE 8192
7202 /* Fill input buffer method for JPEG data source manager. Called
7203 whenever more data is needed. The data is read from a FILE *. */
7206 our_stdio_fill_input_buffer (cinfo
)
7207 j_decompress_ptr cinfo
;
7209 struct jpeg_stdio_mgr
*src
;
7211 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7216 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
7218 src
->mgr
.bytes_in_buffer
= bytes
;
7221 WARNMS (cinfo
, JWRN_JPEG_EOF
);
7223 src
->buffer
[0] = (JOCTET
) 0xFF;
7224 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
7225 src
->mgr
.bytes_in_buffer
= 2;
7227 src
->mgr
.next_input_byte
= src
->buffer
;
7234 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7235 is the JPEG data source manager. */
7238 our_stdio_skip_input_data (cinfo
, num_bytes
)
7239 j_decompress_ptr cinfo
;
7242 struct jpeg_stdio_mgr
*src
;
7243 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7245 while (num_bytes
> 0 && !src
->finished
)
7247 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
7249 src
->mgr
.bytes_in_buffer
-= num_bytes
;
7250 src
->mgr
.next_input_byte
+= num_bytes
;
7255 num_bytes
-= src
->mgr
.bytes_in_buffer
;
7256 src
->mgr
.bytes_in_buffer
= 0;
7257 src
->mgr
.next_input_byte
= NULL
;
7259 our_stdio_fill_input_buffer (cinfo
);
7265 /* Set up the JPEG lib for reading an image from a FILE *.
7266 CINFO is the decompression info structure created for
7267 reading the image. */
7270 jpeg_file_src (cinfo
, fp
)
7271 j_decompress_ptr cinfo
;
7274 struct jpeg_stdio_mgr
*src
;
7276 if (cinfo
->src
!= NULL
)
7277 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7280 /* First time for this JPEG object? */
7281 cinfo
->src
= (struct jpeg_source_mgr
*)
7282 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7283 sizeof (struct jpeg_stdio_mgr
));
7284 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
7285 src
->buffer
= (JOCTET
*)
7286 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
7287 JPEG_STDIO_BUFFER_SIZE
);
7292 src
->mgr
.init_source
= our_common_init_source
;
7293 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
7294 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
7295 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
7296 src
->mgr
.term_source
= our_common_term_source
;
7297 src
->mgr
.bytes_in_buffer
= 0;
7298 src
->mgr
.next_input_byte
= NULL
;
7302 /* Load image IMG for use on frame F. Patterned after example.c
7303 from the JPEG lib. */
7310 struct jpeg_decompress_struct cinfo
;
7311 struct my_jpeg_error_mgr mgr
;
7312 Lisp_Object file
, specified_file
;
7313 Lisp_Object specified_data
;
7314 FILE * volatile fp
= NULL
;
7316 int row_stride
, x
, y
;
7317 XImagePtr ximg
= NULL
;
7319 unsigned long *colors
;
7321 struct gcpro gcpro1
;
7323 /* Open the JPEG file. */
7324 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7325 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7329 if (NILP (specified_data
))
7331 file
= x_find_image_file (specified_file
);
7332 if (!STRINGP (file
))
7334 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7339 fp
= fopen (SDATA (file
), "rb");
7342 image_error ("Cannot open `%s'", file
, Qnil
);
7348 /* Customize libjpeg's error handling to call my_error_exit when an
7349 error is detected. This function will perform a longjmp.
7350 Casting return value avoids a GCC warning on W32. */
7351 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7352 mgr
.pub
.error_exit
= my_error_exit
;
7354 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7358 /* Called from my_error_exit. Display a JPEG error. */
7359 char buffer
[JMSG_LENGTH_MAX
];
7360 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7361 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7362 build_string (buffer
));
7365 /* Close the input file and destroy the JPEG object. */
7367 fclose ((FILE *) fp
);
7368 fn_jpeg_destroy_decompress (&cinfo
);
7370 /* If we already have an XImage, free that. */
7371 x_destroy_x_image (ximg
);
7373 /* Free pixmap and colors. */
7374 x_clear_image (f
, img
);
7380 /* Create the JPEG decompression object. Let it read from fp.
7381 Read the JPEG image header. */
7382 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7384 if (NILP (specified_data
))
7385 jpeg_file_src (&cinfo
, (FILE *) fp
);
7387 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7388 SBYTES (specified_data
));
7390 fn_jpeg_read_header (&cinfo
, 1);
7392 /* Customize decompression so that color quantization will be used.
7393 Start decompression. */
7394 cinfo
.quantize_colors
= 1;
7395 fn_jpeg_start_decompress (&cinfo
);
7396 width
= img
->width
= cinfo
.output_width
;
7397 height
= img
->height
= cinfo
.output_height
;
7399 if (!check_image_size (f
, width
, height
))
7401 image_error ("Invalid image size", Qnil
, Qnil
);
7402 longjmp (mgr
.setjmp_buffer
, 2);
7405 /* Create X image and pixmap. */
7406 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7407 longjmp (mgr
.setjmp_buffer
, 2);
7409 /* Allocate colors. When color quantization is used,
7410 cinfo.actual_number_of_colors has been set with the number of
7411 colors generated, and cinfo.colormap is a two-dimensional array
7412 of color indices in the range 0..cinfo.actual_number_of_colors.
7413 No more than 255 colors will be generated. */
7417 if (cinfo
.out_color_components
> 2)
7418 ir
= 0, ig
= 1, ib
= 2;
7419 else if (cinfo
.out_color_components
> 1)
7420 ir
= 0, ig
= 1, ib
= 0;
7422 ir
= 0, ig
= 0, ib
= 0;
7424 /* Use the color table mechanism because it handles colors that
7425 cannot be allocated nicely. Such colors will be replaced with
7426 a default color, and we don't have to care about which colors
7427 can be freed safely, and which can't. */
7428 init_color_table ();
7429 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7432 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7434 /* Multiply RGB values with 255 because X expects RGB values
7435 in the range 0..0xffff. */
7436 int r
= cinfo
.colormap
[ir
][i
] << 8;
7437 int g
= cinfo
.colormap
[ig
][i
] << 8;
7438 int b
= cinfo
.colormap
[ib
][i
] << 8;
7439 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7442 #ifdef COLOR_TABLE_SUPPORT
7443 /* Remember those colors actually allocated. */
7444 img
->colors
= colors_in_color_table (&img
->ncolors
);
7445 free_color_table ();
7446 #endif /* COLOR_TABLE_SUPPORT */
7450 row_stride
= width
* cinfo
.output_components
;
7451 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7453 for (y
= 0; y
< height
; ++y
)
7455 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7456 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7457 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7461 fn_jpeg_finish_decompress (&cinfo
);
7462 fn_jpeg_destroy_decompress (&cinfo
);
7464 fclose ((FILE *) fp
);
7466 /* Maybe fill in the background field while we have ximg handy. */
7467 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7468 /* Casting avoids a GCC warning. */
7469 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7471 /* Put the image into the pixmap. */
7472 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7473 x_destroy_x_image (ximg
);
7478 #else /* HAVE_JPEG */
7486 #if USE_MAC_IMAGE_IO
7487 return image_load_image_io (f
, img
, kUTTypeJPEG
);
7488 #elif defined (MAC_OSX)
7489 return image_load_quartz2d (f
, img
, 0);
7491 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7496 #endif /* !HAVE_JPEG */
7500 /***********************************************************************
7502 ***********************************************************************/
7504 #if defined (HAVE_TIFF) || defined (MAC_OS)
7506 static int tiff_image_p
P_ ((Lisp_Object object
));
7507 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7509 /* The symbol `tiff' identifying images of this type. */
7513 /* Indices of image specification fields in tiff_format, below. */
7515 enum tiff_keyword_index
7524 TIFF_HEURISTIC_MASK
,
7530 /* Vector of image_keyword structures describing the format
7531 of valid user-defined image specifications. */
7533 static struct image_keyword tiff_format
[TIFF_LAST
] =
7535 {":type", IMAGE_SYMBOL_VALUE
, 1},
7536 {":data", IMAGE_STRING_VALUE
, 0},
7537 {":file", IMAGE_STRING_VALUE
, 0},
7538 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7539 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7540 {":relief", IMAGE_INTEGER_VALUE
, 0},
7541 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7542 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7543 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7544 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7547 /* Structure describing the image type `tiff'. */
7549 static struct image_type tiff_type
=
7558 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7561 tiff_image_p (object
)
7564 struct image_keyword fmt
[TIFF_LAST
];
7565 bcopy (tiff_format
, fmt
, sizeof fmt
);
7567 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7570 /* Must specify either the :data or :file keyword. */
7571 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7574 #endif /* HAVE_TIFF || MAC_OS */
7582 /* TIFF library details. */
7583 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7584 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7585 DEF_IMGLIB_FN (TIFFOpen
);
7586 DEF_IMGLIB_FN (TIFFClientOpen
);
7587 DEF_IMGLIB_FN (TIFFGetField
);
7588 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7589 DEF_IMGLIB_FN (TIFFClose
);
7592 init_tiff_functions (Lisp_Object libraries
)
7596 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7599 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7600 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7601 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7602 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7603 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7604 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7605 LOAD_IMGLIB_FN (library
, TIFFClose
);
7611 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7612 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7613 #define fn_TIFFOpen TIFFOpen
7614 #define fn_TIFFClientOpen TIFFClientOpen
7615 #define fn_TIFFGetField TIFFGetField
7616 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7617 #define fn_TIFFClose TIFFClose
7619 #endif /* HAVE_NTGUI */
7622 /* Reading from a memory buffer for TIFF images Based on the PNG
7623 memory source, but we have to provide a lot of extra functions.
7626 We really only need to implement read and seek, but I am not
7627 convinced that the TIFF library is smart enough not to destroy
7628 itself if we only hand it the function pointers we need to
7633 unsigned char *bytes
;
7640 tiff_read_from_memory (data
, buf
, size
)
7645 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7647 if (size
> src
->len
- src
->index
)
7649 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7655 tiff_write_from_memory (data
, buf
, size
)
7664 tiff_seek_in_memory (data
, off
, whence
)
7669 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7674 case SEEK_SET
: /* Go from beginning of source. */
7678 case SEEK_END
: /* Go from end of source. */
7679 idx
= src
->len
+ off
;
7682 case SEEK_CUR
: /* Go from current position. */
7683 idx
= src
->index
+ off
;
7686 default: /* Invalid `whence'. */
7690 if (idx
> src
->len
|| idx
< 0)
7698 tiff_close_memory (data
)
7706 tiff_mmap_memory (data
, pbase
, psize
)
7711 /* It is already _IN_ memory. */
7716 tiff_unmap_memory (data
, base
, size
)
7721 /* We don't need to do this. */
7725 tiff_size_of_memory (data
)
7728 return ((tiff_memory_source
*) data
)->len
;
7733 tiff_error_handler (title
, format
, ap
)
7734 const char *title
, *format
;
7740 len
= sprintf (buf
, "TIFF error: %s ", title
);
7741 vsprintf (buf
+ len
, format
, ap
);
7742 add_to_log (buf
, Qnil
, Qnil
);
7747 tiff_warning_handler (title
, format
, ap
)
7748 const char *title
, *format
;
7754 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7755 vsprintf (buf
+ len
, format
, ap
);
7756 add_to_log (buf
, Qnil
, Qnil
);
7760 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7768 Lisp_Object file
, specified_file
;
7769 Lisp_Object specified_data
;
7771 int width
, height
, x
, y
;
7775 struct gcpro gcpro1
;
7776 tiff_memory_source memsrc
;
7778 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7779 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7783 fn_TIFFSetErrorHandler (tiff_error_handler
);
7784 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7786 if (NILP (specified_data
))
7788 /* Read from a file */
7789 file
= x_find_image_file (specified_file
);
7790 if (!STRINGP (file
))
7792 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7797 /* Try to open the image file. Casting return value avoids a
7798 GCC warning on W32. */
7799 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7802 image_error ("Cannot open `%s'", file
, Qnil
);
7809 /* Memory source! */
7810 memsrc
.bytes
= SDATA (specified_data
);
7811 memsrc
.len
= SBYTES (specified_data
);
7814 /* Casting return value avoids a GCC warning on W32. */
7815 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7816 (TIFFReadWriteProc
) tiff_read_from_memory
,
7817 (TIFFReadWriteProc
) tiff_write_from_memory
,
7818 tiff_seek_in_memory
,
7820 tiff_size_of_memory
,
7826 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7832 /* Get width and height of the image, and allocate a raster buffer
7833 of width x height 32-bit values. */
7834 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7835 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7837 if (!check_image_size (f
, width
, height
))
7839 image_error ("Invalid image size", Qnil
, Qnil
);
7844 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7846 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7847 fn_TIFFClose (tiff
);
7850 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7856 /* Create the X image and pixmap. */
7857 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7864 /* Initialize the color table. */
7865 init_color_table ();
7867 /* Process the pixel raster. Origin is in the lower-left corner. */
7868 for (y
= 0; y
< height
; ++y
)
7870 uint32
*row
= buf
+ y
* width
;
7872 for (x
= 0; x
< width
; ++x
)
7874 uint32 abgr
= row
[x
];
7875 int r
= TIFFGetR (abgr
) << 8;
7876 int g
= TIFFGetG (abgr
) << 8;
7877 int b
= TIFFGetB (abgr
) << 8;
7878 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7882 #ifdef COLOR_TABLE_SUPPORT
7883 /* Remember the colors allocated for the image. Free the color table. */
7884 img
->colors
= colors_in_color_table (&img
->ncolors
);
7885 free_color_table ();
7886 #endif /* COLOR_TABLE_SUPPORT */
7889 img
->height
= height
;
7891 /* Maybe fill in the background field while we have ximg handy. */
7892 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7893 /* Casting avoids a GCC warning on W32. */
7894 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7896 /* Put the image into the pixmap, then free the X image and its buffer. */
7897 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7898 x_destroy_x_image (ximg
);
7905 #else /* HAVE_TIFF */
7913 #if USE_MAC_IMAGE_IO
7914 return image_load_image_io (f
, img
, kUTTypeTIFF
);
7916 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7921 #endif /* !HAVE_TIFF */
7925 /***********************************************************************
7927 ***********************************************************************/
7929 #if defined (HAVE_GIF) || defined (MAC_OS)
7931 static int gif_image_p
P_ ((Lisp_Object object
));
7932 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7933 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7935 /* The symbol `gif' identifying images of this type. */
7939 /* Indices of image specification fields in gif_format, below. */
7941 enum gif_keyword_index
7957 /* Vector of image_keyword structures describing the format
7958 of valid user-defined image specifications. */
7960 static struct image_keyword gif_format
[GIF_LAST
] =
7962 {":type", IMAGE_SYMBOL_VALUE
, 1},
7963 {":data", IMAGE_STRING_VALUE
, 0},
7964 {":file", IMAGE_STRING_VALUE
, 0},
7965 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7966 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7967 {":relief", IMAGE_INTEGER_VALUE
, 0},
7968 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7969 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7970 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7971 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7972 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7975 /* Structure describing the image type `gif'. */
7977 static struct image_type gif_type
=
7986 /* Free X resources of GIF image IMG which is used on frame F. */
7989 gif_clear_image (f
, img
)
7993 /* IMG->data.ptr_val may contain extension data. */
7994 img
->data
.lisp_val
= Qnil
;
7995 x_clear_image (f
, img
);
7998 /* Return non-zero if OBJECT is a valid GIF image specification. */
8001 gif_image_p (object
)
8004 struct image_keyword fmt
[GIF_LAST
];
8005 bcopy (gif_format
, fmt
, sizeof fmt
);
8007 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
8010 /* Must specify either the :data or :file keyword. */
8011 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
8014 #endif /* HAVE_GIF || MAC_OS */
8018 #if defined (HAVE_NTGUI) || defined (MAC_OS)
8019 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
8020 Undefine before redefining to avoid a preprocessor warning. */
8024 /* avoid conflict with QuickdrawText.h */
8025 #define DrawText gif_DrawText
8026 #include <gif_lib.h>
8029 #else /* HAVE_NTGUI || MAC_OS */
8031 #include <gif_lib.h>
8033 #endif /* HAVE_NTGUI || MAC_OS */
8038 /* GIF library details. */
8039 DEF_IMGLIB_FN (DGifCloseFile
);
8040 DEF_IMGLIB_FN (DGifSlurp
);
8041 DEF_IMGLIB_FN (DGifOpen
);
8042 DEF_IMGLIB_FN (DGifOpenFileName
);
8045 init_gif_functions (Lisp_Object libraries
)
8049 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
8052 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
8053 LOAD_IMGLIB_FN (library
, DGifSlurp
);
8054 LOAD_IMGLIB_FN (library
, DGifOpen
);
8055 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
8061 #define fn_DGifCloseFile DGifCloseFile
8062 #define fn_DGifSlurp DGifSlurp
8063 #define fn_DGifOpen DGifOpen
8064 #define fn_DGifOpenFileName DGifOpenFileName
8066 #endif /* HAVE_NTGUI */
8068 /* Reading a GIF image from memory
8069 Based on the PNG memory stuff to a certain extent. */
8073 unsigned char *bytes
;
8079 /* Make the current memory source available to gif_read_from_memory.
8080 It's done this way because not all versions of libungif support
8081 a UserData field in the GifFileType structure. */
8082 static gif_memory_source
*current_gif_memory_src
;
8085 gif_read_from_memory (file
, buf
, len
)
8090 gif_memory_source
*src
= current_gif_memory_src
;
8092 if (len
> src
->len
- src
->index
)
8095 bcopy (src
->bytes
+ src
->index
, buf
, len
);
8101 /* Load GIF image IMG for use on frame F. Value is non-zero if
8104 static int interlace_start
[] = {0, 4, 2, 1};
8105 static int interlace_increment
[] = {8, 8, 4, 2};
8112 Lisp_Object file
, specified_file
;
8113 Lisp_Object specified_data
;
8114 int rc
, width
, height
, x
, y
, i
;
8116 ColorMapObject
*gif_color_map
;
8117 unsigned long pixel_colors
[256];
8119 struct gcpro gcpro1
;
8121 int ino
, image_height
, image_width
;
8122 gif_memory_source memsrc
;
8123 unsigned char *raster
;
8125 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8126 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8130 if (NILP (specified_data
))
8132 file
= x_find_image_file (specified_file
);
8133 if (!STRINGP (file
))
8135 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8140 /* Open the GIF file. Casting return value avoids a GCC warning
8142 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
8145 image_error ("Cannot open `%s'", file
, Qnil
);
8152 /* Read from memory! */
8153 current_gif_memory_src
= &memsrc
;
8154 memsrc
.bytes
= SDATA (specified_data
);
8155 memsrc
.len
= SBYTES (specified_data
);
8158 /* Casting return value avoids a GCC warning on W32. */
8159 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
8162 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
8168 /* Before reading entire contents, check the declared image size. */
8169 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
8171 image_error ("Invalid image size", Qnil
, Qnil
);
8172 fn_DGifCloseFile (gif
);
8177 /* Read entire contents. */
8178 rc
= fn_DGifSlurp (gif
);
8179 if (rc
== GIF_ERROR
)
8181 image_error ("Error reading `%s'", img
->spec
, Qnil
);
8182 fn_DGifCloseFile (gif
);
8187 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8188 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8189 if (ino
>= gif
->ImageCount
)
8191 image_error ("Invalid image number `%s' in image `%s'",
8193 fn_DGifCloseFile (gif
);
8198 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
8199 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
8200 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
8201 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
8202 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
8203 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
8205 width
= img
->width
= max (gif
->SWidth
,
8206 max (gif
->Image
.Left
+ gif
->Image
.Width
,
8207 img
->corners
[RIGHT_CORNER
]));
8208 height
= img
->height
= max (gif
->SHeight
,
8209 max (gif
->Image
.Top
+ gif
->Image
.Height
,
8210 img
->corners
[BOT_CORNER
]));
8212 if (!check_image_size (f
, width
, height
))
8214 image_error ("Invalid image size", Qnil
, Qnil
);
8215 fn_DGifCloseFile (gif
);
8220 /* Create the X image and pixmap. */
8221 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8223 fn_DGifCloseFile (gif
);
8228 /* Allocate colors. */
8229 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
8231 gif_color_map
= gif
->SColorMap
;
8232 init_color_table ();
8233 bzero (pixel_colors
, sizeof pixel_colors
);
8236 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
8238 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
8239 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
8240 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
8241 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
8244 #ifdef COLOR_TABLE_SUPPORT
8245 img
->colors
= colors_in_color_table (&img
->ncolors
);
8246 free_color_table ();
8247 #endif /* COLOR_TABLE_SUPPORT */
8249 /* Clear the part of the screen image that are not covered by
8250 the image from the GIF file. Full animated GIF support
8251 requires more than can be done here (see the gif89 spec,
8252 disposal methods). Let's simply assume that the part
8253 not covered by a sub-image is in the frame's background color. */
8254 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
8255 for (x
= 0; x
< width
; ++x
)
8256 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8258 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
8259 for (x
= 0; x
< width
; ++x
)
8260 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8262 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
8264 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
8265 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8266 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
8267 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
8270 /* Read the GIF image into the X image. We use a local variable
8271 `raster' here because RasterBits below is a char *, and invites
8272 problems with bytes >= 0x80. */
8273 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
8275 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
8278 int row
= interlace_start
[0];
8282 for (y
= 0; y
< image_height
; y
++)
8284 if (row
>= image_height
)
8286 row
= interlace_start
[++pass
];
8287 while (row
>= image_height
)
8288 row
= interlace_start
[++pass
];
8291 for (x
= 0; x
< image_width
; x
++)
8293 int i
= raster
[(y
* image_width
) + x
];
8294 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8295 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8298 row
+= interlace_increment
[pass
];
8303 for (y
= 0; y
< image_height
; ++y
)
8304 for (x
= 0; x
< image_width
; ++x
)
8306 int i
= raster
[y
* image_width
+ x
];
8307 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
8308 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
8312 /* Save GIF image extension data for `image-extension-data'.
8313 Format is (count IMAGES FUNCTION "BYTES" ...). */
8314 img
->data
.lisp_val
= Qnil
;
8315 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
8317 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
8318 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
8319 /* Append (... FUNCTION "BYTES") */
8320 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
8321 Fcons (make_number (ext
->Function
),
8322 img
->data
.lisp_val
));
8323 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
8325 if (gif
->ImageCount
> 1)
8326 img
->data
.lisp_val
= Fcons (Qcount
,
8327 Fcons (make_number (gif
->ImageCount
),
8328 img
->data
.lisp_val
));
8330 fn_DGifCloseFile (gif
);
8332 /* Maybe fill in the background field while we have ximg handy. */
8333 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8334 /* Casting avoids a GCC warning. */
8335 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8337 /* Put the image into the pixmap, then free the X image and its buffer. */
8338 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8339 x_destroy_x_image (ximg
);
8345 #else /* !HAVE_GIF */
8353 #if USE_MAC_IMAGE_IO
8354 return image_load_image_io (f
, img
, kUTTypeGIF
);
8355 #else /* !USE_MAC_IMAGE_IO */
8356 Lisp_Object specified_file
, file
;
8357 Lisp_Object specified_data
;
8359 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8367 Lisp_Object specified_bg
;
8372 TimeScale time_scale
;
8373 TimeValue time
, duration
;
8378 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8379 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8381 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8384 if (NILP (specified_data
))
8386 /* Read from a file */
8390 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8394 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8399 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8400 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8404 if (!graphic_p
&& !movie_p
)
8406 if (prefer_graphic_p
)
8407 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8408 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8411 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8412 CloseMovieFile (refnum
);
8415 image_error ("Error reading `%s'", file
, Qnil
);
8421 /* Memory source! */
8423 long file_type_atom
[3];
8425 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8428 image_error ("Cannot allocate data handle for `%s'",
8433 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8434 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8435 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8436 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8439 err
= PtrAndHand ("\p", dref
, 1);
8441 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8444 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8447 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8448 &movie_p
, &prefer_graphic_p
, 0);
8452 if (!graphic_p
&& !movie_p
)
8454 if (prefer_graphic_p
)
8458 DisposeHandle (dref
);
8459 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8463 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8464 HandleDataHandlerSubType
);
8465 DisposeHandle (dref
);
8470 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8471 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8472 track
= GetMovieIndTrack (movie
, 1);
8473 media
= GetTrackMedia (track
);
8474 nsamples
= GetMediaSampleCount (media
);
8475 if (ino
>= nsamples
)
8477 image_error ("Invalid image number `%s' in image `%s'",
8481 time_scale
= GetMediaTimeScale (media
);
8483 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8484 if (!STRINGP (specified_bg
)
8485 || !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8487 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8488 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8489 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8490 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8492 GetMovieBox (movie
, &rect
);
8493 width
= img
->width
= rect
.right
- rect
.left
;
8494 height
= img
->height
= rect
.bottom
- rect
.top
;
8495 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8498 GetGWorld (&old_port
, &old_gdh
);
8499 SetGWorld (ximg
, NULL
);
8500 bg_color
.red
= color
.red
;
8501 bg_color
.green
= color
.green
;
8502 bg_color
.blue
= color
.blue
;
8503 RGBBackColor (&bg_color
);
8504 SetGWorld (old_port
, old_gdh
);
8505 SetMovieActive (movie
, 1);
8506 SetMovieGWorld (movie
, ximg
, NULL
);
8507 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8508 SetMovieTimeValue (movie
, time
);
8509 MoviesTask (movie
, 0L);
8510 DisposeTrackMedia (media
);
8511 DisposeMovieTrack (track
);
8512 DisposeMovie (movie
);
8516 /* Save GIF image extension data for `image-extension-data'.
8517 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8519 Lisp_Object gce
= make_uninit_string (4);
8520 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8522 /* Fill the delay time field. */
8523 SSET (gce
, 1, centisec
& 0xff);
8524 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8525 /* We don't know about other fields. */
8529 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8530 make_number (0xf9), gce
);
8533 /* Maybe fill in the background field while we have ximg handy. */
8534 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8535 IMAGE_BACKGROUND (img
, f
, ximg
);
8537 /* Put the image into the pixmap. */
8538 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8539 x_destroy_x_image (ximg
);
8543 image_error ("Cannot open `%s'", file
, Qnil
);
8546 DisposeTrackMedia (media
);
8548 DisposeMovieTrack (track
);
8550 DisposeMovie (movie
);
8554 #endif /* !USE_MAC_IMAGE_IO */
8558 #endif /* HAVE_GIF */
8562 /***********************************************************************
8564 ***********************************************************************/
8566 #if defined (HAVE_RSVG)
8568 /* Function prototypes. */
8570 static int svg_image_p
P_ ((Lisp_Object object
));
8571 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
8573 static int svg_load_image
P_ ((struct frame
*, struct image
*,
8574 unsigned char *, unsigned int));
8576 /* The symbol `svg' identifying images of this type. */
8580 /* Indices of image specification fields in svg_format, below. */
8582 enum svg_keyword_index
8597 /* Vector of image_keyword structures describing the format
8598 of valid user-defined image specifications. */
8600 static struct image_keyword svg_format
[SVG_LAST
] =
8602 {":type", IMAGE_SYMBOL_VALUE
, 1},
8603 {":data", IMAGE_STRING_VALUE
, 0},
8604 {":file", IMAGE_STRING_VALUE
, 0},
8605 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8606 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8607 {":relief", IMAGE_INTEGER_VALUE
, 0},
8608 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8609 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8610 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8611 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8614 /* Structure describing the image type `svg'. Its the same type of
8615 structure defined for all image formats, handled by emacs image
8616 functions. See struct image_type in dispextern.h. */
8618 static struct image_type svg_type
=
8620 /* An identifier showing that this is an image structure for the SVG format. */
8622 /* Handle to a function that can be used to identify a SVG file. */
8624 /* Handle to function used to load a SVG file. */
8626 /* Handle to function to free sresources for SVG. */
8628 /* An internal field to link to the next image type in a list of
8629 image types, will be filled in when registering the format. */
8634 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8635 this by calling parse_image_spec and supplying the keywords that
8636 identify the SVG format. */
8639 svg_image_p (object
)
8642 struct image_keyword fmt
[SVG_LAST
];
8643 bcopy (svg_format
, fmt
, sizeof fmt
);
8645 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
8648 /* Must specify either the :data or :file keyword. */
8649 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
8652 #include <librsvg/rsvg.h>
8656 /* SVG library functions. */
8657 DEF_IMGLIB_FN (rsvg_handle_new
);
8658 DEF_IMGLIB_FN (rsvg_handle_set_size_callback
);
8659 DEF_IMGLIB_FN (rsvg_handle_write
);
8660 DEF_IMGLIB_FN (rsvg_handle_close
);
8661 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
8662 DEF_IMGLIB_FN (rsvg_handle_free
);
8664 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
8665 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
8666 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
8667 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
8668 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
8669 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
8670 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
8671 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
8673 DEF_IMGLIB_FN (g_type_init
);
8674 DEF_IMGLIB_FN (g_object_unref
);
8675 DEF_IMGLIB_FN (g_error_free
);
8677 Lisp_Object Qgdk_pixbuf
, Qglib
;
8680 init_svg_functions (Lisp_Object libraries
)
8682 HMODULE library
, gdklib
, glib
;
8684 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
8685 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
8686 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
8689 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
8690 LOAD_IMGLIB_FN (library
, rsvg_handle_set_size_callback
);
8691 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
8692 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
8693 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
8694 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
8696 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
8697 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
8698 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
8699 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
8700 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
8701 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
8702 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
8703 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
8705 LOAD_IMGLIB_FN (glib
, g_type_init
);
8706 LOAD_IMGLIB_FN (glib
, g_object_unref
);
8707 LOAD_IMGLIB_FN (glib
, g_error_free
);
8712 /* The following aliases for library functions allow dynamic loading
8713 to be used on some platforms. */
8714 #define fn_rsvg_handle_new rsvg_handle_new
8715 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8716 #define fn_rsvg_handle_write rsvg_handle_write
8717 #define fn_rsvg_handle_close rsvg_handle_close
8718 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8719 #define fn_rsvg_handle_free rsvg_handle_free
8721 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8722 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8723 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8724 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8725 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8726 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8727 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8728 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8730 #define fn_g_type_init g_type_init
8731 #define fn_g_object_unref g_object_unref
8732 #define fn_g_error_free g_error_free
8733 #endif /* !HAVE_NTGUI */
8735 /* Load SVG image IMG for use on frame F. Value is non-zero if
8736 successful. this function will go into the svg_type structure, and
8737 the prototype thus needs to be compatible with that structure. */
8745 Lisp_Object file_name
;
8747 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8748 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8749 if (STRINGP (file_name
))
8752 unsigned char *contents
;
8754 struct gcpro gcpro1
;
8756 file
= x_find_image_file (file_name
);
8758 if (!STRINGP (file
))
8760 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
8765 /* Read the entire file into memory. */
8766 contents
= slurp_file (SDATA (file
), &size
);
8767 if (contents
== NULL
)
8769 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8773 /* If the file was slurped into memory properly, parse it. */
8774 success_p
= svg_load_image (f
, img
, contents
, size
);
8778 /* Else its not a file, its a lisp object. Load the image from a
8779 lisp object rather than a file. */
8784 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8785 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8791 /* svg_load_image is a helper function for svg_load, which does the
8792 actual loading given contents and size, apart from frame and image
8793 structures, passed from svg_load.
8795 Uses librsvg to do most of the image processing.
8797 Returns non-zero when successful. */
8799 svg_load_image (f
, img
, contents
, size
)
8800 /* Pointer to emacs frame structure. */
8802 /* Pointer to emacs image structure. */
8804 /* String containing the SVG XML data to be parsed. */
8805 unsigned char *contents
;
8806 /* Size of data in bytes. */
8809 RsvgHandle
*rsvg_handle
;
8810 GError
*error
= NULL
;
8814 const guint8
*pixels
;
8817 Lisp_Object specified_bg
;
8822 /* g_type_init is a glib function that must be called prior to using
8823 gnome type library functions. */
8825 /* Make a handle to a new rsvg object. */
8826 rsvg_handle
= fn_rsvg_handle_new ();
8828 /* Parse the contents argument and fill in the rsvg_handle. */
8829 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8833 /* The parsing is complete, rsvg_handle is ready to used, close it
8834 for further writes. */
8835 fn_rsvg_handle_close (rsvg_handle
, &error
);
8838 /* We can now get a valid pixel buffer from the svg file, if all
8840 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8843 /* Extract some meta data from the svg handle. */
8844 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8845 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8846 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8847 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8849 /* Validate the svg meta data. */
8850 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8851 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8852 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8853 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8855 /* Try to create a x pixmap to hold the svg pixmap. */
8856 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8858 fn_g_object_unref (pixbuf
);
8862 init_color_table ();
8864 /* Handle alpha channel by combining the image with a background
8866 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8867 if (STRINGP (specified_bg
)
8868 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8870 background
.red
>>= 8;
8871 background
.green
>>= 8;
8872 background
.blue
>>= 8;
8876 #ifdef HAVE_X_WINDOWS
8877 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8878 x_query_color (f
, &background
);
8880 /* SVG pixmaps specify transparency in the last byte, so right
8881 shift 8 bits to get rid of it, since emacs doesn't support
8883 background
.red
>>= 8;
8884 background
.green
>>= 8;
8885 background
.blue
>>= 8;
8886 #elif defined (MAC_OS)
8887 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8888 background
.red
= RED_FROM_ULONG (background
.pixel
);
8889 background
.green
= GREEN_FROM_ULONG (background
.pixel
);
8890 background
.blue
= BLUE_FROM_ULONG (background
.pixel
);
8891 #elif defined (HAVE_NTGUI)
8892 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8893 #if 0 /* W32 TODO : Colormap support. */
8894 x_query_color (f
, &background
);
8897 /* SVG pixmaps specify transparency in the last byte, so right
8898 shift 8 bits to get rid of it, since emacs doesn't support
8900 background
.red
>>= 8;
8901 background
.green
>>= 8;
8902 background
.blue
>>= 8;
8903 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8908 /* This loop handles opacity values, since Emacs assumes
8909 non-transparent images. Each pixel must be "flattened" by
8910 calculating the resulting color, given the transparency of the
8911 pixel, and the image background color. */
8912 for (y
= 0; y
< height
; ++y
)
8914 for (x
= 0; x
< width
; ++x
)
8924 opacity
= *pixels
++;
8926 red
= ((red
* opacity
)
8927 + (background
.red
* ((1 << 8) - opacity
)));
8928 green
= ((green
* opacity
)
8929 + (background
.green
* ((1 << 8) - opacity
)));
8930 blue
= ((blue
* opacity
)
8931 + (background
.blue
* ((1 << 8) - opacity
)));
8933 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8936 pixels
+= rowstride
- 4 * width
;
8939 #ifdef COLOR_TABLE_SUPPORT
8940 /* Remember colors allocated for this image. */
8941 img
->colors
= colors_in_color_table (&img
->ncolors
);
8942 free_color_table ();
8943 #endif /* COLOR_TABLE_SUPPORT */
8945 fn_g_object_unref (pixbuf
);
8948 img
->height
= height
;
8950 /* Maybe fill in the background field while we have ximg handy.
8951 Casting avoids a GCC warning. */
8952 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8954 /* Put the image into the pixmap, then free the X image and its
8956 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8957 x_destroy_x_image (ximg
);
8962 /* FIXME: Use error->message so the user knows what is the actual
8963 problem with the image. */
8964 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8965 fn_g_error_free (error
);
8969 #endif /* defined (HAVE_RSVG) */
8974 /***********************************************************************
8976 ***********************************************************************/
8978 #ifdef HAVE_X_WINDOWS
8979 #define HAVE_GHOSTSCRIPT 1
8980 #endif /* HAVE_X_WINDOWS */
8982 /* The symbol `postscript' identifying images of this type. */
8984 Lisp_Object Qpostscript
;
8986 #ifdef HAVE_GHOSTSCRIPT
8988 static int gs_image_p
P_ ((Lisp_Object object
));
8989 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8990 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8992 /* Keyword symbols. */
8994 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8996 /* Indices of image specification fields in gs_format, below. */
8998 enum gs_keyword_index
9016 /* Vector of image_keyword structures describing the format
9017 of valid user-defined image specifications. */
9019 static struct image_keyword gs_format
[GS_LAST
] =
9021 {":type", IMAGE_SYMBOL_VALUE
, 1},
9022 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9023 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
9024 {":file", IMAGE_STRING_VALUE
, 1},
9025 {":loader", IMAGE_FUNCTION_VALUE
, 0},
9026 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
9027 {":ascent", IMAGE_ASCENT_VALUE
, 0},
9028 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
9029 {":relief", IMAGE_INTEGER_VALUE
, 0},
9030 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9031 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9032 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
9033 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
9036 /* Structure describing the image type `ghostscript'. */
9038 static struct image_type gs_type
=
9048 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9051 gs_clear_image (f
, img
)
9055 /* IMG->data.ptr_val may contain a recorded colormap. */
9056 xfree (img
->data
.ptr_val
);
9057 x_clear_image (f
, img
);
9061 /* Return non-zero if OBJECT is a valid Ghostscript image
9068 struct image_keyword fmt
[GS_LAST
];
9072 bcopy (gs_format
, fmt
, sizeof fmt
);
9074 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
9077 /* Bounding box must be a list or vector containing 4 integers. */
9078 tem
= fmt
[GS_BOUNDING_BOX
].value
;
9081 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
9082 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
9087 else if (VECTORP (tem
))
9089 if (XVECTOR (tem
)->size
!= 4)
9091 for (i
= 0; i
< 4; ++i
)
9092 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
9102 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9111 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
9112 struct gcpro gcpro1
, gcpro2
;
9114 double in_width
, in_height
;
9115 Lisp_Object pixel_colors
= Qnil
;
9117 /* Compute pixel size of pixmap needed from the given size in the
9118 image specification. Sizes in the specification are in pt. 1 pt
9119 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9121 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
9122 in_width
= XFASTINT (pt_width
) / 72.0;
9123 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
9124 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
9125 in_height
= XFASTINT (pt_height
) / 72.0;
9126 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
9128 if (!check_image_size (f
, img
->width
, img
->height
))
9130 image_error ("Invalid image size", Qnil
, Qnil
);
9134 /* Create the pixmap. */
9135 xassert (img
->pixmap
== NO_PIXMAP
);
9137 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9139 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9140 img
->width
, img
->height
,
9141 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
9146 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
9150 /* Call the loader to fill the pixmap. It returns a process object
9151 if successful. We do not record_unwind_protect here because
9152 other places in redisplay like calling window scroll functions
9153 don't either. Let the Lisp loader use `unwind-protect' instead. */
9154 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
9156 sprintf (buffer
, "%lu %lu",
9157 (unsigned long) FRAME_X_WINDOW (f
),
9158 (unsigned long) img
->pixmap
);
9159 window_and_pixmap_id
= build_string (buffer
);
9161 sprintf (buffer
, "%lu %lu",
9162 FRAME_FOREGROUND_PIXEL (f
),
9163 FRAME_BACKGROUND_PIXEL (f
));
9164 pixel_colors
= build_string (buffer
);
9166 XSETFRAME (frame
, f
);
9167 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
9169 loader
= intern ("gs-load-image");
9171 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
9172 make_number (img
->width
),
9173 make_number (img
->height
),
9174 window_and_pixmap_id
,
9177 return PROCESSP (img
->data
.lisp_val
);
9181 /* Kill the Ghostscript process that was started to fill PIXMAP on
9182 frame F. Called from XTread_socket when receiving an event
9183 telling Emacs that Ghostscript has finished drawing. */
9186 x_kill_gs_process (pixmap
, f
)
9190 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
9194 /* Find the image containing PIXMAP. */
9195 for (i
= 0; i
< c
->used
; ++i
)
9196 if (c
->images
[i
]->pixmap
== pixmap
)
9199 /* Should someone in between have cleared the image cache, for
9200 instance, give up. */
9204 /* Kill the GS process. We should have found PIXMAP in the image
9205 cache and its image should contain a process object. */
9207 xassert (PROCESSP (img
->data
.lisp_val
));
9208 Fkill_process (img
->data
.lisp_val
, Qnil
);
9209 img
->data
.lisp_val
= Qnil
;
9211 #if defined (HAVE_X_WINDOWS)
9213 /* On displays with a mutable colormap, figure out the colors
9214 allocated for the image by looking at the pixels of an XImage for
9216 class = FRAME_X_VISUAL (f
)->class;
9217 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
9223 /* Try to get an XImage for img->pixmep. */
9224 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
9225 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
9230 /* Initialize the color table. */
9231 init_color_table ();
9233 /* For each pixel of the image, look its color up in the
9234 color table. After having done so, the color table will
9235 contain an entry for each color used by the image. */
9236 for (y
= 0; y
< img
->height
; ++y
)
9237 for (x
= 0; x
< img
->width
; ++x
)
9239 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
9240 lookup_pixel_color (f
, pixel
);
9243 /* Record colors in the image. Free color table and XImage. */
9244 #ifdef COLOR_TABLE_SUPPORT
9245 img
->colors
= colors_in_color_table (&img
->ncolors
);
9246 free_color_table ();
9248 XDestroyImage (ximg
);
9250 #if 0 /* This doesn't seem to be the case. If we free the colors
9251 here, we get a BadAccess later in x_clear_image when
9252 freeing the colors. */
9253 /* We have allocated colors once, but Ghostscript has also
9254 allocated colors on behalf of us. So, to get the
9255 reference counts right, free them once. */
9257 x_free_colors (f
, img
->colors
, img
->ncolors
);
9261 image_error ("Cannot get X image of `%s'; colors will not be freed",
9266 #endif /* HAVE_X_WINDOWS */
9268 /* Now that we have the pixmap, compute mask and transform the
9269 image if requested. */
9271 postprocess_image (f
, img
);
9275 #endif /* HAVE_GHOSTSCRIPT */
9278 /***********************************************************************
9280 ***********************************************************************/
9284 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
9285 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
9289 return valid_image_p (spec
) ? Qt
: Qnil
;
9293 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
9299 if (valid_image_p (spec
))
9300 id
= lookup_image (SELECTED_FRAME (), spec
);
9303 return make_number (id
);
9306 #endif /* GLYPH_DEBUG != 0 */
9309 /***********************************************************************
9311 ***********************************************************************/
9314 /* Image types that rely on external libraries are loaded dynamically
9315 if the library is available. */
9316 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9317 define_image_type (image_type, init_lib_fn (libraries))
9319 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9320 define_image_type (image_type, 1)
9321 #endif /* HAVE_NTGUI */
9323 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
9324 doc
: /* Initialize image library implementing image type TYPE.
9325 Return non-nil if TYPE is a supported image type.
9327 Image types pbm and xbm are prebuilt; other types are loaded here.
9328 Libraries to load are specified in alist LIBRARIES (usually, the value
9329 of `image-library-alist', which see). */)
9331 Lisp_Object type
, libraries
;
9335 /* Don't try to reload the library. */
9336 tested
= Fassq (type
, Vimage_type_cache
);
9338 return XCDR (tested
);
9340 #if defined (HAVE_XPM) || defined (MAC_OS)
9341 if (EQ (type
, Qxpm
))
9342 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
9345 #if defined (HAVE_JPEG) || defined (MAC_OS)
9346 if (EQ (type
, Qjpeg
))
9347 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
9350 #if defined (HAVE_TIFF) || defined (MAC_OS)
9351 if (EQ (type
, Qtiff
))
9352 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
9355 #if defined (HAVE_GIF) || defined (MAC_OS)
9356 if (EQ (type
, Qgif
))
9357 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
9360 #if defined (HAVE_PNG) || defined (MAC_OS)
9361 if (EQ (type
, Qpng
))
9362 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
9365 #if defined (HAVE_RSVG)
9366 if (EQ (type
, Qsvg
))
9367 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
9370 #ifdef HAVE_GHOSTSCRIPT
9371 if (EQ (type
, Qpostscript
))
9372 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
9375 /* If the type is not recognized, avoid testing it ever again. */
9376 CACHE_IMAGE_TYPE (type
, Qnil
);
9383 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
9385 /* Initialize this only once, since that's what we do with Vimage_types
9386 and they are supposed to be in sync. Initializing here gives correct
9387 operation on GNU/Linux of calling dump-emacs after loading some images. */
9390 /* Must be defined now becase we're going to update it below, while
9391 defining the supported image types. */
9392 DEFVAR_LISP ("image-types", &Vimage_types
,
9393 doc
: /* List of potentially supported image types.
9394 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9395 To check whether it is really supported, use `image-type-available-p'. */);
9396 Vimage_types
= Qnil
;
9398 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
9399 doc
: /* Alist of image types vs external libraries needed to display them.
9401 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9402 representing a supported image type, and the rest are strings giving
9403 alternate filenames for the corresponding external libraries.
9405 Emacs tries to load the libraries in the order they appear on the
9406 list; if none is loaded, the running session of Emacs won't
9407 support the image type. Types 'pbm and 'xbm don't need to be
9408 listed; they are always supported. */);
9409 Vimage_library_alist
= Qnil
;
9410 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
9412 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
9413 doc
: /* Maximum size of images.
9414 Emacs will not load an image into memory if its pixel width or
9415 pixel height exceeds this limit.
9417 If the value is an integer, it directly specifies the maximum
9418 image height and width, measured in pixels. If it is a floating
9419 point number, it specifies the maximum image height and width
9420 as a ratio to the frame height and width. If the value is
9421 non-numeric, there is no explicit limit on the size of images. */);
9422 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
9424 Vimage_type_cache
= Qnil
;
9425 staticpro (&Vimage_type_cache
);
9427 Qpbm
= intern ("pbm");
9429 ADD_IMAGE_TYPE (Qpbm
);
9431 Qxbm
= intern ("xbm");
9433 ADD_IMAGE_TYPE (Qxbm
);
9435 define_image_type (&xbm_type
, 1);
9436 define_image_type (&pbm_type
, 1);
9438 Qcount
= intern ("count");
9439 staticpro (&Qcount
);
9441 QCascent
= intern (":ascent");
9442 staticpro (&QCascent
);
9443 QCmargin
= intern (":margin");
9444 staticpro (&QCmargin
);
9445 QCrelief
= intern (":relief");
9446 staticpro (&QCrelief
);
9447 QCconversion
= intern (":conversion");
9448 staticpro (&QCconversion
);
9449 QCcolor_symbols
= intern (":color-symbols");
9450 staticpro (&QCcolor_symbols
);
9451 QCheuristic_mask
= intern (":heuristic-mask");
9452 staticpro (&QCheuristic_mask
);
9453 QCindex
= intern (":index");
9454 staticpro (&QCindex
);
9455 QCmatrix
= intern (":matrix");
9456 staticpro (&QCmatrix
);
9457 QCcolor_adjustment
= intern (":color-adjustment");
9458 staticpro (&QCcolor_adjustment
);
9459 QCmask
= intern (":mask");
9460 staticpro (&QCmask
);
9462 Qlaplace
= intern ("laplace");
9463 staticpro (&Qlaplace
);
9464 Qemboss
= intern ("emboss");
9465 staticpro (&Qemboss
);
9466 Qedge_detection
= intern ("edge-detection");
9467 staticpro (&Qedge_detection
);
9468 Qheuristic
= intern ("heuristic");
9469 staticpro (&Qheuristic
);
9471 Qpostscript
= intern ("postscript");
9472 staticpro (&Qpostscript
);
9473 #ifdef HAVE_GHOSTSCRIPT
9474 ADD_IMAGE_TYPE (Qpostscript
);
9475 QCloader
= intern (":loader");
9476 staticpro (&QCloader
);
9477 QCbounding_box
= intern (":bounding-box");
9478 staticpro (&QCbounding_box
);
9479 QCpt_width
= intern (":pt-width");
9480 staticpro (&QCpt_width
);
9481 QCpt_height
= intern (":pt-height");
9482 staticpro (&QCpt_height
);
9483 #endif /* HAVE_GHOSTSCRIPT */
9485 #if defined (HAVE_XPM) || defined (MAC_OS)
9486 Qxpm
= intern ("xpm");
9488 ADD_IMAGE_TYPE (Qxpm
);
9491 #if defined (HAVE_JPEG) || defined (MAC_OS)
9492 Qjpeg
= intern ("jpeg");
9494 ADD_IMAGE_TYPE (Qjpeg
);
9497 #if defined (HAVE_TIFF) || defined (MAC_OS)
9498 Qtiff
= intern ("tiff");
9500 ADD_IMAGE_TYPE (Qtiff
);
9503 #if defined (HAVE_GIF) || defined (MAC_OS)
9504 Qgif
= intern ("gif");
9506 ADD_IMAGE_TYPE (Qgif
);
9509 #if defined (HAVE_PNG) || defined (MAC_OS)
9510 Qpng
= intern ("png");
9512 ADD_IMAGE_TYPE (Qpng
);
9515 #if defined (HAVE_RSVG)
9516 Qsvg
= intern ("svg");
9518 ADD_IMAGE_TYPE (Qsvg
);
9520 Qgdk_pixbuf
= intern ("gdk-pixbuf");
9521 staticpro (&Qgdk_pixbuf
);
9522 Qglib
= intern ("glib");
9524 #endif /* HAVE_NTGUI */
9525 #endif /* HAVE_RSVG */
9527 defsubr (&Sinit_image_library
);
9528 defsubr (&Sclear_image_cache
);
9529 defsubr (&Simage_refresh
);
9530 defsubr (&Simage_size
);
9531 defsubr (&Simage_mask_p
);
9532 defsubr (&Simage_extension_data
);
9536 defsubr (&Slookup_image
);
9539 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9540 doc
: /* Non-nil means always draw a cross over disabled images.
9541 Disabled images are those having a `:conversion disabled' property.
9542 A cross is always drawn on black & white displays. */);
9543 cross_disabled_images
= 0;
9545 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9546 doc
: /* List of directories to search for window system bitmap files. */);
9547 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9549 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9550 doc
: /* Time after which cached images are removed from the cache.
9551 When an image has not been displayed this many seconds, remove it
9552 from the image cache. Value must be an integer or nil with nil
9553 meaning don't clear the cache. */);
9554 Vimage_cache_eviction_delay
= make_number (30 * 60);
9562 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9563 (do not change this comment) */