1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
32 /* This makes the fields of a Display accessible, in Xlib header files. */
34 #define XLIB_ILLEGAL_ACCESS
39 #include "dispextern.h"
40 #include "blockinput.h"
49 #include <sys/types.h>
52 #define COLOR_TABLE_SUPPORT 1
54 typedef struct x_bitmap_record Bitmap_Record
;
55 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
56 #define NO_PIXMAP None
58 #define RGB_PIXEL_COLOR unsigned long
60 #define PIX_MASK_RETAIN 0
61 #define PIX_MASK_DRAW 1
62 #endif /* HAVE_X_WINDOWS */
68 /* W32_TODO : Color tables on W32. */
69 #undef COLOR_TABLE_SUPPORT
71 typedef struct w32_bitmap_record Bitmap_Record
;
72 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
75 #define RGB_PIXEL_COLOR COLORREF
77 #define PIX_MASK_RETAIN 0
78 #define PIX_MASK_DRAW 1
80 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
81 #define x_defined_color w32_defined_color
82 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 #endif /* HAVE_NTGUI */
91 #include <sys/param.h>
93 #if TARGET_API_MAC_CARBON
95 #include <QuickTime/QuickTime.h>
96 #else /* not MAC_OSX */
97 #include <QuickTime.h>
98 #endif /* not MAC_OSX */
99 #else /* not TARGET_API_MAC_CARBON */
102 #include <TextUtils.h>
103 #include <ImageCompression.h>
104 #include <QuickTimeComponents.h>
105 #endif /* not TARGET_API_MAC_CARBON */
107 /* MAC_TODO : Color tables on Mac. */
108 #undef COLOR_TABLE_SUPPORT
110 #define ZPixmap 0 /* arbitrary */
111 typedef struct mac_bitmap_record Bitmap_Record
;
113 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
116 #define RGB_PIXEL_COLOR unsigned long
118 /* A black pixel in a mask bitmap/pixmap means ``draw a source
119 pixel''. A white pixel means ``retain the current pixel''. */
120 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
121 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
123 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
124 #define x_defined_color mac_defined_color
125 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
130 /* Search path for bitmap files. */
132 Lisp_Object Vx_bitmap_file_path
;
135 static void x_disable_image
P_ ((struct frame
*, struct image
*));
136 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
139 static void init_color_table
P_ ((void));
140 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
141 #ifdef COLOR_TABLE_SUPPORT
142 static void free_color_table
P_ ((void));
143 static unsigned long *colors_in_color_table
P_ ((int *n
));
144 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
147 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
148 id, which is just an int that this section returns. Bitmaps are
149 reference counted so they can be shared among frames.
151 Bitmap indices are guaranteed to be > 0, so a negative number can
152 be used to indicate no bitmap.
154 If you use x_create_bitmap_from_data, then you must keep track of
155 the bitmaps yourself. That is, creating a bitmap from the same
156 data more than once will not be caught. */
161 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
162 Display
*display
; /* not used */
164 int x
, y
; /* not used */
165 unsigned int width
, height
; /* not used */
166 unsigned long plane_mask
; /* not used */
167 int format
; /* not used */
170 xassert (x
== 0 && y
== 0);
173 SetRect (&ri
, 0, 0, width
, height
);
174 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
176 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
179 LockPixels (GetGWorldPixMap (pixmap
));
185 XPutPixel (ximage
, x
, y
, pixel
)
190 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
191 short depth
= GetPixDepth (pixmap
);
193 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
196 char *base_addr
= GetPixBaseAddr (pixmap
);
197 short row_bytes
= GetPixRowBytes (pixmap
);
199 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
205 char *base_addr
= GetPixBaseAddr (pixmap
);
206 short row_bytes
= GetPixRowBytes (pixmap
);
208 if (pixel
== PIX_MASK_DRAW
)
209 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
211 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
219 GetGWorld (&old_port
, &old_gdh
);
220 SetGWorld (ximage
, NULL
);
222 color
.red
= RED16_FROM_ULONG (pixel
);
223 color
.green
= GREEN16_FROM_ULONG (pixel
);
224 color
.blue
= BLUE16_FROM_ULONG (pixel
);
226 SetCPixel (x
, y
, &color
);
228 SetGWorld (old_port
, old_gdh
);
233 XGetPixel (ximage
, x
, y
)
237 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
238 short depth
= GetPixDepth (pixmap
);
240 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
243 char *base_addr
= GetPixBaseAddr (pixmap
);
244 short row_bytes
= GetPixRowBytes (pixmap
);
246 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
252 char *base_addr
= GetPixBaseAddr (pixmap
);
253 short row_bytes
= GetPixRowBytes (pixmap
);
255 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
256 return PIX_MASK_DRAW
;
258 return PIX_MASK_RETAIN
;
266 GetGWorld (&old_port
, &old_gdh
);
267 SetGWorld (ximage
, NULL
);
269 GetCPixel (x
, y
, &color
);
271 SetGWorld (old_port
, old_gdh
);
272 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
280 UnlockPixels (GetGWorldPixMap (ximg
));
285 mac_create_cg_image_from_image (f
, img
)
290 CGImageRef result
= NULL
;
297 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
298 img
->width
, img
->height
, 1);
305 GetGWorld (&old_port
, &old_gdh
);
306 SetGWorld (mask
, NULL
);
307 BackColor (blackColor
); /* Don't mask. */
308 SetRect (&r
, 0, 0, img
->width
, img
->height
);
310 SetGWorld (old_port
, old_gdh
);
315 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
316 GetGWorldPixMap (mask
), &result
);
317 if (mask
!= img
->mask
)
318 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
324 #endif /* USE_CG_DRAWING */
328 /* Functions to access the contents of a bitmap, given an id. */
331 x_bitmap_height (f
, id
)
335 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
339 x_bitmap_width (f
, id
)
343 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
346 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
348 x_bitmap_pixmap (f
, id
)
352 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
356 #ifdef HAVE_X_WINDOWS
358 x_bitmap_mask (f
, id
)
362 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
366 /* Allocate a new bitmap record. Returns index of new record. */
369 x_allocate_bitmap_record (f
)
372 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
375 if (dpyinfo
->bitmaps
== NULL
)
377 dpyinfo
->bitmaps_size
= 10;
379 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
380 dpyinfo
->bitmaps_last
= 1;
384 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
385 return ++dpyinfo
->bitmaps_last
;
387 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
388 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
391 dpyinfo
->bitmaps_size
*= 2;
393 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
394 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
395 return ++dpyinfo
->bitmaps_last
;
398 /* Add one reference to the reference count of the bitmap with id ID. */
401 x_reference_bitmap (f
, id
)
405 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
408 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
411 x_create_bitmap_from_data (f
, bits
, width
, height
)
414 unsigned int width
, height
;
416 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
419 #ifdef HAVE_X_WINDOWS
421 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
422 bits
, width
, height
);
425 #endif /* HAVE_X_WINDOWS */
429 bitmap
= CreateBitmap (width
, height
,
430 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
431 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
435 #endif /* HAVE_NTGUI */
438 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
443 id
= x_allocate_bitmap_record (f
);
445 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
446 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
449 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
450 dpyinfo
->bitmaps
[id
- 1].height
= height
;
451 dpyinfo
->bitmaps
[id
- 1].width
= width
;
452 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
454 #ifdef HAVE_X_WINDOWS
455 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
456 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
457 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
458 #endif /* HAVE_X_WINDOWS */
461 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
462 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
463 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
464 #endif /* HAVE_NTGUI */
469 /* Create bitmap from file FILE for frame F. */
472 x_create_bitmap_from_file (f
, file
)
477 return -1; /* MAC_TODO : bitmap support */
481 return -1; /* W32_TODO : bitmap support */
482 #endif /* HAVE_NTGUI */
484 #ifdef HAVE_X_WINDOWS
485 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
486 unsigned int width
, height
;
488 int xhot
, yhot
, result
, id
;
493 /* Look for an existing bitmap with the same name. */
494 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
496 if (dpyinfo
->bitmaps
[id
].refcount
497 && dpyinfo
->bitmaps
[id
].file
498 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
500 ++dpyinfo
->bitmaps
[id
].refcount
;
505 /* Search bitmap-file-path for the file, if appropriate. */
506 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
511 filename
= (char *) SDATA (found
);
513 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
514 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
515 if (result
!= BitmapSuccess
)
518 id
= x_allocate_bitmap_record (f
);
519 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
520 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
521 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
522 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
523 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
524 dpyinfo
->bitmaps
[id
- 1].height
= height
;
525 dpyinfo
->bitmaps
[id
- 1].width
= width
;
526 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
529 #endif /* HAVE_X_WINDOWS */
535 free_bitmap_record (dpyinfo
, bm
)
536 Display_Info
*dpyinfo
;
539 #ifdef HAVE_X_WINDOWS
540 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
542 XFreePixmap (dpyinfo
->display
, bm
->mask
);
543 #endif /* HAVE_X_WINDOWS */
546 DeleteObject (bm
->pixmap
);
547 #endif /* HAVE_NTGUI */
550 xfree (bm
->bitmap_data
); /* Added ++kfs */
551 bm
->bitmap_data
= NULL
;
561 /* Remove reference to bitmap with id number ID. */
564 x_destroy_bitmap (f
, id
)
568 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
572 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
574 if (--bm
->refcount
== 0)
577 free_bitmap_record (dpyinfo
, bm
);
583 /* Free all the bitmaps for the display specified by DPYINFO. */
586 x_destroy_all_bitmaps (dpyinfo
)
587 Display_Info
*dpyinfo
;
590 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
592 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
593 if (bm
->refcount
> 0)
594 free_bitmap_record (dpyinfo
, bm
);
596 dpyinfo
->bitmaps_last
= 0;
600 #ifdef HAVE_X_WINDOWS
602 /* Useful functions defined in the section
603 `Image type independent image structures' below. */
605 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
608 unsigned long height
));
610 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
611 int depth
, XImagePtr
*ximg
,
614 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
617 /* Create a mask of a bitmap. Note is this not a perfect mask.
618 It's nicer with some borders in this context */
621 x_create_bitmap_mask (f
, id
)
626 XImagePtr ximg
, mask_img
;
627 unsigned long width
, height
;
630 unsigned long x
, y
, xp
, xm
, yp
, ym
;
633 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
638 pixmap
= x_bitmap_pixmap (f
, id
);
639 width
= x_bitmap_width (f
, id
);
640 height
= x_bitmap_height (f
, id
);
643 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
652 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
657 XDestroyImage (ximg
);
661 bg
= four_corners_best (ximg
, NULL
, width
, height
);
663 for (y
= 0; y
< ximg
->height
; ++y
)
665 for (x
= 0; x
< ximg
->width
; ++x
)
667 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
668 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
669 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
670 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
671 if (XGetPixel (ximg
, x
, y
) == bg
672 && XGetPixel (ximg
, x
, yp
) == bg
673 && XGetPixel (ximg
, x
, ym
) == bg
674 && XGetPixel (ximg
, xp
, y
) == bg
675 && XGetPixel (ximg
, xp
, yp
) == bg
676 && XGetPixel (ximg
, xp
, ym
) == bg
677 && XGetPixel (ximg
, xm
, y
) == bg
678 && XGetPixel (ximg
, xm
, yp
) == bg
679 && XGetPixel (ximg
, xm
, ym
) == bg
)
680 XPutPixel (mask_img
, x
, y
, 0);
682 XPutPixel (mask_img
, x
, y
, 1);
686 xassert (interrupt_input_blocked
);
687 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
688 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
690 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
692 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
693 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
695 XDestroyImage (ximg
);
696 x_destroy_x_image (mask_img
);
701 #endif /* HAVE_X_WINDOWS */
704 /***********************************************************************
706 ***********************************************************************/
708 /* Value is the number of elements of vector VECTOR. */
710 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
712 /* List of supported image types. Use define_image_type to add new
713 types. Use lookup_image_type to find a type for a given symbol. */
715 static struct image_type
*image_types
;
717 /* A list of symbols, one for each supported image type. */
719 Lisp_Object Vimage_types
;
721 /* An alist of image types and libraries that implement the type. */
723 Lisp_Object Vimage_library_alist
;
725 /* Cache for delayed-loading image types. */
727 static Lisp_Object Vimage_type_cache
;
729 /* The symbol `xbm' which is used as the type symbol for XBM images. */
735 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
736 extern Lisp_Object QCdata
, QCtype
;
737 extern Lisp_Object Qcenter
;
738 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
739 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
740 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
744 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
746 /* Time in seconds after which images should be removed from the cache
749 Lisp_Object Vimage_cache_eviction_delay
;
751 /* Function prototypes. */
753 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
754 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
755 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
756 static void x_laplace
P_ ((struct frame
*, struct image
*));
757 static void x_emboss
P_ ((struct frame
*, struct image
*));
758 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
761 #define CACHE_IMAGE_TYPE(type, status) \
762 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
764 #define ADD_IMAGE_TYPE(type) \
765 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
767 /* Define a new image type from TYPE. This adds a copy of TYPE to
768 image_types and caches the loading status of TYPE. */
771 define_image_type (type
, loaded
)
772 struct image_type
*type
;
781 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
782 The initialized data segment is read-only. */
783 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
784 bcopy (type
, p
, sizeof *p
);
785 p
->next
= image_types
;
790 CACHE_IMAGE_TYPE (*type
->type
, success
);
795 /* Look up image type SYMBOL, and return a pointer to its image_type
796 structure. Value is null if SYMBOL is not a known image type. */
798 static INLINE
struct image_type
*
799 lookup_image_type (symbol
)
802 struct image_type
*type
;
804 /* We must initialize the image-type if it hasn't been already. */
805 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
806 return 0; /* unimplemented */
808 for (type
= image_types
; type
; type
= type
->next
)
809 if (EQ (symbol
, *type
->type
))
816 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
817 valid image specification is a list whose car is the symbol
818 `image', and whose rest is a property list. The property list must
819 contain a value for key `:type'. That value must be the name of a
820 supported image type. The rest of the property list depends on the
824 valid_image_p (object
)
833 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
834 if (EQ (XCAR (tem
), QCtype
))
837 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
839 struct image_type
*type
;
840 type
= lookup_image_type (XCAR (tem
));
842 valid_p
= type
->valid_p (object
);
853 /* Log error message with format string FORMAT and argument ARG.
854 Signaling an error, e.g. when an image cannot be loaded, is not a
855 good idea because this would interrupt redisplay, and the error
856 message display would lead to another redisplay. This function
857 therefore simply displays a message. */
860 image_error (format
, arg1
, arg2
)
862 Lisp_Object arg1
, arg2
;
864 add_to_log (format
, arg1
, arg2
);
869 /***********************************************************************
871 ***********************************************************************/
873 enum image_value_type
875 IMAGE_DONT_CHECK_VALUE_TYPE
,
877 IMAGE_STRING_OR_NIL_VALUE
,
879 IMAGE_POSITIVE_INTEGER_VALUE
,
880 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
881 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
884 IMAGE_FUNCTION_VALUE
,
889 /* Structure used when parsing image specifications. */
893 /* Name of keyword. */
896 /* The type of value allowed. */
897 enum image_value_type type
;
899 /* Non-zero means key must be present. */
902 /* Used to recognize duplicate keywords in a property list. */
905 /* The value that was found. */
910 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
912 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
915 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
916 has the format (image KEYWORD VALUE ...). One of the keyword/
917 value pairs must be `:type TYPE'. KEYWORDS is a vector of
918 image_keywords structures of size NKEYWORDS describing other
919 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
922 parse_image_spec (spec
, keywords
, nkeywords
, type
)
924 struct image_keyword
*keywords
;
935 while (CONSP (plist
))
937 Lisp_Object key
, value
;
939 /* First element of a pair must be a symbol. */
941 plist
= XCDR (plist
);
945 /* There must follow a value. */
948 value
= XCAR (plist
);
949 plist
= XCDR (plist
);
951 /* Find key in KEYWORDS. Error if not found. */
952 for (i
= 0; i
< nkeywords
; ++i
)
953 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
959 /* Record that we recognized the keyword. If a keywords
960 was found more than once, it's an error. */
961 keywords
[i
].value
= value
;
964 if (keywords
[i
].count
> 1)
967 /* Check type of value against allowed type. */
968 switch (keywords
[i
].type
)
970 case IMAGE_STRING_VALUE
:
971 if (!STRINGP (value
))
975 case IMAGE_STRING_OR_NIL_VALUE
:
976 if (!STRINGP (value
) && !NILP (value
))
980 case IMAGE_SYMBOL_VALUE
:
981 if (!SYMBOLP (value
))
985 case IMAGE_POSITIVE_INTEGER_VALUE
:
986 if (!INTEGERP (value
) || XINT (value
) <= 0)
990 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
991 if (INTEGERP (value
) && XINT (value
) >= 0)
994 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
995 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
999 case IMAGE_ASCENT_VALUE
:
1000 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1002 else if (INTEGERP (value
)
1003 && XINT (value
) >= 0
1004 && XINT (value
) <= 100)
1008 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1009 if (!INTEGERP (value
) || XINT (value
) < 0)
1013 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1016 case IMAGE_FUNCTION_VALUE
:
1017 value
= indirect_function (value
);
1019 || COMPILEDP (value
)
1020 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1024 case IMAGE_NUMBER_VALUE
:
1025 if (!INTEGERP (value
) && !FLOATP (value
))
1029 case IMAGE_INTEGER_VALUE
:
1030 if (!INTEGERP (value
))
1034 case IMAGE_BOOL_VALUE
:
1035 if (!NILP (value
) && !EQ (value
, Qt
))
1044 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1048 /* Check that all mandatory fields are present. */
1049 for (i
= 0; i
< nkeywords
; ++i
)
1050 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1053 return NILP (plist
);
1057 /* Return the value of KEY in image specification SPEC. Value is nil
1058 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1059 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1062 image_spec_value (spec
, key
, found
)
1063 Lisp_Object spec
, key
;
1068 xassert (valid_image_p (spec
));
1070 for (tail
= XCDR (spec
);
1071 CONSP (tail
) && CONSP (XCDR (tail
));
1072 tail
= XCDR (XCDR (tail
)))
1074 if (EQ (XCAR (tail
), key
))
1078 return XCAR (XCDR (tail
));
1088 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1089 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1090 PIXELS non-nil means return the size in pixels, otherwise return the
1091 size in canonical character units.
1092 FRAME is the frame on which the image will be displayed. FRAME nil
1093 or omitted means use the selected frame. */)
1094 (spec
, pixels
, frame
)
1095 Lisp_Object spec
, pixels
, frame
;
1100 if (valid_image_p (spec
))
1102 struct frame
*f
= check_x_frame (frame
);
1103 int id
= lookup_image (f
, spec
);
1104 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1105 int width
= img
->width
+ 2 * img
->hmargin
;
1106 int height
= img
->height
+ 2 * img
->vmargin
;
1109 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1110 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1112 size
= Fcons (make_number (width
), make_number (height
));
1115 error ("Invalid image specification");
1121 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1122 doc
: /* Return t if image SPEC has a mask bitmap.
1123 FRAME is the frame on which the image will be displayed. FRAME nil
1124 or omitted means use the selected frame. */)
1126 Lisp_Object spec
, frame
;
1131 if (valid_image_p (spec
))
1133 struct frame
*f
= check_x_frame (frame
);
1134 int id
= lookup_image (f
, spec
);
1135 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1140 error ("Invalid image specification");
1145 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1146 doc
: /* Return extension data for image SPEC.
1147 FRAME is the frame on which the image will be displayed. FRAME nil
1148 or omitted means use the selected frame. */)
1150 Lisp_Object spec
, frame
;
1155 if (valid_image_p (spec
))
1157 struct frame
*f
= check_x_frame (frame
);
1158 int id
= lookup_image (f
, spec
);
1159 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1160 ext
= img
->data
.lisp_val
;
1167 /***********************************************************************
1168 Image type independent image structures
1169 ***********************************************************************/
1171 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1172 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1173 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1175 #define MAX_IMAGE_SIZE 6.0
1176 Lisp_Object Vmax_image_size
;
1178 /* Allocate and return a new image structure for image specification
1179 SPEC. SPEC has a hash value of HASH. */
1181 static struct image
*
1182 make_image (spec
, hash
)
1186 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1188 xassert (valid_image_p (spec
));
1189 bzero (img
, sizeof *img
);
1190 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1191 xassert (img
->type
!= NULL
);
1193 img
->data
.lisp_val
= Qnil
;
1194 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1196 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1201 /* Free image IMG which was used on frame F, including its resources. */
1210 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1212 /* Remove IMG from the hash table of its cache. */
1214 img
->prev
->next
= img
->next
;
1216 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1219 img
->next
->prev
= img
->prev
;
1221 c
->images
[img
->id
] = NULL
;
1223 /* Free resources, then free IMG. */
1224 img
->type
->free (f
, img
);
1229 /* Return 1 if the given widths and heights are valid for display;
1230 otherwise, return 0. */
1233 check_image_size (f
, width
, height
)
1240 if (width
<= 0 || height
<= 0)
1243 if (INTEGERP (Vmax_image_size
))
1244 w
= h
= XINT (Vmax_image_size
);
1245 else if (FLOATP (Vmax_image_size
))
1249 w
= FRAME_PIXEL_WIDTH (f
);
1250 h
= FRAME_PIXEL_HEIGHT (f
);
1253 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1254 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1255 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1260 return (width
<= w
&& height
<= h
);
1263 /* Prepare image IMG for display on frame F. Must be called before
1264 drawing an image. */
1267 prepare_image_for_display (f
, img
)
1273 /* We're about to display IMG, so set its timestamp to `now'. */
1275 img
->timestamp
= EMACS_SECS (t
);
1277 /* If IMG doesn't have a pixmap yet, load it now, using the image
1278 type dependent loader function. */
1279 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1280 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1282 #if defined (MAC_OS) && USE_CG_DRAWING
1283 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1285 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1286 if (img
->data
.ptr_val
== NULL
)
1288 img
->load_failed_p
= 1;
1289 img
->type
->free (f
, img
);
1296 /* Value is the number of pixels for the ascent of image IMG when
1297 drawn in face FACE. */
1300 image_ascent (img
, face
, slice
)
1303 struct glyph_slice
*slice
;
1308 if (slice
->height
== img
->height
)
1309 height
= img
->height
+ img
->vmargin
;
1310 else if (slice
->y
== 0)
1311 height
= slice
->height
+ img
->vmargin
;
1313 height
= slice
->height
;
1315 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1320 /* W32 specific version. Why?. ++kfs */
1321 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1322 - FONT_BASE (face
->font
)) / 2;
1324 /* This expression is arranged so that if the image can't be
1325 exactly centered, it will be moved slightly up. This is
1326 because a typical font is `top-heavy' (due to the presence
1327 uppercase letters), so the image placement should err towards
1328 being top-heavy too. It also just generally looks better. */
1329 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1330 #endif /* HAVE_NTGUI */
1333 ascent
= height
/ 2;
1336 ascent
= (int) (height
* img
->ascent
/ 100.0);
1342 /* Image background colors. */
1344 /* Find the "best" corner color of a bitmap.
1345 On W32, XIMG is assumed to a device context with the bitmap selected. */
1347 static RGB_PIXEL_COLOR
1348 four_corners_best (ximg
, corners
, width
, height
)
1349 XImagePtr_or_DC ximg
;
1351 unsigned long width
, height
;
1353 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1356 if (corners
&& corners
[BOT_CORNER
] >= 0)
1358 /* Get the colors at the corner_pixels of ximg. */
1359 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1360 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1361 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1362 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1366 /* Get the colors at the corner_pixels of ximg. */
1367 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1368 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1369 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1370 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1372 /* Choose the most frequently found color as background. */
1373 for (i
= best_count
= 0; i
< 4; ++i
)
1377 for (j
= n
= 0; j
< 4; ++j
)
1378 if (corner_pixels
[i
] == corner_pixels
[j
])
1382 best
= corner_pixels
[i
], best_count
= n
;
1388 /* Portability macros */
1392 #define Destroy_Image(img_dc, prev) \
1393 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1395 #define Free_Pixmap(display, pixmap) \
1396 DeleteObject (pixmap)
1400 #define Destroy_Image(ximg, dummy) \
1401 XDestroyImage (ximg)
1403 #define Free_Pixmap(display, pixmap) \
1404 XFreePixmap (display, pixmap)
1406 #endif /* HAVE_NTGUI */
1409 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1410 it is guessed heuristically. If non-zero, XIMG is an existing
1411 XImage object (or device context with the image selected on W32) to
1412 use for the heuristic. */
1415 image_background (img
, f
, ximg
)
1418 XImagePtr_or_DC ximg
;
1420 if (! img
->background_valid
)
1421 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1423 int free_ximg
= !ximg
;
1426 #endif /* HAVE_NTGUI */
1431 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1432 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1434 HDC frame_dc
= get_frame_dc (f
);
1435 ximg
= CreateCompatibleDC (frame_dc
);
1436 release_frame_dc (f
, frame_dc
);
1437 prev
= SelectObject (ximg
, img
->pixmap
);
1438 #endif /* !HAVE_NTGUI */
1441 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1444 Destroy_Image (ximg
, prev
);
1446 img
->background_valid
= 1;
1449 return img
->background
;
1452 /* Return the `background_transparent' field of IMG. If IMG doesn't
1453 have one yet, it is guessed heuristically. If non-zero, MASK is an
1454 existing XImage object to use for the heuristic. */
1457 image_background_transparent (img
, f
, mask
)
1460 XImagePtr_or_DC mask
;
1462 if (! img
->background_transparent_valid
)
1463 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1467 int free_mask
= !mask
;
1470 #endif /* HAVE_NTGUI */
1475 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1476 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1478 HDC frame_dc
= get_frame_dc (f
);
1479 mask
= CreateCompatibleDC (frame_dc
);
1480 release_frame_dc (f
, frame_dc
);
1481 prev
= SelectObject (mask
, img
->mask
);
1482 #endif /* HAVE_NTGUI */
1485 img
->background_transparent
1486 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1489 Destroy_Image (mask
, prev
);
1492 img
->background_transparent
= 0;
1494 img
->background_transparent_valid
= 1;
1497 return img
->background_transparent
;
1501 /***********************************************************************
1502 Helper functions for X image types
1503 ***********************************************************************/
1505 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1507 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1508 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1510 Lisp_Object color_name
,
1511 unsigned long dflt
));
1514 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1515 free the pixmap if any. MASK_P non-zero means clear the mask
1516 pixmap if any. COLORS_P non-zero means free colors allocated for
1517 the image, if any. */
1520 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1523 int pixmap_p
, mask_p
, colors_p
;
1525 if (pixmap_p
&& img
->pixmap
)
1527 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1528 img
->pixmap
= NO_PIXMAP
;
1529 img
->background_valid
= 0;
1532 if (mask_p
&& img
->mask
)
1534 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1535 img
->mask
= NO_PIXMAP
;
1536 img
->background_transparent_valid
= 0;
1539 if (colors_p
&& img
->ncolors
)
1541 /* MAC_TODO: color table support. */
1542 /* W32_TODO: color table support. */
1543 #ifdef HAVE_X_WINDOWS
1544 x_free_colors (f
, img
->colors
, img
->ncolors
);
1545 #endif /* HAVE_X_WINDOWS */
1546 xfree (img
->colors
);
1551 #if defined (MAC_OS) && USE_CG_DRAWING
1552 if (img
->data
.ptr_val
)
1554 CGImageRelease (img
->data
.ptr_val
);
1555 img
->data
.ptr_val
= NULL
;
1560 /* Free X resources of image IMG which is used on frame F. */
1563 x_clear_image (f
, img
)
1568 x_clear_image_1 (f
, img
, 1, 1, 1);
1573 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1574 cannot be allocated, use DFLT. Add a newly allocated color to
1575 IMG->colors, so that it can be freed again. Value is the pixel
1578 static unsigned long
1579 x_alloc_image_color (f
, img
, color_name
, dflt
)
1582 Lisp_Object color_name
;
1586 unsigned long result
;
1588 xassert (STRINGP (color_name
));
1590 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1592 /* This isn't called frequently so we get away with simply
1593 reallocating the color vector to the needed size, here. */
1596 (unsigned long *) xrealloc (img
->colors
,
1597 img
->ncolors
* sizeof *img
->colors
);
1598 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1599 result
= color
.pixel
;
1609 /***********************************************************************
1611 ***********************************************************************/
1613 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1614 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1615 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1617 /* Return a new, initialized image cache that is allocated from the
1618 heap. Call free_image_cache to free an image cache. */
1620 struct image_cache
*
1623 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1626 bzero (c
, sizeof *c
);
1628 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1629 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1630 c
->buckets
= (struct image
**) xmalloc (size
);
1631 bzero (c
->buckets
, size
);
1636 /* Find an image matching SPEC in the cache, and return it. If no
1637 image is found, return NULL. */
1638 static struct image
*
1639 search_image_cache (f
, spec
, hash
)
1645 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1646 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1648 if (!c
) return NULL
;
1650 /* If the image spec does not specify a background color, the cached
1651 image must have the same background color as the current frame.
1652 The foreground color must also match, for the sake of monochrome
1655 In fact, we could ignore the foreground color matching condition
1656 for color images, or if the image spec specifies :foreground;
1657 similarly we could ignore the background color matching condition
1658 for formats that don't use transparency (such as jpeg), or if the
1659 image spec specifies :background. However, the extra memory
1660 usage is probably negligible in practice, so we don't bother. */
1662 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1663 if (img
->hash
== hash
1664 && !NILP (Fequal (img
->spec
, spec
))
1665 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1666 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1672 /* Search frame F for an image with spec SPEC, and free it. */
1675 uncache_image (f
, spec
)
1679 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1681 free_image (f
, img
);
1685 /* Free image cache of frame F. Be aware that X frames share images
1689 free_image_cache (f
)
1692 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1697 /* Cache should not be referenced by any frame when freed. */
1698 xassert (c
->refcount
== 0);
1700 for (i
= 0; i
< c
->used
; ++i
)
1701 free_image (f
, c
->images
[i
]);
1705 FRAME_IMAGE_CACHE (f
) = NULL
;
1710 /* Clear image cache of frame F. FORCE_P non-zero means free all
1711 images. FORCE_P zero means clear only images that haven't been
1712 displayed for some time. Should be called from time to time to
1713 reduce the number of loaded images. If image-cache-eviction-delay
1714 is non-nil, this frees images in the cache which weren't displayed
1715 for at least that many seconds. */
1718 clear_image_cache (f
, force_p
)
1722 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1724 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1731 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1733 /* Block input so that we won't be interrupted by a SIGIO
1734 while being in an inconsistent state. */
1737 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1739 struct image
*img
= c
->images
[i
];
1741 && (force_p
|| img
->timestamp
< old
))
1743 free_image (f
, img
);
1748 /* We may be clearing the image cache because, for example,
1749 Emacs was iconified for a longer period of time. In that
1750 case, current matrices may still contain references to
1751 images freed above. So, clear these matrices. */
1754 Lisp_Object tail
, frame
;
1756 FOR_EACH_FRAME (tail
, frame
)
1758 struct frame
*f
= XFRAME (frame
);
1759 if (FRAME_IMAGE_CACHE (f
) == c
)
1760 clear_current_matrices (f
);
1763 ++windows_or_buffers_changed
;
1771 clear_image_caches (int force_p
)
1773 /* FIXME: We want to do
1774 * struct terminal *t;
1775 * for (t = terminal_list; t; t = t->next_terminal)
1776 * clear_image_cache (t, filter); */
1777 Lisp_Object tail
, frame
;
1778 FOR_EACH_FRAME (tail
, frame
)
1779 if (FRAME_WINDOW_P (XFRAME (frame
)))
1780 clear_image_cache (XFRAME (frame
), force_p
);
1783 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1785 doc
: /* Clear the image cache of FRAME.
1786 FRAME nil or omitted means use the selected frame.
1787 FRAME t means clear the image caches of all frames. */)
1792 clear_image_caches (1);
1794 clear_image_cache (check_x_frame (frame
), 1);
1800 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1802 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1803 If SPEC specifies an image file, the displayed image is updated with
1804 the current contents of that file.
1805 FRAME nil or omitted means use the selected frame.
1806 FRAME t means refresh the image on all frames. */)
1808 Lisp_Object spec
, frame
;
1810 if (!valid_image_p (spec
))
1811 error ("Invalid image specification");
1816 FOR_EACH_FRAME (tail
, frame
)
1818 struct frame
*f
= XFRAME (frame
);
1819 if (FRAME_WINDOW_P (f
))
1820 uncache_image (f
, spec
);
1824 uncache_image (check_x_frame (frame
), spec
);
1830 /* Compute masks and transform image IMG on frame F, as specified
1831 by the image's specification, */
1834 postprocess_image (f
, img
)
1838 /* Manipulation of the image's mask. */
1841 Lisp_Object conversion
, spec
;
1846 /* `:heuristic-mask t'
1848 means build a mask heuristically.
1849 `:heuristic-mask (R G B)'
1850 `:mask (heuristic (R G B))'
1851 means build a mask from color (R G B) in the
1854 means remove a mask, if any. */
1856 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1858 x_build_heuristic_mask (f
, img
, mask
);
1863 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1865 if (EQ (mask
, Qheuristic
))
1866 x_build_heuristic_mask (f
, img
, Qt
);
1867 else if (CONSP (mask
)
1868 && EQ (XCAR (mask
), Qheuristic
))
1870 if (CONSP (XCDR (mask
)))
1871 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1873 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1875 else if (NILP (mask
) && found_p
&& img
->mask
)
1877 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1878 img
->mask
= NO_PIXMAP
;
1883 /* Should we apply an image transformation algorithm? */
1884 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1885 if (EQ (conversion
, Qdisabled
))
1886 x_disable_image (f
, img
);
1887 else if (EQ (conversion
, Qlaplace
))
1889 else if (EQ (conversion
, Qemboss
))
1891 else if (CONSP (conversion
)
1892 && EQ (XCAR (conversion
), Qedge_detection
))
1895 tem
= XCDR (conversion
);
1897 x_edge_detection (f
, img
,
1898 Fplist_get (tem
, QCmatrix
),
1899 Fplist_get (tem
, QCcolor_adjustment
));
1905 /* Return the id of image with Lisp specification SPEC on frame F.
1906 SPEC must be a valid Lisp image specification (see valid_image_p). */
1909 lookup_image (f
, spec
)
1913 struct image_cache
*c
;
1916 struct gcpro gcpro1
;
1919 /* F must be a window-system frame, and SPEC must be a valid image
1921 xassert (FRAME_WINDOW_P (f
));
1922 xassert (valid_image_p (spec
));
1924 c
= FRAME_IMAGE_CACHE (f
);
1928 /* Look up SPEC in the hash table of the image cache. */
1929 hash
= sxhash (spec
, 0);
1930 img
= search_image_cache (f
, spec
, hash
);
1931 if (img
&& img
->load_failed_p
)
1933 free_image (f
, img
);
1937 /* If not found, create a new image and cache it. */
1940 extern Lisp_Object Qpostscript
;
1943 img
= make_image (spec
, hash
);
1944 cache_image (f
, img
);
1945 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1946 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
1947 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
1949 /* If we can't load the image, and we don't have a width and
1950 height, use some arbitrary width and height so that we can
1951 draw a rectangle for it. */
1952 if (img
->load_failed_p
)
1956 value
= image_spec_value (spec
, QCwidth
, NULL
);
1957 img
->width
= (INTEGERP (value
)
1958 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1959 value
= image_spec_value (spec
, QCheight
, NULL
);
1960 img
->height
= (INTEGERP (value
)
1961 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1965 /* Handle image type independent image attributes
1966 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1967 `:background COLOR'. */
1968 Lisp_Object ascent
, margin
, relief
, bg
;
1970 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1971 if (INTEGERP (ascent
))
1972 img
->ascent
= XFASTINT (ascent
);
1973 else if (EQ (ascent
, Qcenter
))
1974 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1976 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1977 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1978 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1979 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1980 && INTEGERP (XCDR (margin
)))
1982 if (XINT (XCAR (margin
)) > 0)
1983 img
->hmargin
= XFASTINT (XCAR (margin
));
1984 if (XINT (XCDR (margin
)) > 0)
1985 img
->vmargin
= XFASTINT (XCDR (margin
));
1988 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1989 if (INTEGERP (relief
))
1991 img
->relief
= XINT (relief
);
1992 img
->hmargin
+= eabs (img
->relief
);
1993 img
->vmargin
+= eabs (img
->relief
);
1996 if (! img
->background_valid
)
1998 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2002 = x_alloc_image_color (f
, img
, bg
,
2003 FRAME_BACKGROUND_PIXEL (f
));
2004 img
->background_valid
= 1;
2008 /* Do image transformations and compute masks, unless we
2009 don't have the image yet. */
2010 if (!EQ (*img
->type
->type
, Qpostscript
))
2011 postprocess_image (f
, img
);
2017 /* We're using IMG, so set its timestamp to `now'. */
2018 EMACS_GET_TIME (now
);
2019 img
->timestamp
= EMACS_SECS (now
);
2023 /* Value is the image id. */
2028 /* Cache image IMG in the image cache of frame F. */
2031 cache_image (f
, img
)
2035 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2038 /* Find a free slot in c->images. */
2039 for (i
= 0; i
< c
->used
; ++i
)
2040 if (c
->images
[i
] == NULL
)
2043 /* If no free slot found, maybe enlarge c->images. */
2044 if (i
== c
->used
&& c
->used
== c
->size
)
2047 c
->images
= (struct image
**) xrealloc (c
->images
,
2048 c
->size
* sizeof *c
->images
);
2051 /* Add IMG to c->images, and assign IMG an id. */
2057 /* Add IMG to the cache's hash table. */
2058 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2059 img
->next
= c
->buckets
[i
];
2061 img
->next
->prev
= img
;
2063 c
->buckets
[i
] = img
;
2067 /* Call FN on every image in the image cache of frame F. Used to mark
2068 Lisp Objects in the image cache. */
2070 /* Mark Lisp objects in image IMG. */
2076 mark_object (img
->spec
);
2078 if (!NILP (img
->data
.lisp_val
))
2079 mark_object (img
->data
.lisp_val
);
2084 mark_image_cache (struct image_cache
*c
)
2089 for (i
= 0; i
< c
->used
; ++i
)
2091 mark_image (c
->images
[i
]);
2097 /***********************************************************************
2098 X / MAC / W32 support code
2099 ***********************************************************************/
2103 /* Macro for defining functions that will be loaded from image DLLs. */
2104 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2106 /* Macro for loading those image functions from the library. */
2107 #define LOAD_IMGLIB_FN(lib,func) { \
2108 fn_##func = (void *) GetProcAddress (lib, #func); \
2109 if (!fn_##func) return 0; \
2112 /* Load a DLL implementing an image type.
2113 The `image-library-alist' variable associates a symbol,
2114 identifying an image type, to a list of possible filenames.
2115 The function returns NULL if no library could be loaded for
2116 the given image type, or if the library was previously loaded;
2117 else the handle of the DLL. */
2119 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2121 HMODULE library
= NULL
;
2123 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2125 Lisp_Object dlls
= Fassq (type
, libraries
);
2128 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2130 CHECK_STRING_CAR (dlls
);
2131 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2139 #endif /* HAVE_NTGUI */
2141 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2142 XImagePtr
*, Pixmap
*));
2143 static void x_destroy_x_image
P_ ((XImagePtr
));
2144 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2147 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2148 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2149 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2150 via xmalloc. Print error messages via image_error if an error
2151 occurs. Value is non-zero if successful.
2153 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2154 should indicate the bit depth of the image. */
2157 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2159 int width
, height
, depth
;
2163 #ifdef HAVE_X_WINDOWS
2164 Display
*display
= FRAME_X_DISPLAY (f
);
2165 Window window
= FRAME_X_WINDOW (f
);
2166 Screen
*screen
= FRAME_X_SCREEN (f
);
2168 xassert (interrupt_input_blocked
);
2171 depth
= DefaultDepthOfScreen (screen
);
2172 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2173 depth
, ZPixmap
, 0, NULL
, width
, height
,
2174 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2177 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2181 /* Allocate image raster. */
2182 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2184 /* Allocate a pixmap of the same size. */
2185 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2186 if (*pixmap
== NO_PIXMAP
)
2188 x_destroy_x_image (*ximg
);
2190 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2195 #endif /* HAVE_X_WINDOWS */
2199 BITMAPINFOHEADER
*header
;
2201 int scanline_width_bits
;
2203 int palette_colors
= 0;
2208 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2209 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2211 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2215 scanline_width_bits
= width
* depth
;
2216 remainder
= scanline_width_bits
% 32;
2219 scanline_width_bits
+= 32 - remainder
;
2221 /* Bitmaps with a depth less than 16 need a palette. */
2222 /* BITMAPINFO structure already contains the first RGBQUAD. */
2224 palette_colors
= 1 << depth
- 1;
2226 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2229 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2233 header
= &((*ximg
)->info
.bmiHeader
);
2234 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2235 header
->biSize
= sizeof (*header
);
2236 header
->biWidth
= width
;
2237 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2238 header
->biPlanes
= 1;
2239 header
->biBitCount
= depth
;
2240 header
->biCompression
= BI_RGB
;
2241 header
->biClrUsed
= palette_colors
;
2243 /* TODO: fill in palette. */
2246 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2247 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2248 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2249 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2250 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2251 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2252 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2253 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2256 hdc
= get_frame_dc (f
);
2258 /* Create a DIBSection and raster array for the bitmap,
2259 and store its handle in *pixmap. */
2260 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2261 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2262 /* casting avoids a GCC warning */
2263 (void **)&((*ximg
)->data
), NULL
, 0);
2265 /* Realize display palette and garbage all frames. */
2266 release_frame_dc (f
, hdc
);
2268 if (*pixmap
== NULL
)
2270 DWORD err
= GetLastError ();
2271 Lisp_Object errcode
;
2272 /* All system errors are < 10000, so the following is safe. */
2273 XSETINT (errcode
, (int) err
);
2274 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2275 x_destroy_x_image (*ximg
);
2281 #endif /* HAVE_NTGUI */
2284 Display
*display
= FRAME_X_DISPLAY (f
);
2285 Window window
= FRAME_X_WINDOW (f
);
2287 xassert (interrupt_input_blocked
);
2289 /* Allocate a pixmap of the same size. */
2290 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2291 if (*pixmap
== NO_PIXMAP
)
2294 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2298 LockPixels (GetGWorldPixMap (*pixmap
));
2306 /* Destroy XImage XIMG. Free XIMG->data. */
2309 x_destroy_x_image (ximg
)
2312 xassert (interrupt_input_blocked
);
2315 #ifdef HAVE_X_WINDOWS
2318 XDestroyImage (ximg
);
2319 #endif /* HAVE_X_WINDOWS */
2321 /* Data will be freed by DestroyObject. */
2324 #endif /* HAVE_NTGUI */
2326 XDestroyImage (ximg
);
2332 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2333 are width and height of both the image and pixmap. */
2336 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2342 #ifdef HAVE_X_WINDOWS
2345 xassert (interrupt_input_blocked
);
2346 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2347 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2348 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2349 #endif /* HAVE_X_WINDOWS */
2352 #if 0 /* I don't think this is necessary looking at where it is used. */
2353 HDC hdc
= get_frame_dc (f
);
2354 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2355 release_frame_dc (f
, hdc
);
2357 #endif /* HAVE_NTGUI */
2360 xassert (ximg
== pixmap
);
2365 /***********************************************************************
2367 ***********************************************************************/
2369 static unsigned char *slurp_file
P_ ((char *, int *));
2372 /* Find image file FILE. Look in data-directory/images, then
2373 x-bitmap-file-path. Value is the encoded full name of the file
2374 found, or nil if not found. */
2377 x_find_image_file (file
)
2380 Lisp_Object file_found
, search_path
;
2381 struct gcpro gcpro1
, gcpro2
;
2385 /* TODO I think this should use something like image-load-path
2386 instead. Unfortunately, that can contain non-string elements. */
2387 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2389 Vx_bitmap_file_path
);
2390 GCPRO2 (file_found
, search_path
);
2392 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2393 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2399 file_found
= ENCODE_FILE (file_found
);
2408 /* Read FILE into memory. Value is a pointer to a buffer allocated
2409 with xmalloc holding FILE's contents. Value is null if an error
2410 occurred. *SIZE is set to the size of the file. */
2412 static unsigned char *
2413 slurp_file (file
, size
)
2418 unsigned char *buf
= NULL
;
2421 if (stat (file
, &st
) == 0
2422 && (fp
= fopen (file
, "rb")) != NULL
2423 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2424 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2447 /***********************************************************************
2448 MAC Image Load Functions
2449 ***********************************************************************/
2451 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2454 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2458 find_image_fsspec (specified_file
, file
, fss
)
2459 Lisp_Object specified_file
, *file
;
2465 *file
= x_find_image_file (specified_file
);
2466 if (!STRINGP (*file
))
2467 return fnfErr
; /* file or directory not found;
2468 incomplete pathname */
2469 /* Try to open the image file. */
2470 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2471 SBYTES (*file
), typeFSS
, &desc
);
2474 #if TARGET_API_MAC_CARBON
2475 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2477 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2479 AEDisposeDesc (&desc
);
2485 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2492 ComponentResult err
;
2493 GraphicsImportComponent gi
;
2496 ImageDescriptionHandle desc_handle
;
2497 short draw_all_pixels
;
2498 Lisp_Object specified_bg
;
2503 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2506 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2511 /* read from file system spec */
2512 err
= GraphicsImportSetDataFile (gi
, fss
);
2515 image_error ("Cannot set fsspec to graphics importer for '%s'",
2522 /* read from data handle */
2523 err
= GraphicsImportSetDataHandle (gi
, dh
);
2526 image_error ("Cannot set data handle to graphics importer for `%s'",
2531 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2532 if (err
!= noErr
|| desc_handle
== NULL
)
2534 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2537 width
= img
->width
= (*desc_handle
)->width
;
2538 height
= img
->height
= (*desc_handle
)->height
;
2539 DisposeHandle ((Handle
)desc_handle
);
2541 if (!check_image_size (f
, width
, height
))
2543 image_error ("Invalid image size", Qnil
, Qnil
);
2547 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2549 /* Don't check the error code here. It may have an undocumented
2553 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2557 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2559 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2560 if (!STRINGP (specified_bg
) ||
2561 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2563 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2564 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2565 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2566 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2570 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2572 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2577 GetGWorld (&old_port
, &old_gdh
);
2578 SetGWorld (ximg
, NULL
);
2579 bg_color
.red
= color
.red
;
2580 bg_color
.green
= color
.green
;
2581 bg_color
.blue
= color
.blue
;
2582 RGBBackColor (&bg_color
);
2583 #if TARGET_API_MAC_CARBON
2584 GetPortBounds (ximg
, &rect
);
2587 EraseRect (&(ximg
->portRect
));
2589 SetGWorld (old_port
, old_gdh
);
2591 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2592 GraphicsImportDraw (gi
);
2593 CloseComponent (gi
);
2595 /* Maybe fill in the background field while we have ximg handy. */
2596 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2597 IMAGE_BACKGROUND (img
, f
, ximg
);
2599 /* Put the image into the pixmap. */
2600 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2601 x_destroy_x_image (ximg
);
2605 CloseComponent (gi
);
2610 /* Load an image using the QuickTime Graphics Importer.
2611 Note: The alpha channel does not work for PNG images. */
2613 image_load_quicktime (f
, img
, type
)
2618 Lisp_Object specified_file
;
2619 Lisp_Object specified_data
;
2622 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2623 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2625 if (NILP (specified_data
))
2627 /* Read from a file */
2631 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2635 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2637 image_error ("Cannot open `%s'", file
, Qnil
);
2640 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2644 /* Memory source! */
2648 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2651 image_error ("Cannot allocate data handle for `%s'",
2655 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2663 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2664 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2665 So don't use this function directly but determine at runtime
2666 whether it exists. */
2667 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2668 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2669 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2673 init_image_func_pointer ()
2675 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2677 MyCGImageCreateWithPNGDataProvider
2678 = (CGImageCreateWithPNGDataProviderProcType
)
2679 NSAddressOfSymbol (NSLookupAndBindSymbol
2680 ("_CGImageCreateWithPNGDataProvider"));
2683 MyCGImageCreateWithPNGDataProvider
= NULL
;
2688 image_load_quartz2d (f
, img
, png_p
)
2693 Lisp_Object file
, specified_file
;
2694 Lisp_Object specified_data
, specified_bg
;
2695 struct gcpro gcpro1
;
2696 CGDataProviderRef source
;
2700 XImagePtr ximg
= NULL
;
2701 CGContextRef context
;
2704 /* Open the file. */
2705 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2706 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2711 if (NILP (specified_data
))
2716 file
= x_find_image_file (specified_file
);
2717 if (!STRINGP (file
))
2719 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2723 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2724 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2725 kCFURLPOSIXPathStyle
, 0);
2727 source
= CGDataProviderCreateWithURL (url
);
2731 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2732 SBYTES (specified_data
), NULL
);
2735 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2736 kCGRenderingIntentDefault
);
2738 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2739 kCGRenderingIntentDefault
);
2741 CGDataProviderRelease (source
);
2745 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2748 width
= img
->width
= CGImageGetWidth (image
);
2749 height
= img
->height
= CGImageGetHeight (image
);
2751 if (!check_image_size (f
, width
, height
))
2753 CGImageRelease (image
);
2755 image_error ("Invalid image size", Qnil
, Qnil
);
2761 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2762 if (!STRINGP (specified_bg
) ||
2763 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2765 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2766 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2767 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2768 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2772 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2774 CGImageRelease (image
);
2778 rectangle
= CGRectMake (0, 0, width
, height
);
2779 QDBeginCGContext (ximg
, &context
);
2782 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2783 color
.green
/ 65535.0,
2784 color
.blue
/ 65535.0, 1.0);
2785 CGContextFillRect (context
, rectangle
);
2787 CGContextDrawImage (context
, rectangle
, image
);
2788 QDEndCGContext (ximg
, &context
);
2789 CGImageRelease (image
);
2791 /* Maybe fill in the background field while we have ximg handy. */
2792 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2793 IMAGE_BACKGROUND (img
, f
, ximg
);
2795 /* Put the image into the pixmap. */
2796 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2797 x_destroy_x_image (ximg
);
2806 /***********************************************************************
2808 ***********************************************************************/
2810 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2811 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2812 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2813 unsigned char *, unsigned char *));
2814 static int xbm_image_p
P_ ((Lisp_Object object
));
2815 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2816 unsigned char *, unsigned char *,
2817 int *, int *, unsigned char **));
2818 static int xbm_file_p
P_ ((Lisp_Object
));
2821 /* Indices of image specification fields in xbm_format, below. */
2823 enum xbm_keyword_index
2841 /* Vector of image_keyword structures describing the format
2842 of valid XBM image specifications. */
2844 static struct image_keyword xbm_format
[XBM_LAST
] =
2846 {":type", IMAGE_SYMBOL_VALUE
, 1},
2847 {":file", IMAGE_STRING_VALUE
, 0},
2848 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2849 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2850 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2851 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2852 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2853 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2854 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2855 {":relief", IMAGE_INTEGER_VALUE
, 0},
2856 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2857 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2858 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2861 /* Structure describing the image type XBM. */
2863 static struct image_type xbm_type
=
2872 /* Tokens returned from xbm_scan. */
2881 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2882 A valid specification is a list starting with the symbol `image'
2883 The rest of the list is a property list which must contain an
2886 If the specification specifies a file to load, it must contain
2887 an entry `:file FILENAME' where FILENAME is a string.
2889 If the specification is for a bitmap loaded from memory it must
2890 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2891 WIDTH and HEIGHT are integers > 0. DATA may be:
2893 1. a string large enough to hold the bitmap data, i.e. it must
2894 have a size >= (WIDTH + 7) / 8 * HEIGHT
2896 2. a bool-vector of size >= WIDTH * HEIGHT
2898 3. a vector of strings or bool-vectors, one for each line of the
2901 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2902 may not be specified in this case because they are defined in the
2905 Both the file and data forms may contain the additional entries
2906 `:background COLOR' and `:foreground COLOR'. If not present,
2907 foreground and background of the frame on which the image is
2908 displayed is used. */
2911 xbm_image_p (object
)
2914 struct image_keyword kw
[XBM_LAST
];
2916 bcopy (xbm_format
, kw
, sizeof kw
);
2917 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2920 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2922 if (kw
[XBM_FILE
].count
)
2924 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2927 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2929 /* In-memory XBM file. */
2930 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2938 /* Entries for `:width', `:height' and `:data' must be present. */
2939 if (!kw
[XBM_WIDTH
].count
2940 || !kw
[XBM_HEIGHT
].count
2941 || !kw
[XBM_DATA
].count
)
2944 data
= kw
[XBM_DATA
].value
;
2945 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2946 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2948 /* Check type of data, and width and height against contents of
2954 /* Number of elements of the vector must be >= height. */
2955 if (XVECTOR (data
)->size
< height
)
2958 /* Each string or bool-vector in data must be large enough
2959 for one line of the image. */
2960 for (i
= 0; i
< height
; ++i
)
2962 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2967 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2970 else if (BOOL_VECTOR_P (elt
))
2972 if (XBOOL_VECTOR (elt
)->size
< width
)
2979 else if (STRINGP (data
))
2982 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2985 else if (BOOL_VECTOR_P (data
))
2987 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2998 /* Scan a bitmap file. FP is the stream to read from. Value is
2999 either an enumerator from enum xbm_token, or a character for a
3000 single-character token, or 0 at end of file. If scanning an
3001 identifier, store the lexeme of the identifier in SVAL. If
3002 scanning a number, store its value in *IVAL. */
3005 xbm_scan (s
, end
, sval
, ival
)
3006 unsigned char **s
, *end
;
3014 /* Skip white space. */
3015 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3020 else if (isdigit (c
))
3022 int value
= 0, digit
;
3024 if (c
== '0' && *s
< end
)
3027 if (c
== 'x' || c
== 'X')
3034 else if (c
>= 'a' && c
<= 'f')
3035 digit
= c
- 'a' + 10;
3036 else if (c
>= 'A' && c
<= 'F')
3037 digit
= c
- 'A' + 10;
3040 value
= 16 * value
+ digit
;
3043 else if (isdigit (c
))
3047 && (c
= *(*s
)++, isdigit (c
)))
3048 value
= 8 * value
+ c
- '0';
3055 && (c
= *(*s
)++, isdigit (c
)))
3056 value
= 10 * value
+ c
- '0';
3064 else if (isalpha (c
) || c
== '_')
3068 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3075 else if (c
== '/' && **s
== '*')
3077 /* C-style comment. */
3079 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3093 /* Create a Windows bitmap from X bitmap data. */
3095 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3097 static unsigned char swap_nibble
[16]
3098 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3099 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3100 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3101 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3103 unsigned char *bits
, *p
;
3106 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3107 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3108 bits
= (unsigned char *) alloca (height
* w2
);
3109 bzero (bits
, height
* w2
);
3110 for (i
= 0; i
< height
; i
++)
3113 for (j
= 0; j
< w1
; j
++)
3115 /* Bitswap XBM bytes to match how Windows does things. */
3116 unsigned char c
= *data
++;
3117 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3118 | (swap_nibble
[(c
>>4) & 0xf]));
3121 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3127 convert_mono_to_color_image (f
, img
, foreground
, background
)
3130 COLORREF foreground
, background
;
3132 HDC hdc
, old_img_dc
, new_img_dc
;
3133 HGDIOBJ old_prev
, new_prev
;
3136 hdc
= get_frame_dc (f
);
3137 old_img_dc
= CreateCompatibleDC (hdc
);
3138 new_img_dc
= CreateCompatibleDC (hdc
);
3139 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3140 release_frame_dc (f
, hdc
);
3141 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3142 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3143 /* Windows convention for mono bitmaps is black = background,
3144 white = foreground. */
3145 SetTextColor (new_img_dc
, background
);
3146 SetBkColor (new_img_dc
, foreground
);
3148 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3151 SelectObject (old_img_dc
, old_prev
);
3152 SelectObject (new_img_dc
, new_prev
);
3153 DeleteDC (old_img_dc
);
3154 DeleteDC (new_img_dc
);
3155 DeleteObject (img
->pixmap
);
3156 if (new_pixmap
== 0)
3157 fprintf (stderr
, "Failed to convert image to color.\n");
3159 img
->pixmap
= new_pixmap
;
3162 #define XBM_BIT_SHUFFLE(b) (~(b))
3166 #define XBM_BIT_SHUFFLE(b) (b)
3168 #endif /* HAVE_NTGUI */
3172 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
3176 RGB_PIXEL_COLOR fg
, bg
;
3177 int non_default_colors
;
3181 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3183 /* If colors were specified, transfer the bitmap to a color one. */
3184 if (non_default_colors
)
3185 convert_mono_to_color_image (f
, img
, fg
, bg
);
3188 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3191 img
->width
, img
->height
,
3193 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3194 #endif /* HAVE_NTGUI */
3199 /* Replacement for XReadBitmapFileData which isn't available under old
3200 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3201 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3202 the image. Return in *DATA the bitmap data allocated with xmalloc.
3203 Value is non-zero if successful. DATA null means just test if
3204 CONTENTS looks like an in-memory XBM file. */
3207 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3209 unsigned char *contents
, *end
;
3210 int *width
, *height
;
3211 unsigned char **data
;
3213 unsigned char *s
= contents
;
3214 char buffer
[BUFSIZ
];
3217 int bytes_per_line
, i
, nbytes
;
3223 LA1 = xbm_scan (&s, end, buffer, &value)
3225 #define expect(TOKEN) \
3226 if (LA1 != (TOKEN)) \
3231 #define expect_ident(IDENT) \
3232 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3237 *width
= *height
= -1;
3240 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3242 /* Parse defines for width, height and hot-spots. */
3246 expect_ident ("define");
3247 expect (XBM_TK_IDENT
);
3249 if (LA1
== XBM_TK_NUMBER
)
3251 char *p
= strrchr (buffer
, '_');
3252 p
= p
? p
+ 1 : buffer
;
3253 if (strcmp (p
, "width") == 0)
3255 else if (strcmp (p
, "height") == 0)
3258 expect (XBM_TK_NUMBER
);
3261 if (!check_image_size (f
, *width
, *height
))
3263 else if (data
== NULL
)
3266 /* Parse bits. Must start with `static'. */
3267 expect_ident ("static");
3268 if (LA1
== XBM_TK_IDENT
)
3270 if (strcmp (buffer
, "unsigned") == 0)
3273 expect_ident ("char");
3275 else if (strcmp (buffer
, "short") == 0)
3279 if (*width
% 16 && *width
% 16 < 9)
3282 else if (strcmp (buffer
, "char") == 0)
3290 expect (XBM_TK_IDENT
);
3296 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3297 nbytes
= bytes_per_line
* *height
;
3298 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3302 for (i
= 0; i
< nbytes
; i
+= 2)
3305 expect (XBM_TK_NUMBER
);
3307 *p
++ = XBM_BIT_SHUFFLE (val
);
3308 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3309 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3311 if (LA1
== ',' || LA1
== '}')
3319 for (i
= 0; i
< nbytes
; ++i
)
3322 expect (XBM_TK_NUMBER
);
3324 *p
++ = XBM_BIT_SHUFFLE (val
);
3326 if (LA1
== ',' || LA1
== '}')
3351 /* Load XBM image IMG which will be displayed on frame F from buffer
3352 CONTENTS. END is the end of the buffer. Value is non-zero if
3356 xbm_load_image (f
, img
, contents
, end
)
3359 unsigned char *contents
, *end
;
3362 unsigned char *data
;
3365 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3368 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3369 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3370 int non_default_colors
= 0;
3373 xassert (img
->width
> 0 && img
->height
> 0);
3375 /* Get foreground and background colors, maybe allocate colors. */
3376 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3379 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3380 non_default_colors
= 1;
3382 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3385 background
= x_alloc_image_color (f
, img
, value
, background
);
3386 img
->background
= background
;
3387 img
->background_valid
= 1;
3388 non_default_colors
= 1;
3391 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3392 foreground
, background
,
3393 non_default_colors
);
3396 if (img
->pixmap
== NO_PIXMAP
)
3398 x_clear_image (f
, img
);
3399 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3405 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3411 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3418 return (STRINGP (data
)
3419 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3426 /* Fill image IMG which is used on frame F with pixmap data. Value is
3427 non-zero if successful. */
3435 Lisp_Object file_name
;
3437 xassert (xbm_image_p (img
->spec
));
3439 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3440 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3441 if (STRINGP (file_name
))
3444 unsigned char *contents
;
3446 struct gcpro gcpro1
;
3448 file
= x_find_image_file (file_name
);
3450 if (!STRINGP (file
))
3452 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3457 contents
= slurp_file (SDATA (file
), &size
);
3458 if (contents
== NULL
)
3460 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3465 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3470 struct image_keyword fmt
[XBM_LAST
];
3472 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3473 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3474 int non_default_colors
= 0;
3477 int in_memory_file_p
= 0;
3479 /* See if data looks like an in-memory XBM file. */
3480 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3481 in_memory_file_p
= xbm_file_p (data
);
3483 /* Parse the image specification. */
3484 bcopy (xbm_format
, fmt
, sizeof fmt
);
3485 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3488 /* Get specified width, and height. */
3489 if (!in_memory_file_p
)
3491 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3492 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3493 xassert (img
->width
> 0 && img
->height
> 0);
3496 /* Get foreground and background colors, maybe allocate colors. */
3497 if (fmt
[XBM_FOREGROUND
].count
3498 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3500 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3502 non_default_colors
= 1;
3505 if (fmt
[XBM_BACKGROUND
].count
3506 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3508 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3510 non_default_colors
= 1;
3513 if (in_memory_file_p
)
3514 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3523 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3525 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3526 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3528 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3530 bcopy (SDATA (line
), p
, nbytes
);
3532 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3535 else if (STRINGP (data
))
3536 bits
= SDATA (data
);
3538 bits
= XBOOL_VECTOR (data
)->data
;
3544 /* Windows mono bitmaps are reversed compared with X. */
3545 invertedBits
= bits
;
3546 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3548 bits
= (char *) alloca(nbytes
);
3549 for (i
= 0; i
< nbytes
; i
++)
3550 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3553 /* Create the pixmap. */
3555 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3556 foreground
, background
,
3557 non_default_colors
);
3562 image_error ("Unable to create pixmap for XBM image `%s'",
3564 x_clear_image (f
, img
);
3574 /***********************************************************************
3576 ***********************************************************************/
3578 #if defined (HAVE_XPM) || defined (MAC_OS)
3580 static int xpm_image_p
P_ ((Lisp_Object object
));
3581 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3582 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3584 #endif /* HAVE_XPM || MAC_OS */
3588 /* Indicate to xpm.h that we don't have Xlib. */
3590 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3591 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3592 #define XColor xpm_XColor
3593 #define XImage xpm_XImage
3594 #define Display xpm_Display
3595 #define PIXEL_ALREADY_TYPEDEFED
3596 #include "X11/xpm.h"
3601 #undef PIXEL_ALREADY_TYPEDEFED
3603 #include "X11/xpm.h"
3604 #endif /* HAVE_NTGUI */
3605 #endif /* HAVE_XPM */
3607 #if defined (HAVE_XPM) || defined (MAC_OS)
3608 /* The symbol `xpm' identifying XPM-format images. */
3612 /* Indices of image specification fields in xpm_format, below. */
3614 enum xpm_keyword_index
3630 /* Vector of image_keyword structures describing the format
3631 of valid XPM image specifications. */
3633 static struct image_keyword xpm_format
[XPM_LAST
] =
3635 {":type", IMAGE_SYMBOL_VALUE
, 1},
3636 {":file", IMAGE_STRING_VALUE
, 0},
3637 {":data", IMAGE_STRING_VALUE
, 0},
3638 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3639 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3640 {":relief", IMAGE_INTEGER_VALUE
, 0},
3641 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3642 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3643 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3644 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3645 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3648 /* Structure describing the image type XPM. */
3650 static struct image_type xpm_type
=
3659 #ifdef HAVE_X_WINDOWS
3661 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3662 functions for allocating image colors. Our own functions handle
3663 color allocation failures more gracefully than the ones on the XPM
3666 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3667 #define ALLOC_XPM_COLORS
3669 #endif /* HAVE_X_WINDOWS */
3671 #ifdef ALLOC_XPM_COLORS
3673 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3674 static void xpm_free_color_cache
P_ ((void));
3675 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3676 static int xpm_color_bucket
P_ ((char *));
3677 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3680 /* An entry in a hash table used to cache color definitions of named
3681 colors. This cache is necessary to speed up XPM image loading in
3682 case we do color allocations ourselves. Without it, we would need
3683 a call to XParseColor per pixel in the image. */
3685 struct xpm_cached_color
3687 /* Next in collision chain. */
3688 struct xpm_cached_color
*next
;
3690 /* Color definition (RGB and pixel color). */
3697 /* The hash table used for the color cache, and its bucket vector
3700 #define XPM_COLOR_CACHE_BUCKETS 1001
3701 struct xpm_cached_color
**xpm_color_cache
;
3703 /* Initialize the color cache. */
3706 xpm_init_color_cache (f
, attrs
)
3708 XpmAttributes
*attrs
;
3710 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3711 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3712 memset (xpm_color_cache
, 0, nbytes
);
3713 init_color_table ();
3715 if (attrs
->valuemask
& XpmColorSymbols
)
3720 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3721 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3722 attrs
->colorsymbols
[i
].value
, &color
))
3724 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3726 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3731 /* Free the color cache. */
3734 xpm_free_color_cache ()
3736 struct xpm_cached_color
*p
, *next
;
3739 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3740 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3746 xfree (xpm_color_cache
);
3747 xpm_color_cache
= NULL
;
3748 free_color_table ();
3751 /* Return the bucket index for color named COLOR_NAME in the color
3755 xpm_color_bucket (color_name
)
3761 for (s
= color_name
; *s
; ++s
)
3763 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3767 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3768 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3771 static struct xpm_cached_color
*
3772 xpm_cache_color (f
, color_name
, color
, bucket
)
3779 struct xpm_cached_color
*p
;
3782 bucket
= xpm_color_bucket (color_name
);
3784 nbytes
= sizeof *p
+ strlen (color_name
);
3785 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3786 strcpy (p
->name
, color_name
);
3788 p
->next
= xpm_color_cache
[bucket
];
3789 xpm_color_cache
[bucket
] = p
;
3793 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3794 return the cached definition in *COLOR. Otherwise, make a new
3795 entry in the cache and allocate the color. Value is zero if color
3796 allocation failed. */
3799 xpm_lookup_color (f
, color_name
, color
)
3804 struct xpm_cached_color
*p
;
3805 int h
= xpm_color_bucket (color_name
);
3807 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3808 if (strcmp (p
->name
, color_name
) == 0)
3813 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3816 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3818 p
= xpm_cache_color (f
, color_name
, color
, h
);
3820 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3821 with transparency, and it's useful. */
3822 else if (strcmp ("opaque", color_name
) == 0)
3824 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3825 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3826 p
= xpm_cache_color (f
, color_name
, color
, h
);
3833 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3834 CLOSURE is a pointer to the frame on which we allocate the
3835 color. Return in *COLOR the allocated color. Value is non-zero
3839 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3846 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3850 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3851 is a pointer to the frame on which we allocate the color. Value is
3852 non-zero if successful. */
3855 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3865 #endif /* ALLOC_XPM_COLORS */
3870 /* XPM library details. */
3872 DEF_IMGLIB_FN (XpmFreeAttributes
);
3873 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3874 DEF_IMGLIB_FN (XpmReadFileToImage
);
3875 DEF_IMGLIB_FN (XImageFree
);
3878 init_xpm_functions (Lisp_Object libraries
)
3882 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3885 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3886 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3887 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3888 LOAD_IMGLIB_FN (library
, XImageFree
);
3892 #endif /* HAVE_NTGUI */
3895 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3896 for XPM images. Such a list must consist of conses whose car and
3900 xpm_valid_color_symbols_p (color_symbols
)
3901 Lisp_Object color_symbols
;
3903 while (CONSP (color_symbols
))
3905 Lisp_Object sym
= XCAR (color_symbols
);
3907 || !STRINGP (XCAR (sym
))
3908 || !STRINGP (XCDR (sym
)))
3910 color_symbols
= XCDR (color_symbols
);
3913 return NILP (color_symbols
);
3917 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3920 xpm_image_p (object
)
3923 struct image_keyword fmt
[XPM_LAST
];
3924 bcopy (xpm_format
, fmt
, sizeof fmt
);
3925 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3926 /* Either `:file' or `:data' must be present. */
3927 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3928 /* Either no `:color-symbols' or it's a list of conses
3929 whose car and cdr are strings. */
3930 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3931 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3934 #endif /* HAVE_XPM || MAC_OS */
3936 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3938 x_create_bitmap_from_xpm_data (f
, bits
)
3942 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3944 XpmAttributes attrs
;
3945 Pixmap bitmap
, mask
;
3947 bzero (&attrs
, sizeof attrs
);
3949 attrs
.visual
= FRAME_X_VISUAL (f
);
3950 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3951 attrs
.valuemask
|= XpmVisual
;
3952 attrs
.valuemask
|= XpmColormap
;
3954 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3955 bits
, &bitmap
, &mask
, &attrs
);
3956 if (rc
!= XpmSuccess
)
3958 XpmFreeAttributes (&attrs
);
3962 id
= x_allocate_bitmap_record (f
);
3963 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3964 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3965 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3966 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3967 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3968 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3969 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3970 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3972 XpmFreeAttributes (&attrs
);
3975 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3977 /* Load image IMG which will be displayed on frame F. Value is
3978 non-zero if successful. */
3988 XpmAttributes attrs
;
3989 Lisp_Object specified_file
, color_symbols
;
3992 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3993 #endif /* HAVE_NTGUI */
3995 /* Configure the XPM lib. Use the visual of frame F. Allocate
3996 close colors. Return colors allocated. */
3997 bzero (&attrs
, sizeof attrs
);
4000 attrs
.visual
= FRAME_X_VISUAL (f
);
4001 attrs
.colormap
= FRAME_X_COLORMAP (f
);
4002 attrs
.valuemask
|= XpmVisual
;
4003 attrs
.valuemask
|= XpmColormap
;
4004 #endif /* HAVE_NTGUI */
4006 #ifdef ALLOC_XPM_COLORS
4007 /* Allocate colors with our own functions which handle
4008 failing color allocation more gracefully. */
4009 attrs
.color_closure
= f
;
4010 attrs
.alloc_color
= xpm_alloc_color
;
4011 attrs
.free_colors
= xpm_free_colors
;
4012 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
4013 #else /* not ALLOC_XPM_COLORS */
4014 /* Let the XPM lib allocate colors. */
4015 attrs
.valuemask
|= XpmReturnAllocPixels
;
4016 #ifdef XpmAllocCloseColors
4017 attrs
.alloc_close_colors
= 1;
4018 attrs
.valuemask
|= XpmAllocCloseColors
;
4019 #else /* not XpmAllocCloseColors */
4020 attrs
.closeness
= 600;
4021 attrs
.valuemask
|= XpmCloseness
;
4022 #endif /* not XpmAllocCloseColors */
4023 #endif /* ALLOC_XPM_COLORS */
4025 /* If image specification contains symbolic color definitions, add
4026 these to `attrs'. */
4027 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4028 if (CONSP (color_symbols
))
4031 XpmColorSymbol
*xpm_syms
;
4034 attrs
.valuemask
|= XpmColorSymbols
;
4036 /* Count number of symbols. */
4037 attrs
.numsymbols
= 0;
4038 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4041 /* Allocate an XpmColorSymbol array. */
4042 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4043 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4044 bzero (xpm_syms
, size
);
4045 attrs
.colorsymbols
= xpm_syms
;
4047 /* Fill the color symbol array. */
4048 for (tail
= color_symbols
, i
= 0;
4050 ++i
, tail
= XCDR (tail
))
4052 Lisp_Object name
= XCAR (XCAR (tail
));
4053 Lisp_Object color
= XCDR (XCAR (tail
));
4054 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4055 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4056 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4057 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4061 /* Create a pixmap for the image, either from a file, or from a
4062 string buffer containing data in the same format as an XPM file. */
4063 #ifdef ALLOC_XPM_COLORS
4064 xpm_init_color_cache (f
, &attrs
);
4067 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4071 HDC frame_dc
= get_frame_dc (f
);
4072 hdc
= CreateCompatibleDC (frame_dc
);
4073 release_frame_dc (f
, frame_dc
);
4075 #endif /* HAVE_NTGUI */
4077 if (STRINGP (specified_file
))
4079 Lisp_Object file
= x_find_image_file (specified_file
);
4080 if (!STRINGP (file
))
4082 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4087 /* XpmReadFileToPixmap is not available in the Windows port of
4088 libxpm. But XpmReadFileToImage almost does what we want. */
4089 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4090 &xpm_image
, &xpm_mask
,
4093 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4094 SDATA (file
), &img
->pixmap
, &img
->mask
,
4096 #endif /* HAVE_NTGUI */
4100 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4102 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4103 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4104 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4105 &xpm_image
, &xpm_mask
,
4108 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4110 &img
->pixmap
, &img
->mask
,
4112 #endif /* HAVE_NTGUI */
4115 if (rc
== XpmSuccess
)
4117 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4118 img
->colors
= colors_in_color_table (&img
->ncolors
);
4119 #else /* not ALLOC_XPM_COLORS */
4123 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4124 plus some duplicate attributes. */
4125 if (xpm_image
&& xpm_image
->bitmap
)
4127 img
->pixmap
= xpm_image
->bitmap
;
4128 /* XImageFree in libXpm frees XImage struct without destroying
4129 the bitmap, which is what we want. */
4130 fn_XImageFree (xpm_image
);
4132 if (xpm_mask
&& xpm_mask
->bitmap
)
4134 /* The mask appears to be inverted compared with what we expect.
4135 TODO: invert our expectations. See other places where we
4136 have to invert bits because our idea of masks is backwards. */
4138 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4140 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4141 SelectObject (hdc
, old_obj
);
4143 img
->mask
= xpm_mask
->bitmap
;
4144 fn_XImageFree (xpm_mask
);
4149 #endif /* HAVE_NTGUI */
4151 /* Remember allocated colors. */
4152 img
->ncolors
= attrs
.nalloc_pixels
;
4153 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4154 * sizeof *img
->colors
);
4155 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4157 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4158 #ifdef DEBUG_X_COLORS
4159 register_color (img
->colors
[i
]);
4162 #endif /* not ALLOC_XPM_COLORS */
4164 img
->width
= attrs
.width
;
4165 img
->height
= attrs
.height
;
4166 xassert (img
->width
> 0 && img
->height
> 0);
4168 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4170 fn_XpmFreeAttributes (&attrs
);
4172 XpmFreeAttributes (&attrs
);
4173 #endif /* HAVE_NTGUI */
4179 #endif /* HAVE_NTGUI */
4184 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4187 case XpmFileInvalid
:
4188 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4192 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4195 case XpmColorFailed
:
4196 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4200 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4205 #ifdef ALLOC_XPM_COLORS
4206 xpm_free_color_cache ();
4208 return rc
== XpmSuccess
;
4211 #endif /* HAVE_XPM */
4215 /* XPM support functions for Mac OS where libxpm is not available.
4216 Only XPM version 3 (without any extensions) is supported. */
4218 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4219 const unsigned char **, int *));
4220 static Lisp_Object xpm_make_color_table_v
4221 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4222 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4223 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4225 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4226 const unsigned char *, int));
4227 static Lisp_Object xpm_make_color_table_h
4228 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4229 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4230 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4232 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4233 const unsigned char *, int));
4234 static int xpm_str_to_color_key
P_ ((const char *));
4235 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4236 const unsigned char *, const unsigned char *));
4238 /* Tokens returned from xpm_scan. */
4247 /* Scan an XPM data and return a character (< 256) or a token defined
4248 by enum xpm_token above. *S and END are the start (inclusive) and
4249 the end (exclusive) addresses of the data, respectively. Advance
4250 *S while scanning. If token is either XPM_TK_IDENT or
4251 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4252 length of the corresponding token, respectively. */
4255 xpm_scan (s
, end
, beg
, len
)
4256 const unsigned char **s
, *end
, **beg
;
4263 /* Skip white-space. */
4264 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4267 /* gnus-pointer.xpm uses '-' in its identifier.
4268 sb-dir-plus.xpm uses '+' in its identifier. */
4269 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4273 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4276 return XPM_TK_IDENT
;
4281 while (*s
< end
&& **s
!= '"')
4286 return XPM_TK_STRING
;
4290 if (*s
< end
&& **s
== '*')
4292 /* C-style comment. */
4296 while (*s
< end
&& *(*s
)++ != '*')
4299 while (*s
< end
&& **s
!= '/');
4313 /* Functions for color table lookup in XPM data. A key is a string
4314 specifying the color of each pixel in XPM data. A value is either
4315 an integer that specifies a pixel color, Qt that specifies
4316 transparency, or Qnil for the unspecified color. If the length of
4317 the key string is one, a vector is used as a table. Otherwise, a
4318 hash table is used. */
4321 xpm_make_color_table_v (put_func
, get_func
)
4322 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4323 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4325 *put_func
= xpm_put_color_table_v
;
4326 *get_func
= xpm_get_color_table_v
;
4327 return Fmake_vector (make_number (256), Qnil
);
4331 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4332 Lisp_Object color_table
;
4333 const unsigned char *chars_start
;
4337 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4341 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4342 Lisp_Object color_table
;
4343 const unsigned char *chars_start
;
4346 return XVECTOR (color_table
)->contents
[*chars_start
];
4350 xpm_make_color_table_h (put_func
, get_func
)
4351 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4352 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4354 *put_func
= xpm_put_color_table_h
;
4355 *get_func
= xpm_get_color_table_h
;
4356 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4357 make_float (DEFAULT_REHASH_SIZE
),
4358 make_float (DEFAULT_REHASH_THRESHOLD
),
4363 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4364 Lisp_Object color_table
;
4365 const unsigned char *chars_start
;
4369 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4371 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4373 hash_lookup (table
, chars
, &hash_code
);
4374 hash_put (table
, chars
, color
, hash_code
);
4378 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4379 Lisp_Object color_table
;
4380 const unsigned char *chars_start
;
4383 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4384 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4387 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4390 enum xpm_color_key
{
4398 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4401 xpm_str_to_color_key (s
)
4407 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4409 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4415 xpm_load_image (f
, img
, contents
, end
)
4418 const unsigned char *contents
, *end
;
4420 const unsigned char *s
= contents
, *beg
, *str
;
4421 unsigned char buffer
[BUFSIZ
];
4422 int width
, height
, x
, y
;
4423 int num_colors
, chars_per_pixel
;
4425 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4426 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4427 Lisp_Object frame
, color_symbols
, color_table
;
4428 int best_key
, have_mask
= 0;
4429 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4432 LA1 = xpm_scan (&s, end, &beg, &len)
4434 #define expect(TOKEN) \
4435 if (LA1 != (TOKEN)) \
4440 #define expect_ident(IDENT) \
4441 if (LA1 == XPM_TK_IDENT \
4442 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4447 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4451 expect_ident ("static");
4452 expect_ident ("char");
4454 expect (XPM_TK_IDENT
);
4459 expect (XPM_TK_STRING
);
4462 memcpy (buffer
, beg
, len
);
4464 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4465 &num_colors
, &chars_per_pixel
) != 4
4466 || width
<= 0 || height
<= 0
4467 || num_colors
<= 0 || chars_per_pixel
<= 0)
4470 if (!check_image_size (f
, width
, height
))
4472 image_error ("Invalid image size", Qnil
, Qnil
);
4478 XSETFRAME (frame
, f
);
4479 if (!NILP (Fxw_display_color_p (frame
)))
4480 best_key
= XPM_COLOR_KEY_C
;
4481 else if (!NILP (Fx_display_grayscale_p (frame
)))
4482 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4483 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4485 best_key
= XPM_COLOR_KEY_M
;
4487 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4488 if (chars_per_pixel
== 1)
4489 color_table
= xpm_make_color_table_v (&put_color_table
,
4492 color_table
= xpm_make_color_table_h (&put_color_table
,
4495 while (num_colors
-- > 0)
4497 unsigned char *color
, *max_color
;
4498 int key
, next_key
, max_key
= 0;
4499 Lisp_Object symbol_color
= Qnil
, color_val
;
4502 expect (XPM_TK_STRING
);
4503 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4505 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4506 buffer
[len
- chars_per_pixel
] = '\0';
4508 str
= strtok (buffer
, " \t");
4511 key
= xpm_str_to_color_key (str
);
4516 color
= strtok (NULL
, " \t");
4520 while ((str
= strtok (NULL
, " \t")) != NULL
)
4522 next_key
= xpm_str_to_color_key (str
);
4525 color
[strlen (color
)] = ' ';
4528 if (key
== XPM_COLOR_KEY_S
)
4530 if (NILP (symbol_color
))
4531 symbol_color
= build_string (color
);
4533 else if (max_key
< key
&& key
<= best_key
)
4543 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4545 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4547 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4549 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4551 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4553 color_val
= make_number (cdef
.pixel
);
4556 if (NILP (color_val
) && max_key
> 0)
4558 if (xstricmp (max_color
, "None") == 0)
4560 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4561 color_val
= make_number (cdef
.pixel
);
4563 if (!NILP (color_val
))
4564 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4569 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4570 &ximg
, &img
->pixmap
)
4571 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4572 &mask_img
, &img
->mask
))
4574 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4578 for (y
= 0; y
< height
; y
++)
4580 expect (XPM_TK_STRING
);
4582 if (len
< width
* chars_per_pixel
)
4584 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4586 Lisp_Object color_val
=
4587 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4589 XPutPixel (ximg
, x
, y
,
4590 (INTEGERP (color_val
) ? XINT (color_val
)
4591 : FRAME_FOREGROUND_PIXEL (f
)));
4592 XPutPixel (mask_img
, x
, y
,
4593 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4594 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4601 img
->height
= height
;
4603 /* Maybe fill in the background field while we have ximg handy. */
4604 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4605 IMAGE_BACKGROUND (img
, f
, ximg
);
4607 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4608 x_destroy_x_image (ximg
);
4611 /* Fill in the background_transparent field while we have the
4613 image_background_transparent (img
, f
, mask_img
);
4615 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4616 x_destroy_x_image (mask_img
);
4620 x_destroy_x_image (mask_img
);
4621 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4622 img
->mask
= NO_PIXMAP
;
4628 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4630 x_destroy_x_image (ximg
);
4631 x_destroy_x_image (mask_img
);
4632 x_clear_image (f
, img
);
4646 Lisp_Object file_name
;
4648 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4649 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4650 if (STRINGP (file_name
))
4653 unsigned char *contents
;
4655 struct gcpro gcpro1
;
4657 file
= x_find_image_file (file_name
);
4659 if (!STRINGP (file
))
4661 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4666 contents
= slurp_file (SDATA (file
), &size
);
4667 if (contents
== NULL
)
4669 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4674 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4682 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4683 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4684 SDATA (data
) + SBYTES (data
));
4694 /***********************************************************************
4696 ***********************************************************************/
4698 #ifdef COLOR_TABLE_SUPPORT
4700 /* An entry in the color table mapping an RGB color to a pixel color. */
4705 unsigned long pixel
;
4707 /* Next in color table collision list. */
4708 struct ct_color
*next
;
4711 /* The bucket vector size to use. Must be prime. */
4715 /* Value is a hash of the RGB color given by R, G, and B. */
4717 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4719 /* The color hash table. */
4721 struct ct_color
**ct_table
;
4723 /* Number of entries in the color table. */
4725 int ct_colors_allocated
;
4727 /* Initialize the color table. */
4732 int size
= CT_SIZE
* sizeof (*ct_table
);
4733 ct_table
= (struct ct_color
**) xmalloc (size
);
4734 bzero (ct_table
, size
);
4735 ct_colors_allocated
= 0;
4739 /* Free memory associated with the color table. */
4745 struct ct_color
*p
, *next
;
4747 for (i
= 0; i
< CT_SIZE
; ++i
)
4748 for (p
= ct_table
[i
]; p
; p
= next
)
4759 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4760 entry for that color already is in the color table, return the
4761 pixel color of that entry. Otherwise, allocate a new color for R,
4762 G, B, and make an entry in the color table. */
4764 static unsigned long
4765 lookup_rgb_color (f
, r
, g
, b
)
4769 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4770 int i
= hash
% CT_SIZE
;
4772 Display_Info
*dpyinfo
;
4774 /* Handle TrueColor visuals specially, which improves performance by
4775 two orders of magnitude. Freeing colors on TrueColor visuals is
4776 a nop, and pixel colors specify RGB values directly. See also
4777 the Xlib spec, chapter 3.1. */
4778 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4779 if (dpyinfo
->red_bits
> 0)
4781 unsigned long pr
, pg
, pb
;
4783 /* Apply gamma-correction like normal color allocation does. */
4787 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4788 gamma_correct (f
, &color
);
4789 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4792 /* Scale down RGB values to the visual's bits per RGB, and shift
4793 them to the right position in the pixel color. Note that the
4794 original RGB values are 16-bit values, as usual in X. */
4795 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4796 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4797 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4799 /* Assemble the pixel color. */
4800 return pr
| pg
| pb
;
4803 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4804 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4810 #ifdef HAVE_X_WINDOWS
4819 cmap
= FRAME_X_COLORMAP (f
);
4820 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4823 ++ct_colors_allocated
;
4824 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4828 p
->pixel
= color
.pixel
;
4829 p
->next
= ct_table
[i
];
4833 return FRAME_FOREGROUND_PIXEL (f
);
4838 color
= PALETTERGB (r
, g
, b
);
4840 color
= RGB_TO_ULONG (r
, g
, b
);
4841 #endif /* HAVE_NTGUI */
4842 ++ct_colors_allocated
;
4843 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4848 p
->next
= ct_table
[i
];
4850 #endif /* HAVE_X_WINDOWS */
4858 /* Look up pixel color PIXEL which is used on frame F in the color
4859 table. If not already present, allocate it. Value is PIXEL. */
4861 static unsigned long
4862 lookup_pixel_color (f
, pixel
)
4864 unsigned long pixel
;
4866 int i
= pixel
% CT_SIZE
;
4869 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4870 if (p
->pixel
== pixel
)
4879 #ifdef HAVE_X_WINDOWS
4880 cmap
= FRAME_X_COLORMAP (f
);
4881 color
.pixel
= pixel
;
4882 x_query_color (f
, &color
);
4883 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4886 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4887 color
.pixel
= pixel
;
4888 XQueryColor (NULL
, cmap
, &color
);
4889 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4891 #endif /* HAVE_X_WINDOWS */
4895 ++ct_colors_allocated
;
4897 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4902 p
->next
= ct_table
[i
];
4906 return FRAME_FOREGROUND_PIXEL (f
);
4912 /* Value is a vector of all pixel colors contained in the color table,
4913 allocated via xmalloc. Set *N to the number of colors. */
4915 static unsigned long *
4916 colors_in_color_table (n
)
4921 unsigned long *colors
;
4923 if (ct_colors_allocated
== 0)
4930 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4932 *n
= ct_colors_allocated
;
4934 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4935 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4936 colors
[j
++] = p
->pixel
;
4942 #else /* COLOR_TABLE_SUPPORT */
4944 static unsigned long
4945 lookup_rgb_color (f
, r
, g
, b
)
4949 unsigned long pixel
;
4952 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4953 gamma_correct (f
, &pixel
);
4957 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4958 #endif /* HAVE_NTGUI */
4967 #endif /* COLOR_TABLE_SUPPORT */
4970 /***********************************************************************
4972 ***********************************************************************/
4974 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4975 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4976 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4979 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4980 #endif /* HAVE_NTGUI */
4982 /* Non-zero means draw a cross on images having `:conversion
4985 int cross_disabled_images
;
4987 /* Edge detection matrices for different edge-detection
4990 static int emboss_matrix
[9] = {
4992 2, -1, 0, /* y - 1 */
4994 0, 1, -2 /* y + 1 */
4997 static int laplace_matrix
[9] = {
4999 1, 0, 0, /* y - 1 */
5001 0, 0, -1 /* y + 1 */
5004 /* Value is the intensity of the color whose red/green/blue values
5007 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5010 /* On frame F, return an array of XColor structures describing image
5011 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5012 non-zero means also fill the red/green/blue members of the XColor
5013 structures. Value is a pointer to the array of XColors structures,
5014 allocated with xmalloc; it must be freed by the caller. */
5017 x_to_xcolors (f
, img
, rgb_p
)
5024 XImagePtr_or_DC ximg
;
5028 #endif /* HAVE_NTGUI */
5030 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5033 /* Get the X image IMG->pixmap. */
5034 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5035 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5037 /* Load the image into a memory device context. */
5038 hdc
= get_frame_dc (f
);
5039 ximg
= CreateCompatibleDC (hdc
);
5040 release_frame_dc (f
, hdc
);
5041 prev
= SelectObject (ximg
, img
->pixmap
);
5042 #endif /* HAVE_NTGUI */
5044 /* Fill the `pixel' members of the XColor array. I wished there
5045 were an easy and portable way to circumvent XGetPixel. */
5047 for (y
= 0; y
< img
->height
; ++y
)
5051 #ifdef HAVE_X_WINDOWS
5052 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5053 p
->pixel
= XGetPixel (ximg
, x
, y
);
5055 x_query_colors (f
, row
, img
->width
);
5059 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5061 /* W32_TODO: palette support needed here? */
5062 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5066 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5067 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5068 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5071 p
->red
= 256 * GetRValue (p
->pixel
);
5072 p
->green
= 256 * GetGValue (p
->pixel
);
5073 p
->blue
= 256 * GetBValue (p
->pixel
);
5074 #endif /* HAVE_NTGUI */
5077 #endif /* HAVE_X_WINDOWS */
5080 Destroy_Image (ximg
, prev
);
5087 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5088 created with CreateDIBSection, with the pointer to the bit values
5089 stored in ximg->data. */
5092 XPutPixel (ximg
, x
, y
, color
)
5097 int width
= ximg
->info
.bmiHeader
.biWidth
;
5098 int height
= ximg
->info
.bmiHeader
.biHeight
;
5099 unsigned char * pixel
;
5101 /* True color images. */
5102 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5104 int rowbytes
= width
* 3;
5105 /* Ensure scanlines are aligned on 4 byte boundaries. */
5107 rowbytes
+= 4 - (rowbytes
% 4);
5109 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5110 /* Windows bitmaps are in BGR order. */
5111 *pixel
= GetBValue (color
);
5112 *(pixel
+ 1) = GetGValue (color
);
5113 *(pixel
+ 2) = GetRValue (color
);
5115 /* Monochrome images. */
5116 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5118 int rowbytes
= width
/ 8;
5119 /* Ensure scanlines are aligned on 4 byte boundaries. */
5121 rowbytes
+= 4 - (rowbytes
% 4);
5122 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5123 /* Filter out palette info. */
5124 if (color
& 0x00ffffff)
5125 *pixel
= *pixel
| (1 << x
% 8);
5127 *pixel
= *pixel
& ~(1 << x
% 8);
5130 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5133 #endif /* HAVE_NTGUI */
5135 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5136 RGB members are set. F is the frame on which this all happens.
5137 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5140 x_from_xcolors (f
, img
, colors
)
5150 init_color_table ();
5152 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5155 for (y
= 0; y
< img
->height
; ++y
)
5156 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5158 unsigned long pixel
;
5159 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5160 XPutPixel (oimg
, x
, y
, pixel
);
5164 x_clear_image_1 (f
, img
, 1, 0, 1);
5166 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5167 x_destroy_x_image (oimg
);
5168 img
->pixmap
= pixmap
;
5169 #ifdef COLOR_TABLE_SUPPORT
5170 img
->colors
= colors_in_color_table (&img
->ncolors
);
5171 free_color_table ();
5172 #endif /* COLOR_TABLE_SUPPORT */
5176 /* On frame F, perform edge-detection on image IMG.
5178 MATRIX is a nine-element array specifying the transformation
5179 matrix. See emboss_matrix for an example.
5181 COLOR_ADJUST is a color adjustment added to each pixel of the
5185 x_detect_edges (f
, img
, matrix
, color_adjust
)
5188 int matrix
[9], color_adjust
;
5190 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5194 for (i
= sum
= 0; i
< 9; ++i
)
5195 sum
+= eabs (matrix
[i
]);
5197 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5199 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5201 for (y
= 0; y
< img
->height
; ++y
)
5203 p
= COLOR (new, 0, y
);
5204 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5205 p
= COLOR (new, img
->width
- 1, y
);
5206 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5209 for (x
= 1; x
< img
->width
- 1; ++x
)
5211 p
= COLOR (new, x
, 0);
5212 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5213 p
= COLOR (new, x
, img
->height
- 1);
5214 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5217 for (y
= 1; y
< img
->height
- 1; ++y
)
5219 p
= COLOR (new, 1, y
);
5221 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5223 int r
, g
, b
, y1
, x1
;
5226 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5227 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5230 XColor
*t
= COLOR (colors
, x1
, y1
);
5231 r
+= matrix
[i
] * t
->red
;
5232 g
+= matrix
[i
] * t
->green
;
5233 b
+= matrix
[i
] * t
->blue
;
5236 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5237 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5238 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5239 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5244 x_from_xcolors (f
, img
, new);
5250 /* Perform the pre-defined `emboss' edge-detection on image IMG
5258 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5262 /* Transform image IMG which is used on frame F with a Laplace
5263 edge-detection algorithm. The result is an image that can be used
5264 to draw disabled buttons, for example. */
5271 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5275 /* Perform edge-detection on image IMG on frame F, with specified
5276 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5278 MATRIX must be either
5280 - a list of at least 9 numbers in row-major form
5281 - a vector of at least 9 numbers
5283 COLOR_ADJUST nil means use a default; otherwise it must be a
5287 x_edge_detection (f
, img
, matrix
, color_adjust
)
5290 Lisp_Object matrix
, color_adjust
;
5298 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5299 ++i
, matrix
= XCDR (matrix
))
5300 trans
[i
] = XFLOATINT (XCAR (matrix
));
5302 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5304 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5305 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5308 if (NILP (color_adjust
))
5309 color_adjust
= make_number (0xffff / 2);
5311 if (i
== 9 && NUMBERP (color_adjust
))
5312 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5316 /* Transform image IMG on frame F so that it looks disabled. */
5319 x_disable_image (f
, img
)
5323 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5325 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5327 int n_planes
= dpyinfo
->n_planes
;
5328 #endif /* HAVE_NTGUI */
5332 /* Color (or grayscale). Convert to gray, and equalize. Just
5333 drawing such images with a stipple can look very odd, so
5334 we're using this method instead. */
5335 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5337 const int h
= 15000;
5338 const int l
= 30000;
5340 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5344 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5345 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5346 p
->red
= p
->green
= p
->blue
= i2
;
5349 x_from_xcolors (f
, img
, colors
);
5352 /* Draw a cross over the disabled image, if we must or if we
5354 if (n_planes
< 2 || cross_disabled_images
)
5357 Display
*dpy
= FRAME_X_DISPLAY (f
);
5361 #define MaskForeground(f) PIX_MASK_DRAW
5363 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5366 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5367 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5368 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5369 img
->width
- 1, img
->height
- 1);
5370 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5376 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5377 XSetForeground (dpy
, gc
, MaskForeground (f
));
5378 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5379 img
->width
- 1, img
->height
- 1);
5380 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5388 hdc
= get_frame_dc (f
);
5389 bmpdc
= CreateCompatibleDC (hdc
);
5390 release_frame_dc (f
, hdc
);
5392 prev
= SelectObject (bmpdc
, img
->pixmap
);
5394 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5395 MoveToEx (bmpdc
, 0, 0, NULL
);
5396 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5397 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5398 LineTo (bmpdc
, img
->width
- 1, 0);
5402 SelectObject (bmpdc
, img
->mask
);
5403 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5404 MoveToEx (bmpdc
, 0, 0, NULL
);
5405 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5406 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5407 LineTo (bmpdc
, img
->width
- 1, 0);
5409 SelectObject (bmpdc
, prev
);
5411 #endif /* HAVE_NTGUI */
5416 /* Build a mask for image IMG which is used on frame F. FILE is the
5417 name of an image file, for error messages. HOW determines how to
5418 determine the background color of IMG. If it is a list '(R G B)',
5419 with R, G, and B being integers >= 0, take that as the color of the
5420 background. Otherwise, determine the background color of IMG
5421 heuristically. Value is non-zero if successful. */
5424 x_build_heuristic_mask (f
, img
, how
)
5429 XImagePtr_or_DC ximg
;
5437 #endif /* HAVE_NTGUI */
5438 int x
, y
, rc
, use_img_background
;
5439 unsigned long bg
= 0;
5443 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5444 img
->mask
= NO_PIXMAP
;
5445 img
->background_transparent_valid
= 0;
5449 /* Create an image and pixmap serving as mask. */
5450 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5451 &mask_img
, &img
->mask
);
5455 /* Get the X image of IMG->pixmap. */
5456 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5457 img
->width
, img
->height
,
5460 /* Create the bit array serving as mask. */
5461 row_width
= (img
->width
+ 7) / 8;
5462 mask_img
= xmalloc (row_width
* img
->height
);
5463 bzero (mask_img
, row_width
* img
->height
);
5465 /* Create a memory device context for IMG->pixmap. */
5466 frame_dc
= get_frame_dc (f
);
5467 ximg
= CreateCompatibleDC (frame_dc
);
5468 release_frame_dc (f
, frame_dc
);
5469 prev
= SelectObject (ximg
, img
->pixmap
);
5470 #endif /* HAVE_NTGUI */
5472 /* Determine the background color of ximg. If HOW is `(R G B)'
5473 take that as color. Otherwise, use the image's background color. */
5474 use_img_background
= 1;
5480 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5482 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5486 if (i
== 3 && NILP (how
))
5488 char color_name
[30];
5489 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5492 0x00ffffff & /* Filter out palette info. */
5493 #endif /* HAVE_NTGUI */
5494 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5495 use_img_background
= 0;
5499 if (use_img_background
)
5500 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5502 /* Set all bits in mask_img to 1 whose color in ximg is different
5503 from the background color bg. */
5505 for (y
= 0; y
< img
->height
; ++y
)
5506 for (x
= 0; x
< img
->width
; ++x
)
5507 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5508 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5510 /* Fill in the background_transparent field while we have the mask handy. */
5511 image_background_transparent (img
, f
, mask_img
);
5513 /* Put mask_img into img->mask. */
5514 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5515 x_destroy_x_image (mask_img
);
5518 for (y
= 0; y
< img
->height
; ++y
)
5519 for (x
= 0; x
< img
->width
; ++x
)
5521 COLORREF p
= GetPixel (ximg
, x
, y
);
5523 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5526 /* Create the mask image. */
5527 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5529 /* Fill in the background_transparent field while we have the mask handy. */
5530 SelectObject (ximg
, img
->mask
);
5531 image_background_transparent (img
, f
, ximg
);
5533 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5535 #endif /* HAVE_NTGUI */
5537 Destroy_Image (ximg
, prev
);
5543 /***********************************************************************
5544 PBM (mono, gray, color)
5545 ***********************************************************************/
5547 static int pbm_image_p
P_ ((Lisp_Object object
));
5548 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5549 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5551 /* The symbol `pbm' identifying images of this type. */
5555 /* Indices of image specification fields in gs_format, below. */
5557 enum pbm_keyword_index
5573 /* Vector of image_keyword structures describing the format
5574 of valid user-defined image specifications. */
5576 static struct image_keyword pbm_format
[PBM_LAST
] =
5578 {":type", IMAGE_SYMBOL_VALUE
, 1},
5579 {":file", IMAGE_STRING_VALUE
, 0},
5580 {":data", IMAGE_STRING_VALUE
, 0},
5581 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5582 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5583 {":relief", IMAGE_INTEGER_VALUE
, 0},
5584 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5585 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5586 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5587 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5588 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5591 /* Structure describing the image type `pbm'. */
5593 static struct image_type pbm_type
=
5603 /* Return non-zero if OBJECT is a valid PBM image specification. */
5606 pbm_image_p (object
)
5609 struct image_keyword fmt
[PBM_LAST
];
5611 bcopy (pbm_format
, fmt
, sizeof fmt
);
5613 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5616 /* Must specify either :data or :file. */
5617 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5621 /* Scan a decimal number from *S and return it. Advance *S while
5622 reading the number. END is the end of the string. Value is -1 at
5626 pbm_scan_number (s
, end
)
5627 unsigned char **s
, *end
;
5629 int c
= 0, val
= -1;
5633 /* Skip white-space. */
5634 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5639 /* Skip comment to end of line. */
5640 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5643 else if (isdigit (c
))
5645 /* Read decimal number. */
5647 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5648 val
= 10 * val
+ c
- '0';
5660 #if 0 /* Unused. ++kfs */
5662 /* Read FILE into memory. Value is a pointer to a buffer allocated
5663 with xmalloc holding FILE's contents. Value is null if an error
5664 occurred. *SIZE is set to the size of the file. */
5667 pbm_read_file (file
, size
)
5675 if (stat (SDATA (file
), &st
) == 0
5676 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5677 && (buf
= (char *) xmalloc (st
.st_size
),
5678 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5697 #endif /* HAVE_NTGUI */
5699 /* Load PBM image IMG for use on frame F. */
5707 int width
, height
, max_color_idx
= 0;
5709 Lisp_Object file
, specified_file
;
5710 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5711 struct gcpro gcpro1
;
5712 unsigned char *contents
= NULL
;
5713 unsigned char *end
, *p
;
5716 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5720 if (STRINGP (specified_file
))
5722 file
= x_find_image_file (specified_file
);
5723 if (!STRINGP (file
))
5725 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5730 contents
= slurp_file (SDATA (file
), &size
);
5731 if (contents
== NULL
)
5733 image_error ("Error reading `%s'", file
, Qnil
);
5739 end
= contents
+ size
;
5744 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5746 end
= p
+ SBYTES (data
);
5749 /* Check magic number. */
5750 if (end
- p
< 2 || *p
++ != 'P')
5752 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5762 raw_p
= 0, type
= PBM_MONO
;
5766 raw_p
= 0, type
= PBM_GRAY
;
5770 raw_p
= 0, type
= PBM_COLOR
;
5774 raw_p
= 1, type
= PBM_MONO
;
5778 raw_p
= 1, type
= PBM_GRAY
;
5782 raw_p
= 1, type
= PBM_COLOR
;
5786 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5790 /* Read width, height, maximum color-component. Characters
5791 starting with `#' up to the end of a line are ignored. */
5792 width
= pbm_scan_number (&p
, end
);
5793 height
= pbm_scan_number (&p
, end
);
5795 if (type
!= PBM_MONO
)
5797 max_color_idx
= pbm_scan_number (&p
, end
);
5798 if (raw_p
&& max_color_idx
> 255)
5799 max_color_idx
= 255;
5802 if (!check_image_size (f
, width
, height
)
5803 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5806 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5807 &ximg
, &img
->pixmap
))
5810 /* Initialize the color hash table. */
5811 init_color_table ();
5813 if (type
== PBM_MONO
)
5816 struct image_keyword fmt
[PBM_LAST
];
5817 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5818 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5820 /* Parse the image specification. */
5821 bcopy (pbm_format
, fmt
, sizeof fmt
);
5822 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5824 /* Get foreground and background colors, maybe allocate colors. */
5825 if (fmt
[PBM_FOREGROUND
].count
5826 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5827 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5828 if (fmt
[PBM_BACKGROUND
].count
5829 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5831 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5832 img
->background
= bg
;
5833 img
->background_valid
= 1;
5836 for (y
= 0; y
< height
; ++y
)
5837 for (x
= 0; x
< width
; ++x
)
5845 x_destroy_x_image (ximg
);
5846 x_clear_image (f
, img
);
5847 image_error ("Invalid image size in image `%s'",
5857 g
= pbm_scan_number (&p
, end
);
5859 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5865 && ((type
== PBM_GRAY
)
5866 ? (p
+ height
* width
> end
)
5867 : (p
+ 3 * height
* width
> end
)))
5869 x_destroy_x_image (ximg
);
5870 x_clear_image (f
, img
);
5871 image_error ("Invalid image size in image `%s'",
5876 for (y
= 0; y
< height
; ++y
)
5877 for (x
= 0; x
< width
; ++x
)
5881 if (type
== PBM_GRAY
)
5882 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5891 r
= pbm_scan_number (&p
, end
);
5892 g
= pbm_scan_number (&p
, end
);
5893 b
= pbm_scan_number (&p
, end
);
5896 if (r
< 0 || g
< 0 || b
< 0)
5898 x_destroy_x_image (ximg
);
5899 image_error ("Invalid pixel value in image `%s'",
5904 /* RGB values are now in the range 0..max_color_idx.
5905 Scale this to the range 0..0xffff supported by X. */
5906 r
= (double) r
* 65535 / max_color_idx
;
5907 g
= (double) g
* 65535 / max_color_idx
;
5908 b
= (double) b
* 65535 / max_color_idx
;
5909 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5913 #ifdef COLOR_TABLE_SUPPORT
5914 /* Store in IMG->colors the colors allocated for the image, and
5915 free the color table. */
5916 img
->colors
= colors_in_color_table (&img
->ncolors
);
5917 free_color_table ();
5918 #endif /* COLOR_TABLE_SUPPORT */
5921 img
->height
= height
;
5923 /* Maybe fill in the background field while we have ximg handy. */
5925 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5926 /* Casting avoids a GCC warning. */
5927 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5929 /* Put the image into a pixmap. */
5930 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5931 x_destroy_x_image (ximg
);
5933 /* X and W32 versions did it here, MAC version above. ++kfs
5935 img->height = height; */
5943 /***********************************************************************
5945 ***********************************************************************/
5947 #if defined (HAVE_PNG) || defined (MAC_OS)
5949 /* Function prototypes. */
5951 static int png_image_p
P_ ((Lisp_Object object
));
5952 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5954 /* The symbol `png' identifying images of this type. */
5958 /* Indices of image specification fields in png_format, below. */
5960 enum png_keyword_index
5975 /* Vector of image_keyword structures describing the format
5976 of valid user-defined image specifications. */
5978 static struct image_keyword png_format
[PNG_LAST
] =
5980 {":type", IMAGE_SYMBOL_VALUE
, 1},
5981 {":data", IMAGE_STRING_VALUE
, 0},
5982 {":file", IMAGE_STRING_VALUE
, 0},
5983 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5984 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5985 {":relief", IMAGE_INTEGER_VALUE
, 0},
5986 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5987 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5988 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5989 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5992 /* Structure describing the image type `png'. */
5994 static struct image_type png_type
=
6003 /* Return non-zero if OBJECT is a valid PNG image specification. */
6006 png_image_p (object
)
6009 struct image_keyword fmt
[PNG_LAST
];
6010 bcopy (png_format
, fmt
, sizeof fmt
);
6012 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
6015 /* Must specify either the :data or :file keyword. */
6016 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
6019 #endif /* HAVE_PNG || MAC_OS */
6024 #if defined HAVE_LIBPNG_PNG_H
6025 # include <libpng/png.h>
6031 /* PNG library details. */
6033 DEF_IMGLIB_FN (png_get_io_ptr
);
6034 DEF_IMGLIB_FN (png_check_sig
);
6035 DEF_IMGLIB_FN (png_create_read_struct
);
6036 DEF_IMGLIB_FN (png_create_info_struct
);
6037 DEF_IMGLIB_FN (png_destroy_read_struct
);
6038 DEF_IMGLIB_FN (png_set_read_fn
);
6039 DEF_IMGLIB_FN (png_set_sig_bytes
);
6040 DEF_IMGLIB_FN (png_read_info
);
6041 DEF_IMGLIB_FN (png_get_IHDR
);
6042 DEF_IMGLIB_FN (png_get_valid
);
6043 DEF_IMGLIB_FN (png_set_strip_16
);
6044 DEF_IMGLIB_FN (png_set_expand
);
6045 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6046 DEF_IMGLIB_FN (png_set_background
);
6047 DEF_IMGLIB_FN (png_get_bKGD
);
6048 DEF_IMGLIB_FN (png_read_update_info
);
6049 DEF_IMGLIB_FN (png_get_channels
);
6050 DEF_IMGLIB_FN (png_get_rowbytes
);
6051 DEF_IMGLIB_FN (png_read_image
);
6052 DEF_IMGLIB_FN (png_read_end
);
6053 DEF_IMGLIB_FN (png_error
);
6056 init_png_functions (Lisp_Object libraries
)
6060 /* Try loading libpng under probable names. */
6061 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6064 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6065 LOAD_IMGLIB_FN (library
, png_check_sig
);
6066 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6067 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6068 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6069 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6070 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6071 LOAD_IMGLIB_FN (library
, png_read_info
);
6072 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6073 LOAD_IMGLIB_FN (library
, png_get_valid
);
6074 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6075 LOAD_IMGLIB_FN (library
, png_set_expand
);
6076 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6077 LOAD_IMGLIB_FN (library
, png_set_background
);
6078 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6079 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6080 LOAD_IMGLIB_FN (library
, png_get_channels
);
6081 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6082 LOAD_IMGLIB_FN (library
, png_read_image
);
6083 LOAD_IMGLIB_FN (library
, png_read_end
);
6084 LOAD_IMGLIB_FN (library
, png_error
);
6089 #define fn_png_get_io_ptr png_get_io_ptr
6090 #define fn_png_check_sig png_check_sig
6091 #define fn_png_create_read_struct png_create_read_struct
6092 #define fn_png_create_info_struct png_create_info_struct
6093 #define fn_png_destroy_read_struct png_destroy_read_struct
6094 #define fn_png_set_read_fn png_set_read_fn
6095 #define fn_png_set_sig_bytes png_set_sig_bytes
6096 #define fn_png_read_info png_read_info
6097 #define fn_png_get_IHDR png_get_IHDR
6098 #define fn_png_get_valid png_get_valid
6099 #define fn_png_set_strip_16 png_set_strip_16
6100 #define fn_png_set_expand png_set_expand
6101 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6102 #define fn_png_set_background png_set_background
6103 #define fn_png_get_bKGD png_get_bKGD
6104 #define fn_png_read_update_info png_read_update_info
6105 #define fn_png_get_channels png_get_channels
6106 #define fn_png_get_rowbytes png_get_rowbytes
6107 #define fn_png_read_image png_read_image
6108 #define fn_png_read_end png_read_end
6109 #define fn_png_error png_error
6111 #endif /* HAVE_NTGUI */
6113 /* Error and warning handlers installed when the PNG library
6117 my_png_error (png_ptr
, msg
)
6118 png_struct
*png_ptr
;
6121 xassert (png_ptr
!= NULL
);
6122 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6123 longjmp (png_ptr
->jmpbuf
, 1);
6128 my_png_warning (png_ptr
, msg
)
6129 png_struct
*png_ptr
;
6132 xassert (png_ptr
!= NULL
);
6133 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6136 /* Memory source for PNG decoding. */
6138 struct png_memory_storage
6140 unsigned char *bytes
; /* The data */
6141 size_t len
; /* How big is it? */
6142 int index
; /* Where are we? */
6146 /* Function set as reader function when reading PNG image from memory.
6147 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6148 bytes from the input to DATA. */
6151 png_read_from_memory (png_ptr
, data
, length
)
6152 png_structp png_ptr
;
6156 struct png_memory_storage
*tbr
6157 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6159 if (length
> tbr
->len
- tbr
->index
)
6160 fn_png_error (png_ptr
, "Read error");
6162 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6163 tbr
->index
= tbr
->index
+ length
;
6167 /* Function set as reader function when reading PNG image from a file.
6168 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6169 bytes from the input to DATA. */
6172 png_read_from_file (png_ptr
, data
, length
)
6173 png_structp png_ptr
;
6177 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6179 if (fread (data
, 1, length
, fp
) < length
)
6180 fn_png_error (png_ptr
, "Read error");
6184 /* Load PNG image IMG for use on frame F. Value is non-zero if
6192 Lisp_Object file
, specified_file
;
6193 Lisp_Object specified_data
;
6195 XImagePtr ximg
, mask_img
= NULL
;
6196 struct gcpro gcpro1
;
6197 png_struct
*png_ptr
= NULL
;
6198 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6199 FILE *volatile fp
= NULL
;
6201 png_byte
* volatile pixels
= NULL
;
6202 png_byte
** volatile rows
= NULL
;
6203 png_uint_32 width
, height
;
6204 int bit_depth
, color_type
, interlace_type
;
6206 png_uint_32 row_bytes
;
6208 double screen_gamma
;
6209 struct png_memory_storage tbr
; /* Data to be read */
6211 /* Find out what file to load. */
6212 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6213 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6217 if (NILP (specified_data
))
6219 file
= x_find_image_file (specified_file
);
6220 if (!STRINGP (file
))
6222 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6227 /* Open the image file. */
6228 fp
= fopen (SDATA (file
), "rb");
6231 image_error ("Cannot open image file `%s'", file
, Qnil
);
6236 /* Check PNG signature. */
6237 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6238 || !fn_png_check_sig (sig
, sizeof sig
))
6240 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6248 /* Read from memory. */
6249 tbr
.bytes
= SDATA (specified_data
);
6250 tbr
.len
= SBYTES (specified_data
);
6253 /* Check PNG signature. */
6254 if (tbr
.len
< sizeof sig
6255 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6257 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6262 /* Need to skip past the signature. */
6263 tbr
.bytes
+= sizeof (sig
);
6266 /* Initialize read and info structs for PNG lib. Casting return
6267 value avoids a GCC warning on W32. */
6268 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6273 if (fp
) fclose (fp
);
6278 /* Casting return value avoids a GCC warning on W32. */
6279 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6282 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6283 if (fp
) fclose (fp
);
6288 /* Casting return value avoids a GCC warning on W32. */
6289 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6292 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6293 if (fp
) fclose (fp
);
6298 /* Set error jump-back. We come back here when the PNG library
6299 detects an error. */
6300 if (setjmp (png_ptr
->jmpbuf
))
6304 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6307 if (fp
) fclose (fp
);
6312 /* Read image info. */
6313 if (!NILP (specified_data
))
6314 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6316 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6318 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6319 fn_png_read_info (png_ptr
, info_ptr
);
6320 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6321 &interlace_type
, NULL
, NULL
);
6323 if (!check_image_size (f
, width
, height
))
6326 /* If image contains simply transparency data, we prefer to
6327 construct a clipping mask. */
6328 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6333 /* This function is easier to write if we only have to handle
6334 one data format: RGB or RGBA with 8 bits per channel. Let's
6335 transform other formats into that format. */
6337 /* Strip more than 8 bits per channel. */
6338 if (bit_depth
== 16)
6339 fn_png_set_strip_16 (png_ptr
);
6341 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6343 fn_png_set_expand (png_ptr
);
6345 /* Convert grayscale images to RGB. */
6346 if (color_type
== PNG_COLOR_TYPE_GRAY
6347 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6348 fn_png_set_gray_to_rgb (png_ptr
);
6350 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
6352 #if 0 /* Avoid double gamma correction for PNG images. */
6353 { /* Tell the PNG lib to handle gamma correction for us. */
6356 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6357 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
6358 /* The libpng documentation says this is right in this case. */
6359 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6362 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
6363 /* Image contains gamma information. */
6364 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
6366 /* Use the standard default for the image gamma. */
6367 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6371 /* Handle alpha channel by combining the image with a background
6372 color. Do this only if a real alpha channel is supplied. For
6373 simple transparency, we prefer a clipping mask. */
6376 /* png_color_16 *image_bg; */
6377 Lisp_Object specified_bg
6378 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6380 if (STRINGP (specified_bg
))
6381 /* The user specified `:background', use that. */
6383 /* W32 version incorrectly used COLORREF here!! ++kfs */
6385 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6387 png_color_16 user_bg
;
6389 bzero (&user_bg
, sizeof user_bg
);
6390 user_bg
.red
= color
.red
>> 8;
6391 user_bg
.green
= color
.green
>> 8;
6392 user_bg
.blue
= color
.blue
>> 8;
6394 fn_png_set_background (png_ptr
, &user_bg
,
6395 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6398 /* The commented-out code checked if the png specifies a default
6399 background color, and uses that. Since we use the current
6400 frame background, it is OK for us to ignore this.
6402 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
6403 fn_png_set_background (png_ptr, image_bg,
6404 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6408 /* Image does not contain a background color with which
6409 to combine the image data via an alpha channel. Use
6410 the frame's background instead. */
6411 #ifdef HAVE_X_WINDOWS
6413 png_color_16 frame_background
;
6415 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6416 x_query_color (f
, &color
);
6418 bzero (&frame_background
, sizeof frame_background
);
6419 frame_background
.red
= color
.red
>> 8;
6420 frame_background
.green
= color
.green
>> 8;
6421 frame_background
.blue
= color
.blue
>> 8;
6422 #endif /* HAVE_X_WINDOWS */
6426 png_color_16 frame_background
;
6427 color
= FRAME_BACKGROUND_PIXEL (f
);
6428 #if 0 /* W32 TODO : Colormap support. */
6429 x_query_color (f
, &color
);
6431 bzero (&frame_background
, sizeof frame_background
);
6432 frame_background
.red
= GetRValue (color
);
6433 frame_background
.green
= GetGValue (color
);
6434 frame_background
.blue
= GetBValue (color
);
6435 #endif /* HAVE_NTGUI */
6438 unsigned long color
;
6439 png_color_16 frame_background
;
6440 color
= FRAME_BACKGROUND_PIXEL (f
);
6441 #if 0 /* MAC/W32 TODO : Colormap support. */
6442 x_query_color (f
, &color
);
6444 bzero (&frame_background
, sizeof frame_background
);
6445 frame_background
.red
= RED_FROM_ULONG (color
);
6446 frame_background
.green
= GREEN_FROM_ULONG (color
);
6447 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6450 fn_png_set_background (png_ptr
, &frame_background
,
6451 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6455 /* Update info structure. */
6456 fn_png_read_update_info (png_ptr
, info_ptr
);
6458 /* Get number of channels. Valid values are 1 for grayscale images
6459 and images with a palette, 2 for grayscale images with transparency
6460 information (alpha channel), 3 for RGB images, and 4 for RGB
6461 images with alpha channel, i.e. RGBA. If conversions above were
6462 sufficient we should only have 3 or 4 channels here. */
6463 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6464 xassert (channels
== 3 || channels
== 4);
6466 /* Number of bytes needed for one row of the image. */
6467 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6469 /* Allocate memory for the image. */
6470 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6471 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6472 for (i
= 0; i
< height
; ++i
)
6473 rows
[i
] = pixels
+ i
* row_bytes
;
6475 /* Read the entire image. */
6476 fn_png_read_image (png_ptr
, rows
);
6477 fn_png_read_end (png_ptr
, info_ptr
);
6484 /* Create the X image and pixmap. */
6485 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6489 /* Create an image and pixmap serving as mask if the PNG image
6490 contains an alpha channel. */
6493 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6494 &mask_img
, &img
->mask
))
6496 x_destroy_x_image (ximg
);
6497 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6498 img
->pixmap
= NO_PIXMAP
;
6502 /* Fill the X image and mask from PNG data. */
6503 init_color_table ();
6505 for (y
= 0; y
< height
; ++y
)
6507 png_byte
*p
= rows
[y
];
6509 for (x
= 0; x
< width
; ++x
)
6516 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6517 /* An alpha channel, aka mask channel, associates variable
6518 transparency with an image. Where other image formats
6519 support binary transparency---fully transparent or fully
6520 opaque---PNG allows up to 254 levels of partial transparency.
6521 The PNG library implements partial transparency by combining
6522 the image with a specified background color.
6524 I'm not sure how to handle this here nicely: because the
6525 background on which the image is displayed may change, for
6526 real alpha channel support, it would be necessary to create
6527 a new image for each possible background.
6529 What I'm doing now is that a mask is created if we have
6530 boolean transparency information. Otherwise I'm using
6531 the frame's background color to combine the image with. */
6536 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6542 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6543 /* Set IMG's background color from the PNG image, unless the user
6547 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6549 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6550 img
->background_valid
= 1;
6554 #ifdef COLOR_TABLE_SUPPORT
6555 /* Remember colors allocated for this image. */
6556 img
->colors
= colors_in_color_table (&img
->ncolors
);
6557 free_color_table ();
6558 #endif /* COLOR_TABLE_SUPPORT */
6561 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6566 img
->height
= height
;
6568 /* Maybe fill in the background field while we have ximg handy.
6569 Casting avoids a GCC warning. */
6570 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6572 /* Put the image into the pixmap, then free the X image and its buffer. */
6573 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6574 x_destroy_x_image (ximg
);
6576 /* Same for the mask. */
6579 /* Fill in the background_transparent field while we have the
6580 mask handy. Casting avoids a GCC warning. */
6581 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6583 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6584 x_destroy_x_image (mask_img
);
6591 #else /* HAVE_PNG */
6600 if (MyCGImageCreateWithPNGDataProvider
)
6601 return image_load_quartz2d (f
, img
, 1);
6604 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6608 #endif /* !HAVE_PNG */
6612 /***********************************************************************
6614 ***********************************************************************/
6616 #if defined (HAVE_JPEG) || defined (MAC_OS)
6618 static int jpeg_image_p
P_ ((Lisp_Object object
));
6619 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6621 /* The symbol `jpeg' identifying images of this type. */
6625 /* Indices of image specification fields in gs_format, below. */
6627 enum jpeg_keyword_index
6636 JPEG_HEURISTIC_MASK
,
6642 /* Vector of image_keyword structures describing the format
6643 of valid user-defined image specifications. */
6645 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6647 {":type", IMAGE_SYMBOL_VALUE
, 1},
6648 {":data", IMAGE_STRING_VALUE
, 0},
6649 {":file", IMAGE_STRING_VALUE
, 0},
6650 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6651 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6652 {":relief", IMAGE_INTEGER_VALUE
, 0},
6653 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6654 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6655 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6656 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6659 /* Structure describing the image type `jpeg'. */
6661 static struct image_type jpeg_type
=
6670 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6673 jpeg_image_p (object
)
6676 struct image_keyword fmt
[JPEG_LAST
];
6678 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6680 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6683 /* Must specify either the :data or :file keyword. */
6684 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6687 #endif /* HAVE_JPEG || MAC_OS */
6691 /* Work around a warning about HAVE_STDLIB_H being redefined in
6693 #ifdef HAVE_STDLIB_H
6694 #define HAVE_STDLIB_H_1
6695 #undef HAVE_STDLIB_H
6696 #endif /* HAVE_STLIB_H */
6698 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6699 /* In older releases of the jpeg library, jpeglib.h will define boolean
6700 differently depending on __WIN32__, so make sure it is defined. */
6704 #include <jpeglib.h>
6708 #ifdef HAVE_STLIB_H_1
6709 #define HAVE_STDLIB_H 1
6714 /* JPEG library details. */
6715 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6716 DEF_IMGLIB_FN (jpeg_start_decompress
);
6717 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6718 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6719 DEF_IMGLIB_FN (jpeg_read_header
);
6720 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6721 DEF_IMGLIB_FN (jpeg_std_error
);
6722 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6725 init_jpeg_functions (Lisp_Object libraries
)
6729 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6732 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6733 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6734 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6735 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6736 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6737 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6738 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6739 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6743 /* Wrapper since we can't directly assign the function pointer
6744 to another function pointer that was declared more completely easily. */
6746 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
6747 j_decompress_ptr cinfo
;
6750 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6755 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6756 #define fn_jpeg_start_decompress jpeg_start_decompress
6757 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6758 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6759 #define fn_jpeg_read_header jpeg_read_header
6760 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6761 #define fn_jpeg_std_error jpeg_std_error
6762 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6764 #endif /* HAVE_NTGUI */
6766 struct my_jpeg_error_mgr
6768 struct jpeg_error_mgr pub
;
6769 jmp_buf setjmp_buffer
;
6774 my_error_exit (cinfo
)
6777 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6778 longjmp (mgr
->setjmp_buffer
, 1);
6782 /* Init source method for JPEG data source manager. Called by
6783 jpeg_read_header() before any data is actually read. See
6784 libjpeg.doc from the JPEG lib distribution. */
6787 our_common_init_source (cinfo
)
6788 j_decompress_ptr cinfo
;
6793 /* Method to terminate data source. Called by
6794 jpeg_finish_decompress() after all data has been processed. */
6797 our_common_term_source (cinfo
)
6798 j_decompress_ptr cinfo
;
6803 /* Fill input buffer method for JPEG data source manager. Called
6804 whenever more data is needed. We read the whole image in one step,
6805 so this only adds a fake end of input marker at the end. */
6807 static JOCTET our_memory_buffer
[2];
6810 our_memory_fill_input_buffer (cinfo
)
6811 j_decompress_ptr cinfo
;
6813 /* Insert a fake EOI marker. */
6814 struct jpeg_source_mgr
*src
= cinfo
->src
;
6816 our_memory_buffer
[0] = (JOCTET
) 0xFF;
6817 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
6819 src
->next_input_byte
= our_memory_buffer
;
6820 src
->bytes_in_buffer
= 2;
6825 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6826 is the JPEG data source manager. */
6829 our_memory_skip_input_data (cinfo
, num_bytes
)
6830 j_decompress_ptr cinfo
;
6833 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6837 if (num_bytes
> src
->bytes_in_buffer
)
6838 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6840 src
->bytes_in_buffer
-= num_bytes
;
6841 src
->next_input_byte
+= num_bytes
;
6846 /* Set up the JPEG lib for reading an image from DATA which contains
6847 LEN bytes. CINFO is the decompression info structure created for
6848 reading the image. */
6851 jpeg_memory_src (cinfo
, data
, len
)
6852 j_decompress_ptr cinfo
;
6856 struct jpeg_source_mgr
*src
;
6858 if (cinfo
->src
== NULL
)
6860 /* First time for this JPEG object? */
6861 cinfo
->src
= (struct jpeg_source_mgr
*)
6862 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6863 sizeof (struct jpeg_source_mgr
));
6864 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6865 src
->next_input_byte
= data
;
6868 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6869 src
->init_source
= our_common_init_source
;
6870 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6871 src
->skip_input_data
= our_memory_skip_input_data
;
6872 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6873 src
->term_source
= our_common_term_source
;
6874 src
->bytes_in_buffer
= len
;
6875 src
->next_input_byte
= data
;
6879 struct jpeg_stdio_mgr
6881 struct jpeg_source_mgr mgr
;
6888 /* Size of buffer to read JPEG from file.
6889 Not too big, as we want to use alloc_small. */
6890 #define JPEG_STDIO_BUFFER_SIZE 8192
6893 /* Fill input buffer method for JPEG data source manager. Called
6894 whenever more data is needed. The data is read from a FILE *. */
6897 our_stdio_fill_input_buffer (cinfo
)
6898 j_decompress_ptr cinfo
;
6900 struct jpeg_stdio_mgr
*src
;
6902 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6907 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6909 src
->mgr
.bytes_in_buffer
= bytes
;
6912 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6914 src
->buffer
[0] = (JOCTET
) 0xFF;
6915 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6916 src
->mgr
.bytes_in_buffer
= 2;
6918 src
->mgr
.next_input_byte
= src
->buffer
;
6925 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6926 is the JPEG data source manager. */
6929 our_stdio_skip_input_data (cinfo
, num_bytes
)
6930 j_decompress_ptr cinfo
;
6933 struct jpeg_stdio_mgr
*src
;
6934 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6936 while (num_bytes
> 0 && !src
->finished
)
6938 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6940 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6941 src
->mgr
.next_input_byte
+= num_bytes
;
6946 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6947 src
->mgr
.bytes_in_buffer
= 0;
6948 src
->mgr
.next_input_byte
= NULL
;
6950 our_stdio_fill_input_buffer (cinfo
);
6956 /* Set up the JPEG lib for reading an image from a FILE *.
6957 CINFO is the decompression info structure created for
6958 reading the image. */
6961 jpeg_file_src (cinfo
, fp
)
6962 j_decompress_ptr cinfo
;
6965 struct jpeg_stdio_mgr
*src
;
6967 if (cinfo
->src
!= NULL
)
6968 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6971 /* First time for this JPEG object? */
6972 cinfo
->src
= (struct jpeg_source_mgr
*)
6973 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6974 sizeof (struct jpeg_stdio_mgr
));
6975 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6976 src
->buffer
= (JOCTET
*)
6977 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6978 JPEG_STDIO_BUFFER_SIZE
);
6983 src
->mgr
.init_source
= our_common_init_source
;
6984 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6985 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6986 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6987 src
->mgr
.term_source
= our_common_term_source
;
6988 src
->mgr
.bytes_in_buffer
= 0;
6989 src
->mgr
.next_input_byte
= NULL
;
6993 /* Load image IMG for use on frame F. Patterned after example.c
6994 from the JPEG lib. */
7001 struct jpeg_decompress_struct cinfo
;
7002 struct my_jpeg_error_mgr mgr
;
7003 Lisp_Object file
, specified_file
;
7004 Lisp_Object specified_data
;
7005 FILE * volatile fp
= NULL
;
7007 int row_stride
, x
, y
;
7008 XImagePtr ximg
= NULL
;
7010 unsigned long *colors
;
7012 struct gcpro gcpro1
;
7014 /* Open the JPEG file. */
7015 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7016 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7020 if (NILP (specified_data
))
7022 file
= x_find_image_file (specified_file
);
7023 if (!STRINGP (file
))
7025 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7030 fp
= fopen (SDATA (file
), "rb");
7033 image_error ("Cannot open `%s'", file
, Qnil
);
7039 /* Customize libjpeg's error handling to call my_error_exit when an
7040 error is detected. This function will perform a longjmp.
7041 Casting return value avoids a GCC warning on W32. */
7042 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7043 mgr
.pub
.error_exit
= my_error_exit
;
7045 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7049 /* Called from my_error_exit. Display a JPEG error. */
7050 char buffer
[JMSG_LENGTH_MAX
];
7051 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7052 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7053 build_string (buffer
));
7056 /* Close the input file and destroy the JPEG object. */
7058 fclose ((FILE *) fp
);
7059 fn_jpeg_destroy_decompress (&cinfo
);
7061 /* If we already have an XImage, free that. */
7062 x_destroy_x_image (ximg
);
7064 /* Free pixmap and colors. */
7065 x_clear_image (f
, img
);
7071 /* Create the JPEG decompression object. Let it read from fp.
7072 Read the JPEG image header. */
7073 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7075 if (NILP (specified_data
))
7076 jpeg_file_src (&cinfo
, (FILE *) fp
);
7078 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7079 SBYTES (specified_data
));
7081 fn_jpeg_read_header (&cinfo
, 1);
7083 /* Customize decompression so that color quantization will be used.
7084 Start decompression. */
7085 cinfo
.quantize_colors
= 1;
7086 fn_jpeg_start_decompress (&cinfo
);
7087 width
= img
->width
= cinfo
.output_width
;
7088 height
= img
->height
= cinfo
.output_height
;
7090 if (!check_image_size (f
, width
, height
))
7092 image_error ("Invalid image size", Qnil
, Qnil
);
7093 longjmp (mgr
.setjmp_buffer
, 2);
7096 /* Create X image and pixmap. */
7097 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7098 longjmp (mgr
.setjmp_buffer
, 2);
7100 /* Allocate colors. When color quantization is used,
7101 cinfo.actual_number_of_colors has been set with the number of
7102 colors generated, and cinfo.colormap is a two-dimensional array
7103 of color indices in the range 0..cinfo.actual_number_of_colors.
7104 No more than 255 colors will be generated. */
7108 if (cinfo
.out_color_components
> 2)
7109 ir
= 0, ig
= 1, ib
= 2;
7110 else if (cinfo
.out_color_components
> 1)
7111 ir
= 0, ig
= 1, ib
= 0;
7113 ir
= 0, ig
= 0, ib
= 0;
7115 /* Use the color table mechanism because it handles colors that
7116 cannot be allocated nicely. Such colors will be replaced with
7117 a default color, and we don't have to care about which colors
7118 can be freed safely, and which can't. */
7119 init_color_table ();
7120 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7123 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7125 /* Multiply RGB values with 255 because X expects RGB values
7126 in the range 0..0xffff. */
7127 int r
= cinfo
.colormap
[ir
][i
] << 8;
7128 int g
= cinfo
.colormap
[ig
][i
] << 8;
7129 int b
= cinfo
.colormap
[ib
][i
] << 8;
7130 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7133 #ifdef COLOR_TABLE_SUPPORT
7134 /* Remember those colors actually allocated. */
7135 img
->colors
= colors_in_color_table (&img
->ncolors
);
7136 free_color_table ();
7137 #endif /* COLOR_TABLE_SUPPORT */
7141 row_stride
= width
* cinfo
.output_components
;
7142 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7144 for (y
= 0; y
< height
; ++y
)
7146 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7147 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7148 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7152 fn_jpeg_finish_decompress (&cinfo
);
7153 fn_jpeg_destroy_decompress (&cinfo
);
7155 fclose ((FILE *) fp
);
7157 /* Maybe fill in the background field while we have ximg handy. */
7158 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7159 /* Casting avoids a GCC warning. */
7160 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7162 /* Put the image into the pixmap. */
7163 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7164 x_destroy_x_image (ximg
);
7169 #else /* HAVE_JPEG */
7178 return image_load_quartz2d (f
, img
, 0);
7180 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7185 #endif /* !HAVE_JPEG */
7189 /***********************************************************************
7191 ***********************************************************************/
7193 #if defined (HAVE_TIFF) || defined (MAC_OS)
7195 static int tiff_image_p
P_ ((Lisp_Object object
));
7196 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7198 /* The symbol `tiff' identifying images of this type. */
7202 /* Indices of image specification fields in tiff_format, below. */
7204 enum tiff_keyword_index
7213 TIFF_HEURISTIC_MASK
,
7219 /* Vector of image_keyword structures describing the format
7220 of valid user-defined image specifications. */
7222 static struct image_keyword tiff_format
[TIFF_LAST
] =
7224 {":type", IMAGE_SYMBOL_VALUE
, 1},
7225 {":data", IMAGE_STRING_VALUE
, 0},
7226 {":file", IMAGE_STRING_VALUE
, 0},
7227 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7228 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7229 {":relief", IMAGE_INTEGER_VALUE
, 0},
7230 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7231 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7232 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7233 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7236 /* Structure describing the image type `tiff'. */
7238 static struct image_type tiff_type
=
7247 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7250 tiff_image_p (object
)
7253 struct image_keyword fmt
[TIFF_LAST
];
7254 bcopy (tiff_format
, fmt
, sizeof fmt
);
7256 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7259 /* Must specify either the :data or :file keyword. */
7260 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7263 #endif /* HAVE_TIFF || MAC_OS */
7271 /* TIFF library details. */
7272 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7273 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7274 DEF_IMGLIB_FN (TIFFOpen
);
7275 DEF_IMGLIB_FN (TIFFClientOpen
);
7276 DEF_IMGLIB_FN (TIFFGetField
);
7277 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7278 DEF_IMGLIB_FN (TIFFClose
);
7281 init_tiff_functions (Lisp_Object libraries
)
7285 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7288 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7289 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7290 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7291 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7292 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7293 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7294 LOAD_IMGLIB_FN (library
, TIFFClose
);
7300 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7301 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7302 #define fn_TIFFOpen TIFFOpen
7303 #define fn_TIFFClientOpen TIFFClientOpen
7304 #define fn_TIFFGetField TIFFGetField
7305 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7306 #define fn_TIFFClose TIFFClose
7308 #endif /* HAVE_NTGUI */
7311 /* Reading from a memory buffer for TIFF images Based on the PNG
7312 memory source, but we have to provide a lot of extra functions.
7315 We really only need to implement read and seek, but I am not
7316 convinced that the TIFF library is smart enough not to destroy
7317 itself if we only hand it the function pointers we need to
7322 unsigned char *bytes
;
7329 tiff_read_from_memory (data
, buf
, size
)
7334 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7336 if (size
> src
->len
- src
->index
)
7338 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7344 tiff_write_from_memory (data
, buf
, size
)
7353 tiff_seek_in_memory (data
, off
, whence
)
7358 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7363 case SEEK_SET
: /* Go from beginning of source. */
7367 case SEEK_END
: /* Go from end of source. */
7368 idx
= src
->len
+ off
;
7371 case SEEK_CUR
: /* Go from current position. */
7372 idx
= src
->index
+ off
;
7375 default: /* Invalid `whence'. */
7379 if (idx
> src
->len
|| idx
< 0)
7387 tiff_close_memory (data
)
7395 tiff_mmap_memory (data
, pbase
, psize
)
7400 /* It is already _IN_ memory. */
7405 tiff_unmap_memory (data
, base
, size
)
7410 /* We don't need to do this. */
7414 tiff_size_of_memory (data
)
7417 return ((tiff_memory_source
*) data
)->len
;
7422 tiff_error_handler (title
, format
, ap
)
7423 const char *title
, *format
;
7429 len
= sprintf (buf
, "TIFF error: %s ", title
);
7430 vsprintf (buf
+ len
, format
, ap
);
7431 add_to_log (buf
, Qnil
, Qnil
);
7436 tiff_warning_handler (title
, format
, ap
)
7437 const char *title
, *format
;
7443 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7444 vsprintf (buf
+ len
, format
, ap
);
7445 add_to_log (buf
, Qnil
, Qnil
);
7449 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7457 Lisp_Object file
, specified_file
;
7458 Lisp_Object specified_data
;
7460 int width
, height
, x
, y
;
7464 struct gcpro gcpro1
;
7465 tiff_memory_source memsrc
;
7467 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7468 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7472 fn_TIFFSetErrorHandler (tiff_error_handler
);
7473 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7475 if (NILP (specified_data
))
7477 /* Read from a file */
7478 file
= x_find_image_file (specified_file
);
7479 if (!STRINGP (file
))
7481 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7486 /* Try to open the image file. Casting return value avoids a
7487 GCC warning on W32. */
7488 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7491 image_error ("Cannot open `%s'", file
, Qnil
);
7498 /* Memory source! */
7499 memsrc
.bytes
= SDATA (specified_data
);
7500 memsrc
.len
= SBYTES (specified_data
);
7503 /* Casting return value avoids a GCC warning on W32. */
7504 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7505 (TIFFReadWriteProc
) tiff_read_from_memory
,
7506 (TIFFReadWriteProc
) tiff_write_from_memory
,
7507 tiff_seek_in_memory
,
7509 tiff_size_of_memory
,
7515 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7521 /* Get width and height of the image, and allocate a raster buffer
7522 of width x height 32-bit values. */
7523 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7524 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7526 if (!check_image_size (f
, width
, height
))
7528 image_error ("Invalid image size", Qnil
, Qnil
);
7533 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7535 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7536 fn_TIFFClose (tiff
);
7539 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7545 /* Create the X image and pixmap. */
7546 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7553 /* Initialize the color table. */
7554 init_color_table ();
7556 /* Process the pixel raster. Origin is in the lower-left corner. */
7557 for (y
= 0; y
< height
; ++y
)
7559 uint32
*row
= buf
+ y
* width
;
7561 for (x
= 0; x
< width
; ++x
)
7563 uint32 abgr
= row
[x
];
7564 int r
= TIFFGetR (abgr
) << 8;
7565 int g
= TIFFGetG (abgr
) << 8;
7566 int b
= TIFFGetB (abgr
) << 8;
7567 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7571 #ifdef COLOR_TABLE_SUPPORT
7572 /* Remember the colors allocated for the image. Free the color table. */
7573 img
->colors
= colors_in_color_table (&img
->ncolors
);
7574 free_color_table ();
7575 #endif /* COLOR_TABLE_SUPPORT */
7578 img
->height
= height
;
7580 /* Maybe fill in the background field while we have ximg handy. */
7581 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7582 /* Casting avoids a GCC warning on W32. */
7583 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7585 /* Put the image into the pixmap, then free the X image and its buffer. */
7586 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7587 x_destroy_x_image (ximg
);
7594 #else /* HAVE_TIFF */
7602 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7606 #endif /* !HAVE_TIFF */
7610 /***********************************************************************
7612 ***********************************************************************/
7614 #if defined (HAVE_GIF) || defined (MAC_OS)
7616 static int gif_image_p
P_ ((Lisp_Object object
));
7617 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7618 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7620 /* The symbol `gif' identifying images of this type. */
7624 /* Indices of image specification fields in gif_format, below. */
7626 enum gif_keyword_index
7642 /* Vector of image_keyword structures describing the format
7643 of valid user-defined image specifications. */
7645 static struct image_keyword gif_format
[GIF_LAST
] =
7647 {":type", IMAGE_SYMBOL_VALUE
, 1},
7648 {":data", IMAGE_STRING_VALUE
, 0},
7649 {":file", IMAGE_STRING_VALUE
, 0},
7650 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7651 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7652 {":relief", IMAGE_INTEGER_VALUE
, 0},
7653 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7654 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7655 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7656 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7657 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7660 /* Structure describing the image type `gif'. */
7662 static struct image_type gif_type
=
7671 /* Free X resources of GIF image IMG which is used on frame F. */
7674 gif_clear_image (f
, img
)
7678 /* IMG->data.ptr_val may contain extension data. */
7679 img
->data
.lisp_val
= Qnil
;
7680 x_clear_image (f
, img
);
7683 /* Return non-zero if OBJECT is a valid GIF image specification. */
7686 gif_image_p (object
)
7689 struct image_keyword fmt
[GIF_LAST
];
7690 bcopy (gif_format
, fmt
, sizeof fmt
);
7692 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7695 /* Must specify either the :data or :file keyword. */
7696 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7699 #endif /* HAVE_GIF || MAC_OS */
7703 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7704 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7705 Undefine before redefining to avoid a preprocessor warning. */
7709 /* avoid conflict with QuickdrawText.h */
7710 #define DrawText gif_DrawText
7711 #include <gif_lib.h>
7714 #else /* HAVE_NTGUI || MAC_OS */
7716 #include <gif_lib.h>
7718 #endif /* HAVE_NTGUI || MAC_OS */
7723 /* GIF library details. */
7724 DEF_IMGLIB_FN (DGifCloseFile
);
7725 DEF_IMGLIB_FN (DGifSlurp
);
7726 DEF_IMGLIB_FN (DGifOpen
);
7727 DEF_IMGLIB_FN (DGifOpenFileName
);
7730 init_gif_functions (Lisp_Object libraries
)
7734 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7737 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7738 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7739 LOAD_IMGLIB_FN (library
, DGifOpen
);
7740 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7746 #define fn_DGifCloseFile DGifCloseFile
7747 #define fn_DGifSlurp DGifSlurp
7748 #define fn_DGifOpen DGifOpen
7749 #define fn_DGifOpenFileName DGifOpenFileName
7751 #endif /* HAVE_NTGUI */
7753 /* Reading a GIF image from memory
7754 Based on the PNG memory stuff to a certain extent. */
7758 unsigned char *bytes
;
7764 /* Make the current memory source available to gif_read_from_memory.
7765 It's done this way because not all versions of libungif support
7766 a UserData field in the GifFileType structure. */
7767 static gif_memory_source
*current_gif_memory_src
;
7770 gif_read_from_memory (file
, buf
, len
)
7775 gif_memory_source
*src
= current_gif_memory_src
;
7777 if (len
> src
->len
- src
->index
)
7780 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7786 /* Load GIF image IMG for use on frame F. Value is non-zero if
7789 static int interlace_start
[] = {0, 4, 2, 1};
7790 static int interlace_increment
[] = {8, 8, 4, 2};
7797 Lisp_Object file
, specified_file
;
7798 Lisp_Object specified_data
;
7799 int rc
, width
, height
, x
, y
, i
;
7801 ColorMapObject
*gif_color_map
;
7802 unsigned long pixel_colors
[256];
7804 struct gcpro gcpro1
;
7806 int ino
, image_height
, image_width
;
7807 gif_memory_source memsrc
;
7808 unsigned char *raster
;
7810 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7811 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7815 if (NILP (specified_data
))
7817 file
= x_find_image_file (specified_file
);
7818 if (!STRINGP (file
))
7820 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7825 /* Open the GIF file. Casting return value avoids a GCC warning
7827 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7830 image_error ("Cannot open `%s'", file
, Qnil
);
7837 /* Read from memory! */
7838 current_gif_memory_src
= &memsrc
;
7839 memsrc
.bytes
= SDATA (specified_data
);
7840 memsrc
.len
= SBYTES (specified_data
);
7843 /* Casting return value avoids a GCC warning on W32. */
7844 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
7847 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7853 /* Before reading entire contents, check the declared image size. */
7854 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7856 image_error ("Invalid image size", Qnil
, Qnil
);
7857 fn_DGifCloseFile (gif
);
7862 /* Read entire contents. */
7863 rc
= fn_DGifSlurp (gif
);
7864 if (rc
== GIF_ERROR
)
7866 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7867 fn_DGifCloseFile (gif
);
7872 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7873 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7874 if (ino
>= gif
->ImageCount
)
7876 image_error ("Invalid image number `%s' in image `%s'",
7878 fn_DGifCloseFile (gif
);
7883 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7884 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7885 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7886 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7887 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7888 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7890 width
= img
->width
= max (gif
->SWidth
,
7891 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7892 img
->corners
[RIGHT_CORNER
]));
7893 height
= img
->height
= max (gif
->SHeight
,
7894 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7895 img
->corners
[BOT_CORNER
]));
7897 if (!check_image_size (f
, width
, height
))
7899 image_error ("Invalid image size", Qnil
, Qnil
);
7900 fn_DGifCloseFile (gif
);
7905 /* Create the X image and pixmap. */
7906 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7908 fn_DGifCloseFile (gif
);
7913 /* Allocate colors. */
7914 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7916 gif_color_map
= gif
->SColorMap
;
7917 init_color_table ();
7918 bzero (pixel_colors
, sizeof pixel_colors
);
7921 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7923 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7924 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7925 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7926 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7929 #ifdef COLOR_TABLE_SUPPORT
7930 img
->colors
= colors_in_color_table (&img
->ncolors
);
7931 free_color_table ();
7932 #endif /* COLOR_TABLE_SUPPORT */
7934 /* Clear the part of the screen image that are not covered by
7935 the image from the GIF file. Full animated GIF support
7936 requires more than can be done here (see the gif89 spec,
7937 disposal methods). Let's simply assume that the part
7938 not covered by a sub-image is in the frame's background color. */
7939 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7940 for (x
= 0; x
< width
; ++x
)
7941 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7943 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7944 for (x
= 0; x
< width
; ++x
)
7945 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7947 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7949 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7950 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7951 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7952 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7955 /* Read the GIF image into the X image. We use a local variable
7956 `raster' here because RasterBits below is a char *, and invites
7957 problems with bytes >= 0x80. */
7958 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7960 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7963 int row
= interlace_start
[0];
7967 for (y
= 0; y
< image_height
; y
++)
7969 if (row
>= image_height
)
7971 row
= interlace_start
[++pass
];
7972 while (row
>= image_height
)
7973 row
= interlace_start
[++pass
];
7976 for (x
= 0; x
< image_width
; x
++)
7978 int i
= raster
[(y
* image_width
) + x
];
7979 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7980 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7983 row
+= interlace_increment
[pass
];
7988 for (y
= 0; y
< image_height
; ++y
)
7989 for (x
= 0; x
< image_width
; ++x
)
7991 int i
= raster
[y
* image_width
+ x
];
7992 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7993 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7997 /* Save GIF image extension data for `image-extension-data'.
7998 Format is (count IMAGES FUNCTION "BYTES" ...). */
7999 img
->data
.lisp_val
= Qnil
;
8000 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
8002 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
8003 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
8004 /* Append (... FUNCTION "BYTES") */
8005 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
8006 Fcons (make_number (ext
->Function
),
8007 img
->data
.lisp_val
));
8008 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
8010 if (gif
->ImageCount
> 1)
8011 img
->data
.lisp_val
= Fcons (Qcount
,
8012 Fcons (make_number (gif
->ImageCount
),
8013 img
->data
.lisp_val
));
8015 fn_DGifCloseFile (gif
);
8017 /* Maybe fill in the background field while we have ximg handy. */
8018 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8019 /* Casting avoids a GCC warning. */
8020 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8022 /* Put the image into the pixmap, then free the X image and its buffer. */
8023 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8024 x_destroy_x_image (ximg
);
8030 #else /* !HAVE_GIF */
8038 Lisp_Object specified_file
, file
;
8039 Lisp_Object specified_data
;
8041 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8049 Lisp_Object specified_bg
;
8054 TimeScale time_scale
;
8055 TimeValue time
, duration
;
8060 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8061 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8063 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8066 if (NILP (specified_data
))
8068 /* Read from a file */
8072 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8076 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8081 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8082 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8086 if (!graphic_p
&& !movie_p
)
8088 if (prefer_graphic_p
)
8089 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8090 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8093 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8094 CloseMovieFile (refnum
);
8097 image_error ("Error reading `%s'", file
, Qnil
);
8103 /* Memory source! */
8105 long file_type_atom
[3];
8107 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8110 image_error ("Cannot allocate data handle for `%s'",
8115 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8116 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8117 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8118 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8121 err
= PtrAndHand ("\p", dref
, 1);
8123 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8126 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8129 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8130 &movie_p
, &prefer_graphic_p
, 0);
8134 if (!graphic_p
&& !movie_p
)
8136 if (prefer_graphic_p
)
8140 DisposeHandle (dref
);
8141 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8145 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8146 HandleDataHandlerSubType
);
8147 DisposeHandle (dref
);
8152 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8153 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8154 track
= GetMovieIndTrack (movie
, 1);
8155 media
= GetTrackMedia (track
);
8156 nsamples
= GetMediaSampleCount (media
);
8157 if (ino
>= nsamples
)
8159 image_error ("Invalid image number `%s' in image `%s'",
8163 time_scale
= GetMediaTimeScale (media
);
8165 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8166 if (!STRINGP (specified_bg
) ||
8167 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8169 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8170 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8171 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8172 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8174 GetMovieBox (movie
, &rect
);
8175 width
= img
->width
= rect
.right
- rect
.left
;
8176 height
= img
->height
= rect
.bottom
- rect
.top
;
8177 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8180 GetGWorld (&old_port
, &old_gdh
);
8181 SetGWorld (ximg
, NULL
);
8182 bg_color
.red
= color
.red
;
8183 bg_color
.green
= color
.green
;
8184 bg_color
.blue
= color
.blue
;
8185 RGBBackColor (&bg_color
);
8186 SetGWorld (old_port
, old_gdh
);
8187 SetMovieActive (movie
, 1);
8188 SetMovieGWorld (movie
, ximg
, NULL
);
8189 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8190 SetMovieTimeValue (movie
, time
);
8191 MoviesTask (movie
, 0L);
8192 DisposeTrackMedia (media
);
8193 DisposeMovieTrack (track
);
8194 DisposeMovie (movie
);
8198 /* Save GIF image extension data for `image-extension-data'.
8199 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8201 Lisp_Object gce
= make_uninit_string (4);
8202 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8204 /* Fill the delay time field. */
8205 SSET (gce
, 1, centisec
& 0xff);
8206 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8207 /* We don't know about other fields. */
8211 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8212 make_number (0xf9), gce
);
8215 /* Maybe fill in the background field while we have ximg handy. */
8216 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8217 IMAGE_BACKGROUND (img
, f
, ximg
);
8219 /* Put the image into the pixmap. */
8220 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8221 x_destroy_x_image (ximg
);
8225 image_error ("Cannot open `%s'", file
, Qnil
);
8228 DisposeTrackMedia (media
);
8230 DisposeMovieTrack (track
);
8232 DisposeMovie (movie
);
8239 #endif /* HAVE_GIF */
8243 /***********************************************************************
8245 ***********************************************************************/
8247 #if defined (HAVE_RSVG)
8249 /* Function prototypes. */
8251 static int svg_image_p
P_ ((Lisp_Object object
));
8252 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
8254 static int svg_load_image
P_ ((struct frame
*, struct image
*,
8255 unsigned char *, unsigned int));
8257 /* The symbol `svg' identifying images of this type. */
8261 /* Indices of image specification fields in svg_format, below. */
8263 enum svg_keyword_index
8278 /* Vector of image_keyword structures describing the format
8279 of valid user-defined image specifications. */
8281 static struct image_keyword svg_format
[SVG_LAST
] =
8283 {":type", IMAGE_SYMBOL_VALUE
, 1},
8284 {":data", IMAGE_STRING_VALUE
, 0},
8285 {":file", IMAGE_STRING_VALUE
, 0},
8286 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8287 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8288 {":relief", IMAGE_INTEGER_VALUE
, 0},
8289 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8290 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8291 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8292 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8295 /* Structure describing the image type `svg'. Its the same type of
8296 structure defined for all image formats, handled by emacs image
8297 functions. See struct image_type in dispextern.h. */
8299 static struct image_type svg_type
=
8301 /* An identifier showing that this is an image structure for the SVG format. */
8303 /* Handle to a function that can be used to identify a SVG file. */
8305 /* Handle to function used to load a SVG file. */
8307 /* Handle to function to free sresources for SVG. */
8309 /* An internal field to link to the next image type in a list of
8310 image types, will be filled in when registering the format. */
8315 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8316 this by calling parse_image_spec and supplying the keywords that
8317 identify the SVG format. */
8320 svg_image_p (object
)
8323 struct image_keyword fmt
[SVG_LAST
];
8324 bcopy (svg_format
, fmt
, sizeof fmt
);
8326 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
8329 /* Must specify either the :data or :file keyword. */
8330 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
8333 #include <librsvg/rsvg.h>
8337 /* SVG library functions. */
8338 DEF_IMGLIB_FN (rsvg_handle_new
);
8339 DEF_IMGLIB_FN (rsvg_handle_set_size_callback
);
8340 DEF_IMGLIB_FN (rsvg_handle_write
);
8341 DEF_IMGLIB_FN (rsvg_handle_close
);
8342 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
8343 DEF_IMGLIB_FN (rsvg_handle_free
);
8345 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
8346 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
8347 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
8348 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
8349 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
8350 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
8351 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
8352 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
8354 DEF_IMGLIB_FN (g_type_init
);
8355 DEF_IMGLIB_FN (g_object_unref
);
8356 DEF_IMGLIB_FN (g_error_free
);
8358 Lisp_Object Qgdk_pixbuf
, Qglib
;
8361 init_svg_functions (Lisp_Object libraries
)
8363 HMODULE library
, gdklib
, glib
;
8365 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
8366 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
8367 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
8370 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
8371 LOAD_IMGLIB_FN (library
, rsvg_handle_set_size_callback
);
8372 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
8373 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
8374 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
8375 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
8377 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
8378 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
8379 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
8380 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
8381 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
8382 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
8383 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
8384 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
8386 LOAD_IMGLIB_FN (glib
, g_type_init
);
8387 LOAD_IMGLIB_FN (glib
, g_object_unref
);
8388 LOAD_IMGLIB_FN (glib
, g_error_free
);
8393 /* The following aliases for library functions allow dynamic loading
8394 to be used on some platforms. */
8395 #define fn_rsvg_handle_new rsvg_handle_new
8396 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8397 #define fn_rsvg_handle_write rsvg_handle_write
8398 #define fn_rsvg_handle_close rsvg_handle_close
8399 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8400 #define fn_rsvg_handle_free rsvg_handle_free
8402 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8403 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8404 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8405 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8406 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8407 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8408 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8409 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8411 #define fn_g_type_init g_type_init
8412 #define fn_g_object_unref g_object_unref
8413 #define fn_g_error_free g_error_free
8414 #endif /* !HAVE_NTGUI */
8416 /* Load SVG image IMG for use on frame F. Value is non-zero if
8417 successful. this function will go into the svg_type structure, and
8418 the prototype thus needs to be compatible with that structure. */
8426 Lisp_Object file_name
;
8428 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8429 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8430 if (STRINGP (file_name
))
8433 unsigned char *contents
;
8435 struct gcpro gcpro1
;
8437 file
= x_find_image_file (file_name
);
8439 if (!STRINGP (file
))
8441 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
8446 /* Read the entire file into memory. */
8447 contents
= slurp_file (SDATA (file
), &size
);
8448 if (contents
== NULL
)
8450 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8454 /* If the file was slurped into memory properly, parse it. */
8455 success_p
= svg_load_image (f
, img
, contents
, size
);
8459 /* Else its not a file, its a lisp object. Load the image from a
8460 lisp object rather than a file. */
8465 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8466 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8472 /* svg_load_image is a helper function for svg_load, which does the
8473 actual loading given contents and size, apart from frame and image
8474 structures, passed from svg_load.
8476 Uses librsvg to do most of the image processing.
8478 Returns non-zero when successful. */
8480 svg_load_image (f
, img
, contents
, size
)
8481 /* Pointer to emacs frame structure. */
8483 /* Pointer to emacs image structure. */
8485 /* String containing the SVG XML data to be parsed. */
8486 unsigned char *contents
;
8487 /* Size of data in bytes. */
8490 RsvgHandle
*rsvg_handle
;
8491 GError
*error
= NULL
;
8495 const guint8
*pixels
;
8498 Lisp_Object specified_bg
;
8503 /* g_type_init is a glib function that must be called prior to using
8504 gnome type library functions. */
8506 /* Make a handle to a new rsvg object. */
8507 rsvg_handle
= fn_rsvg_handle_new ();
8509 /* Parse the contents argument and fill in the rsvg_handle. */
8510 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8514 /* The parsing is complete, rsvg_handle is ready to used, close it
8515 for further writes. */
8516 fn_rsvg_handle_close (rsvg_handle
, &error
);
8519 /* We can now get a valid pixel buffer from the svg file, if all
8521 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8524 /* Extract some meta data from the svg handle. */
8525 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8526 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8527 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8528 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8530 /* Validate the svg meta data. */
8531 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8532 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8533 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8534 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8536 /* Try to create a x pixmap to hold the svg pixmap. */
8537 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8539 fn_g_object_unref (pixbuf
);
8543 init_color_table ();
8545 /* Handle alpha channel by combining the image with a background
8547 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8548 if (STRINGP (specified_bg
)
8549 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8551 background
.red
>>= 8;
8552 background
.green
>>= 8;
8553 background
.blue
>>= 8;
8557 #ifdef HAVE_X_WINDOWS
8558 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8559 x_query_color (f
, &background
);
8561 /* SVG pixmaps specify transparency in the last byte, so right
8562 shift 8 bits to get rid of it, since emacs doesn't support
8564 background
.red
>>= 8;
8565 background
.green
>>= 8;
8566 background
.blue
>>= 8;
8567 #elif defined (MAC_OS)
8568 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8569 background
.red
= RED_FROM_ULONG (background
.pixel
);
8570 background
.green
= GREEN_FROM_ULONG (background
.pixel
);
8571 background
.blue
= BLUE_FROM_ULONG (background
.pixel
);
8572 #elif defined (HAVE_NTGUI)
8573 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8574 #if 0 /* W32 TODO : Colormap support. */
8575 x_query_color (f
, &background
);
8578 /* SVG pixmaps specify transparency in the last byte, so right
8579 shift 8 bits to get rid of it, since emacs doesn't support
8581 background
.red
>>= 8;
8582 background
.green
>>= 8;
8583 background
.blue
>>= 8;
8584 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8589 /* This loop handles opacity values, since Emacs assumes
8590 non-transparent images. Each pixel must be "flattened" by
8591 calculating the resulting color, given the transparency of the
8592 pixel, and the image background color. */
8593 for (y
= 0; y
< height
; ++y
)
8595 for (x
= 0; x
< width
; ++x
)
8605 opacity
= *pixels
++;
8607 red
= ((red
* opacity
)
8608 + (background
.red
* ((1 << 8) - opacity
)));
8609 green
= ((green
* opacity
)
8610 + (background
.green
* ((1 << 8) - opacity
)));
8611 blue
= ((blue
* opacity
)
8612 + (background
.blue
* ((1 << 8) - opacity
)));
8614 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8617 pixels
+= rowstride
- 4 * width
;
8620 #ifdef COLOR_TABLE_SUPPORT
8621 /* Remember colors allocated for this image. */
8622 img
->colors
= colors_in_color_table (&img
->ncolors
);
8623 free_color_table ();
8624 #endif /* COLOR_TABLE_SUPPORT */
8626 fn_g_object_unref (pixbuf
);
8629 img
->height
= height
;
8631 /* Maybe fill in the background field while we have ximg handy.
8632 Casting avoids a GCC warning. */
8633 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8635 /* Put the image into the pixmap, then free the X image and its
8637 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8638 x_destroy_x_image (ximg
);
8643 /* FIXME: Use error->message so the user knows what is the actual
8644 problem with the image. */
8645 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8646 fn_g_error_free (error
);
8650 #endif /* defined (HAVE_RSVG) */
8655 /***********************************************************************
8657 ***********************************************************************/
8659 #ifdef HAVE_X_WINDOWS
8660 #define HAVE_GHOSTSCRIPT 1
8661 #endif /* HAVE_X_WINDOWS */
8663 /* The symbol `postscript' identifying images of this type. */
8665 Lisp_Object Qpostscript
;
8667 #ifdef HAVE_GHOSTSCRIPT
8669 static int gs_image_p
P_ ((Lisp_Object object
));
8670 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8671 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8673 /* Keyword symbols. */
8675 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8677 /* Indices of image specification fields in gs_format, below. */
8679 enum gs_keyword_index
8697 /* Vector of image_keyword structures describing the format
8698 of valid user-defined image specifications. */
8700 static struct image_keyword gs_format
[GS_LAST
] =
8702 {":type", IMAGE_SYMBOL_VALUE
, 1},
8703 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8704 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8705 {":file", IMAGE_STRING_VALUE
, 1},
8706 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8707 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8708 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8709 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8710 {":relief", IMAGE_INTEGER_VALUE
, 0},
8711 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8712 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8713 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8714 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8717 /* Structure describing the image type `ghostscript'. */
8719 static struct image_type gs_type
=
8729 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8732 gs_clear_image (f
, img
)
8736 /* IMG->data.ptr_val may contain a recorded colormap. */
8737 xfree (img
->data
.ptr_val
);
8738 x_clear_image (f
, img
);
8742 /* Return non-zero if OBJECT is a valid Ghostscript image
8749 struct image_keyword fmt
[GS_LAST
];
8753 bcopy (gs_format
, fmt
, sizeof fmt
);
8755 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8758 /* Bounding box must be a list or vector containing 4 integers. */
8759 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8762 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8763 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8768 else if (VECTORP (tem
))
8770 if (XVECTOR (tem
)->size
!= 4)
8772 for (i
= 0; i
< 4; ++i
)
8773 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8783 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8792 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8793 struct gcpro gcpro1
, gcpro2
;
8795 double in_width
, in_height
;
8796 Lisp_Object pixel_colors
= Qnil
;
8798 /* Compute pixel size of pixmap needed from the given size in the
8799 image specification. Sizes in the specification are in pt. 1 pt
8800 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8802 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8803 in_width
= XFASTINT (pt_width
) / 72.0;
8804 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8805 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8806 in_height
= XFASTINT (pt_height
) / 72.0;
8807 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8809 if (!check_image_size (f
, img
->width
, img
->height
))
8811 image_error ("Invalid image size", Qnil
, Qnil
);
8815 /* Create the pixmap. */
8816 xassert (img
->pixmap
== NO_PIXMAP
);
8818 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8820 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8821 img
->width
, img
->height
,
8822 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8827 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8831 /* Call the loader to fill the pixmap. It returns a process object
8832 if successful. We do not record_unwind_protect here because
8833 other places in redisplay like calling window scroll functions
8834 don't either. Let the Lisp loader use `unwind-protect' instead. */
8835 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8837 sprintf (buffer
, "%lu %lu",
8838 (unsigned long) FRAME_X_WINDOW (f
),
8839 (unsigned long) img
->pixmap
);
8840 window_and_pixmap_id
= build_string (buffer
);
8842 sprintf (buffer
, "%lu %lu",
8843 FRAME_FOREGROUND_PIXEL (f
),
8844 FRAME_BACKGROUND_PIXEL (f
));
8845 pixel_colors
= build_string (buffer
);
8847 XSETFRAME (frame
, f
);
8848 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8850 loader
= intern ("gs-load-image");
8852 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8853 make_number (img
->width
),
8854 make_number (img
->height
),
8855 window_and_pixmap_id
,
8858 return PROCESSP (img
->data
.lisp_val
);
8862 /* Kill the Ghostscript process that was started to fill PIXMAP on
8863 frame F. Called from XTread_socket when receiving an event
8864 telling Emacs that Ghostscript has finished drawing. */
8867 x_kill_gs_process (pixmap
, f
)
8871 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
8875 /* Find the image containing PIXMAP. */
8876 for (i
= 0; i
< c
->used
; ++i
)
8877 if (c
->images
[i
]->pixmap
== pixmap
)
8880 /* Should someone in between have cleared the image cache, for
8881 instance, give up. */
8885 /* Kill the GS process. We should have found PIXMAP in the image
8886 cache and its image should contain a process object. */
8888 xassert (PROCESSP (img
->data
.lisp_val
));
8889 Fkill_process (img
->data
.lisp_val
, Qnil
);
8890 img
->data
.lisp_val
= Qnil
;
8892 #if defined (HAVE_X_WINDOWS)
8894 /* On displays with a mutable colormap, figure out the colors
8895 allocated for the image by looking at the pixels of an XImage for
8897 class = FRAME_X_VISUAL (f
)->class;
8898 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8904 /* Try to get an XImage for img->pixmep. */
8905 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8906 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8911 /* Initialize the color table. */
8912 init_color_table ();
8914 /* For each pixel of the image, look its color up in the
8915 color table. After having done so, the color table will
8916 contain an entry for each color used by the image. */
8917 for (y
= 0; y
< img
->height
; ++y
)
8918 for (x
= 0; x
< img
->width
; ++x
)
8920 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8921 lookup_pixel_color (f
, pixel
);
8924 /* Record colors in the image. Free color table and XImage. */
8925 #ifdef COLOR_TABLE_SUPPORT
8926 img
->colors
= colors_in_color_table (&img
->ncolors
);
8927 free_color_table ();
8929 XDestroyImage (ximg
);
8931 #if 0 /* This doesn't seem to be the case. If we free the colors
8932 here, we get a BadAccess later in x_clear_image when
8933 freeing the colors. */
8934 /* We have allocated colors once, but Ghostscript has also
8935 allocated colors on behalf of us. So, to get the
8936 reference counts right, free them once. */
8938 x_free_colors (f
, img
->colors
, img
->ncolors
);
8942 image_error ("Cannot get X image of `%s'; colors will not be freed",
8947 #endif /* HAVE_X_WINDOWS */
8949 /* Now that we have the pixmap, compute mask and transform the
8950 image if requested. */
8952 postprocess_image (f
, img
);
8956 #endif /* HAVE_GHOSTSCRIPT */
8959 /***********************************************************************
8961 ***********************************************************************/
8965 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8966 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8970 return valid_image_p (spec
) ? Qt
: Qnil
;
8974 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8980 if (valid_image_p (spec
))
8981 id
= lookup_image (SELECTED_FRAME (), spec
);
8984 return make_number (id
);
8987 #endif /* GLYPH_DEBUG != 0 */
8990 /***********************************************************************
8992 ***********************************************************************/
8995 /* Image types that rely on external libraries are loaded dynamically
8996 if the library is available. */
8997 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8998 define_image_type (image_type, init_lib_fn (libraries))
9000 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9001 define_image_type (image_type, 1)
9002 #endif /* HAVE_NTGUI */
9004 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
9005 doc
: /* Initialize image library implementing image type TYPE.
9006 Return non-nil if TYPE is a supported image type.
9008 Image types pbm and xbm are prebuilt; other types are loaded here.
9009 Libraries to load are specified in alist LIBRARIES (usually, the value
9010 of `image-library-alist', which see). */)
9012 Lisp_Object type
, libraries
;
9016 /* Don't try to reload the library. */
9017 tested
= Fassq (type
, Vimage_type_cache
);
9019 return XCDR (tested
);
9021 #if defined (HAVE_XPM) || defined (MAC_OS)
9022 if (EQ (type
, Qxpm
))
9023 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
9026 #if defined (HAVE_JPEG) || defined (MAC_OS)
9027 if (EQ (type
, Qjpeg
))
9028 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
9031 #if defined (HAVE_TIFF) || defined (MAC_OS)
9032 if (EQ (type
, Qtiff
))
9033 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
9036 #if defined (HAVE_GIF) || defined (MAC_OS)
9037 if (EQ (type
, Qgif
))
9038 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
9041 #if defined (HAVE_PNG) || defined (MAC_OS)
9042 if (EQ (type
, Qpng
))
9043 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
9046 #if defined (HAVE_RSVG)
9047 if (EQ (type
, Qsvg
))
9048 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
9051 #ifdef HAVE_GHOSTSCRIPT
9052 if (EQ (type
, Qpostscript
))
9053 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
9056 /* If the type is not recognized, avoid testing it ever again. */
9057 CACHE_IMAGE_TYPE (type
, Qnil
);
9064 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
9066 /* Initialize this only once, since that's what we do with Vimage_types
9067 and they are supposed to be in sync. Initializing here gives correct
9068 operation on GNU/Linux of calling dump-emacs after loading some images. */
9071 /* Must be defined now becase we're going to update it below, while
9072 defining the supported image types. */
9073 DEFVAR_LISP ("image-types", &Vimage_types
,
9074 doc
: /* List of potentially supported image types.
9075 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9076 To check whether it is really supported, use `image-type-available-p'. */);
9077 Vimage_types
= Qnil
;
9079 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
9080 doc
: /* Alist of image types vs external libraries needed to display them.
9082 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9083 representing a supported image type, and the rest are strings giving
9084 alternate filenames for the corresponding external libraries.
9086 Emacs tries to load the libraries in the order they appear on the
9087 list; if none is loaded, the running session of Emacs won't
9088 support the image type. Types 'pbm and 'xbm don't need to be
9089 listed; they are always supported. */);
9090 Vimage_library_alist
= Qnil
;
9091 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
9093 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
9094 doc
: /* Maximum size of images.
9095 Emacs will not load an image into memory if its pixel width or
9096 pixel height exceeds this limit.
9098 If the value is an integer, it directly specifies the maximum
9099 image height and width, measured in pixels. If it is a floating
9100 point number, it specifies the maximum image height and width
9101 as a ratio to the frame height and width. If the value is
9102 non-numeric, there is no explicit limit on the size of images. */);
9103 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
9105 Vimage_type_cache
= Qnil
;
9106 staticpro (&Vimage_type_cache
);
9108 Qpbm
= intern ("pbm");
9110 ADD_IMAGE_TYPE (Qpbm
);
9112 Qxbm
= intern ("xbm");
9114 ADD_IMAGE_TYPE (Qxbm
);
9116 define_image_type (&xbm_type
, 1);
9117 define_image_type (&pbm_type
, 1);
9119 Qcount
= intern ("count");
9120 staticpro (&Qcount
);
9122 QCascent
= intern (":ascent");
9123 staticpro (&QCascent
);
9124 QCmargin
= intern (":margin");
9125 staticpro (&QCmargin
);
9126 QCrelief
= intern (":relief");
9127 staticpro (&QCrelief
);
9128 QCconversion
= intern (":conversion");
9129 staticpro (&QCconversion
);
9130 QCcolor_symbols
= intern (":color-symbols");
9131 staticpro (&QCcolor_symbols
);
9132 QCheuristic_mask
= intern (":heuristic-mask");
9133 staticpro (&QCheuristic_mask
);
9134 QCindex
= intern (":index");
9135 staticpro (&QCindex
);
9136 QCmatrix
= intern (":matrix");
9137 staticpro (&QCmatrix
);
9138 QCcolor_adjustment
= intern (":color-adjustment");
9139 staticpro (&QCcolor_adjustment
);
9140 QCmask
= intern (":mask");
9141 staticpro (&QCmask
);
9143 Qlaplace
= intern ("laplace");
9144 staticpro (&Qlaplace
);
9145 Qemboss
= intern ("emboss");
9146 staticpro (&Qemboss
);
9147 Qedge_detection
= intern ("edge-detection");
9148 staticpro (&Qedge_detection
);
9149 Qheuristic
= intern ("heuristic");
9150 staticpro (&Qheuristic
);
9152 Qpostscript
= intern ("postscript");
9153 staticpro (&Qpostscript
);
9154 #ifdef HAVE_GHOSTSCRIPT
9155 ADD_IMAGE_TYPE (Qpostscript
);
9156 QCloader
= intern (":loader");
9157 staticpro (&QCloader
);
9158 QCbounding_box
= intern (":bounding-box");
9159 staticpro (&QCbounding_box
);
9160 QCpt_width
= intern (":pt-width");
9161 staticpro (&QCpt_width
);
9162 QCpt_height
= intern (":pt-height");
9163 staticpro (&QCpt_height
);
9164 #endif /* HAVE_GHOSTSCRIPT */
9166 #if defined (HAVE_XPM) || defined (MAC_OS)
9167 Qxpm
= intern ("xpm");
9169 ADD_IMAGE_TYPE (Qxpm
);
9172 #if defined (HAVE_JPEG) || defined (MAC_OS)
9173 Qjpeg
= intern ("jpeg");
9175 ADD_IMAGE_TYPE (Qjpeg
);
9178 #if defined (HAVE_TIFF) || defined (MAC_OS)
9179 Qtiff
= intern ("tiff");
9181 ADD_IMAGE_TYPE (Qtiff
);
9184 #if defined (HAVE_GIF) || defined (MAC_OS)
9185 Qgif
= intern ("gif");
9187 ADD_IMAGE_TYPE (Qgif
);
9190 #if defined (HAVE_PNG) || defined (MAC_OS)
9191 Qpng
= intern ("png");
9193 ADD_IMAGE_TYPE (Qpng
);
9196 #if defined (HAVE_RSVG)
9197 Qsvg
= intern ("svg");
9199 ADD_IMAGE_TYPE (Qsvg
);
9201 Qgdk_pixbuf
= intern ("gdk-pixbuf");
9202 staticpro (&Qgdk_pixbuf
);
9203 Qglib
= intern ("glib");
9205 #endif /* HAVE_NTGUI */
9206 #endif /* HAVE_RSVG */
9208 defsubr (&Sinit_image_library
);
9209 defsubr (&Sclear_image_cache
);
9210 defsubr (&Simage_refresh
);
9211 defsubr (&Simage_size
);
9212 defsubr (&Simage_mask_p
);
9213 defsubr (&Simage_extension_data
);
9217 defsubr (&Slookup_image
);
9220 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9221 doc
: /* Non-nil means always draw a cross over disabled images.
9222 Disabled images are those having a `:conversion disabled' property.
9223 A cross is always drawn on black & white displays. */);
9224 cross_disabled_images
= 0;
9226 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9227 doc
: /* List of directories to search for window system bitmap files. */);
9228 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9230 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9231 doc
: /* Time after which cached images are removed from the cache.
9232 When an image has not been displayed this many seconds, remove it
9233 from the image cache. Value must be an integer or nil with nil
9234 meaning don't clear the cache. */);
9235 Vimage_cache_eviction_delay
= make_number (30 * 60);
9241 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
9242 init_image_func_pointer ();
9246 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9247 (do not change this comment) */