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
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
, Qcount
;
737 extern Lisp_Object Qcenter
;
738 Lisp_Object QCascent
, QCmargin
, QCrelief
;
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_X_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_X_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_X_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_X_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-eviction-seconds is
1714 non-nil, this frees images in the cache which weren't displayed for
1715 at least that many seconds. */
1718 clear_image_cache (f
, force_p
)
1722 struct image_cache
*c
= FRAME_X_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_WINDOW_P (f
)
1760 && FRAME_X_IMAGE_CACHE (f
) == c
)
1761 clear_current_matrices (f
);
1764 ++windows_or_buffers_changed
;
1772 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1774 doc
: /* Clear the image cache of FRAME.
1775 FRAME nil or omitted means use the selected frame.
1776 FRAME t means clear the image caches of all frames. */)
1784 FOR_EACH_FRAME (tail
, frame
)
1785 if (FRAME_WINDOW_P (XFRAME (frame
)))
1786 clear_image_cache (XFRAME (frame
), 1);
1789 clear_image_cache (check_x_frame (frame
), 1);
1795 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1797 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1798 If SPEC specifies an image file, the displayed image is updated with
1799 the current contents of that file.
1800 FRAME nil or omitted means use the selected frame.
1801 FRAME t means refresh the image on all frames. */)
1803 Lisp_Object spec
, frame
;
1805 if (!valid_image_p (spec
))
1806 error ("Invalid image specification");
1811 FOR_EACH_FRAME (tail
, frame
)
1813 struct frame
*f
= XFRAME (frame
);
1814 if (FRAME_WINDOW_P (f
))
1815 uncache_image (f
, spec
);
1819 uncache_image (check_x_frame (frame
), spec
);
1825 /* Compute masks and transform image IMG on frame F, as specified
1826 by the image's specification, */
1829 postprocess_image (f
, img
)
1833 /* Manipulation of the image's mask. */
1836 Lisp_Object conversion
, spec
;
1841 /* `:heuristic-mask t'
1843 means build a mask heuristically.
1844 `:heuristic-mask (R G B)'
1845 `:mask (heuristic (R G B))'
1846 means build a mask from color (R G B) in the
1849 means remove a mask, if any. */
1851 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1853 x_build_heuristic_mask (f
, img
, mask
);
1858 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1860 if (EQ (mask
, Qheuristic
))
1861 x_build_heuristic_mask (f
, img
, Qt
);
1862 else if (CONSP (mask
)
1863 && EQ (XCAR (mask
), Qheuristic
))
1865 if (CONSP (XCDR (mask
)))
1866 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1868 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1870 else if (NILP (mask
) && found_p
&& img
->mask
)
1872 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1873 img
->mask
= NO_PIXMAP
;
1878 /* Should we apply an image transformation algorithm? */
1879 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1880 if (EQ (conversion
, Qdisabled
))
1881 x_disable_image (f
, img
);
1882 else if (EQ (conversion
, Qlaplace
))
1884 else if (EQ (conversion
, Qemboss
))
1886 else if (CONSP (conversion
)
1887 && EQ (XCAR (conversion
), Qedge_detection
))
1890 tem
= XCDR (conversion
);
1892 x_edge_detection (f
, img
,
1893 Fplist_get (tem
, QCmatrix
),
1894 Fplist_get (tem
, QCcolor_adjustment
));
1900 /* Return the id of image with Lisp specification SPEC on frame F.
1901 SPEC must be a valid Lisp image specification (see valid_image_p). */
1904 lookup_image (f
, spec
)
1910 struct gcpro gcpro1
;
1913 /* F must be a window-system frame, and SPEC must be a valid image
1915 xassert (FRAME_WINDOW_P (f
));
1916 xassert (valid_image_p (spec
));
1920 /* Look up SPEC in the hash table of the image cache. */
1921 hash
= sxhash (spec
, 0);
1922 img
= search_image_cache (f
, spec
, hash
);
1923 if (img
&& img
->load_failed_p
)
1925 free_image (f
, img
);
1929 /* If not found, create a new image and cache it. */
1932 extern Lisp_Object Qpostscript
;
1935 img
= make_image (spec
, hash
);
1936 cache_image (f
, img
);
1937 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1938 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
1939 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
1941 /* If we can't load the image, and we don't have a width and
1942 height, use some arbitrary width and height so that we can
1943 draw a rectangle for it. */
1944 if (img
->load_failed_p
)
1948 value
= image_spec_value (spec
, QCwidth
, NULL
);
1949 img
->width
= (INTEGERP (value
)
1950 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1951 value
= image_spec_value (spec
, QCheight
, NULL
);
1952 img
->height
= (INTEGERP (value
)
1953 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1957 /* Handle image type independent image attributes
1958 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1959 `:background COLOR'. */
1960 Lisp_Object ascent
, margin
, relief
, bg
;
1962 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1963 if (INTEGERP (ascent
))
1964 img
->ascent
= XFASTINT (ascent
);
1965 else if (EQ (ascent
, Qcenter
))
1966 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1968 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1969 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1970 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1971 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1972 && INTEGERP (XCDR (margin
)))
1974 if (XINT (XCAR (margin
)) > 0)
1975 img
->hmargin
= XFASTINT (XCAR (margin
));
1976 if (XINT (XCDR (margin
)) > 0)
1977 img
->vmargin
= XFASTINT (XCDR (margin
));
1980 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1981 if (INTEGERP (relief
))
1983 img
->relief
= XINT (relief
);
1984 img
->hmargin
+= abs (img
->relief
);
1985 img
->vmargin
+= abs (img
->relief
);
1988 if (! img
->background_valid
)
1990 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1994 = x_alloc_image_color (f
, img
, bg
,
1995 FRAME_BACKGROUND_PIXEL (f
));
1996 img
->background_valid
= 1;
2000 /* Do image transformations and compute masks, unless we
2001 don't have the image yet. */
2002 if (!EQ (*img
->type
->type
, Qpostscript
))
2003 postprocess_image (f
, img
);
2009 /* We're using IMG, so set its timestamp to `now'. */
2010 EMACS_GET_TIME (now
);
2011 img
->timestamp
= EMACS_SECS (now
);
2015 /* Value is the image id. */
2020 /* Cache image IMG in the image cache of frame F. */
2023 cache_image (f
, img
)
2027 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
2030 /* Find a free slot in c->images. */
2031 for (i
= 0; i
< c
->used
; ++i
)
2032 if (c
->images
[i
] == NULL
)
2035 /* If no free slot found, maybe enlarge c->images. */
2036 if (i
== c
->used
&& c
->used
== c
->size
)
2039 c
->images
= (struct image
**) xrealloc (c
->images
,
2040 c
->size
* sizeof *c
->images
);
2043 /* Add IMG to c->images, and assign IMG an id. */
2049 /* Add IMG to the cache's hash table. */
2050 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2051 img
->next
= c
->buckets
[i
];
2053 img
->next
->prev
= img
;
2055 c
->buckets
[i
] = img
;
2059 /* Call FN on every image in the image cache of frame F. Used to mark
2060 Lisp Objects in the image cache. */
2063 forall_images_in_image_cache (f
, fn
)
2065 void (*fn
) P_ ((struct image
*img
));
2067 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
2069 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
2073 for (i
= 0; i
< c
->used
; ++i
)
2082 /***********************************************************************
2083 X / MAC / W32 support code
2084 ***********************************************************************/
2088 /* Macro for defining functions that will be loaded from image DLLs. */
2089 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2091 /* Macro for loading those image functions from the library. */
2092 #define LOAD_IMGLIB_FN(lib,func) { \
2093 fn_##func = (void *) GetProcAddress (lib, #func); \
2094 if (!fn_##func) return 0; \
2097 /* Load a DLL implementing an image type.
2098 The `image-library-alist' variable associates a symbol,
2099 identifying an image type, to a list of possible filenames.
2100 The function returns NULL if no library could be loaded for
2101 the given image type, or if the library was previously loaded;
2102 else the handle of the DLL. */
2104 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2106 HMODULE library
= NULL
;
2108 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2110 Lisp_Object dlls
= Fassq (type
, libraries
);
2113 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2115 CHECK_STRING_CAR (dlls
);
2116 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2124 #endif /* HAVE_NTGUI */
2126 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2127 XImagePtr
*, Pixmap
*));
2128 static void x_destroy_x_image
P_ ((XImagePtr
));
2129 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2132 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2133 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2134 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2135 via xmalloc. Print error messages via image_error if an error
2136 occurs. Value is non-zero if successful.
2138 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2139 should indicate the bit depth of the image. */
2142 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2144 int width
, height
, depth
;
2148 #ifdef HAVE_X_WINDOWS
2149 Display
*display
= FRAME_X_DISPLAY (f
);
2150 Window window
= FRAME_X_WINDOW (f
);
2151 Screen
*screen
= FRAME_X_SCREEN (f
);
2153 xassert (interrupt_input_blocked
);
2156 depth
= DefaultDepthOfScreen (screen
);
2157 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2158 depth
, ZPixmap
, 0, NULL
, width
, height
,
2159 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2162 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2166 /* Allocate image raster. */
2167 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2169 /* Allocate a pixmap of the same size. */
2170 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2171 if (*pixmap
== NO_PIXMAP
)
2173 x_destroy_x_image (*ximg
);
2175 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2180 #endif /* HAVE_X_WINDOWS */
2184 BITMAPINFOHEADER
*header
;
2186 int scanline_width_bits
;
2188 int palette_colors
= 0;
2193 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2194 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2196 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2200 scanline_width_bits
= width
* depth
;
2201 remainder
= scanline_width_bits
% 32;
2204 scanline_width_bits
+= 32 - remainder
;
2206 /* Bitmaps with a depth less than 16 need a palette. */
2207 /* BITMAPINFO structure already contains the first RGBQUAD. */
2209 palette_colors
= 1 << depth
- 1;
2211 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2214 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2218 header
= &((*ximg
)->info
.bmiHeader
);
2219 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2220 header
->biSize
= sizeof (*header
);
2221 header
->biWidth
= width
;
2222 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2223 header
->biPlanes
= 1;
2224 header
->biBitCount
= depth
;
2225 header
->biCompression
= BI_RGB
;
2226 header
->biClrUsed
= palette_colors
;
2228 /* TODO: fill in palette. */
2231 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2232 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2233 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2234 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2235 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2236 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2237 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2238 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2241 hdc
= get_frame_dc (f
);
2243 /* Create a DIBSection and raster array for the bitmap,
2244 and store its handle in *pixmap. */
2245 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2246 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2247 /* casting avoids a GCC warning */
2248 (void **)&((*ximg
)->data
), NULL
, 0);
2250 /* Realize display palette and garbage all frames. */
2251 release_frame_dc (f
, hdc
);
2253 if (*pixmap
== NULL
)
2255 DWORD err
= GetLastError ();
2256 Lisp_Object errcode
;
2257 /* All system errors are < 10000, so the following is safe. */
2258 XSETINT (errcode
, (int) err
);
2259 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2260 x_destroy_x_image (*ximg
);
2266 #endif /* HAVE_NTGUI */
2269 Display
*display
= FRAME_X_DISPLAY (f
);
2270 Window window
= FRAME_X_WINDOW (f
);
2272 xassert (interrupt_input_blocked
);
2274 /* Allocate a pixmap of the same size. */
2275 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2276 if (*pixmap
== NO_PIXMAP
)
2279 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2283 LockPixels (GetGWorldPixMap (*pixmap
));
2291 /* Destroy XImage XIMG. Free XIMG->data. */
2294 x_destroy_x_image (ximg
)
2297 xassert (interrupt_input_blocked
);
2300 #ifdef HAVE_X_WINDOWS
2303 XDestroyImage (ximg
);
2304 #endif /* HAVE_X_WINDOWS */
2306 /* Data will be freed by DestroyObject. */
2309 #endif /* HAVE_NTGUI */
2311 XDestroyImage (ximg
);
2317 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2318 are width and height of both the image and pixmap. */
2321 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2327 #ifdef HAVE_X_WINDOWS
2330 xassert (interrupt_input_blocked
);
2331 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2332 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2333 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2334 #endif /* HAVE_X_WINDOWS */
2337 #if 0 /* I don't think this is necessary looking at where it is used. */
2338 HDC hdc
= get_frame_dc (f
);
2339 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2340 release_frame_dc (f
, hdc
);
2342 #endif /* HAVE_NTGUI */
2345 xassert (ximg
== pixmap
);
2350 /***********************************************************************
2352 ***********************************************************************/
2354 static unsigned char *slurp_file
P_ ((char *, int *));
2357 /* Find image file FILE. Look in data-directory/images, then
2358 x-bitmap-file-path. Value is the encoded full name of the file
2359 found, or nil if not found. */
2362 x_find_image_file (file
)
2365 Lisp_Object file_found
, search_path
;
2366 struct gcpro gcpro1
, gcpro2
;
2370 /* TODO I think this should use something like image-load-path
2371 instead. Unfortunately, that can contain non-string elements. */
2372 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2374 Vx_bitmap_file_path
);
2375 GCPRO2 (file_found
, search_path
);
2377 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2378 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2384 file_found
= ENCODE_FILE (file_found
);
2393 /* Read FILE into memory. Value is a pointer to a buffer allocated
2394 with xmalloc holding FILE's contents. Value is null if an error
2395 occurred. *SIZE is set to the size of the file. */
2397 static unsigned char *
2398 slurp_file (file
, size
)
2403 unsigned char *buf
= NULL
;
2406 if (stat (file
, &st
) == 0
2407 && (fp
= fopen (file
, "rb")) != NULL
2408 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2409 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2432 /***********************************************************************
2433 MAC Image Load Functions
2434 ***********************************************************************/
2436 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2439 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2443 find_image_fsspec (specified_file
, file
, fss
)
2444 Lisp_Object specified_file
, *file
;
2450 *file
= x_find_image_file (specified_file
);
2451 if (!STRINGP (*file
))
2452 return fnfErr
; /* file or directory not found;
2453 incomplete pathname */
2454 /* Try to open the image file. */
2455 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2456 SBYTES (*file
), typeFSS
, &desc
);
2459 #if TARGET_API_MAC_CARBON
2460 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2462 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2464 AEDisposeDesc (&desc
);
2470 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2477 ComponentResult err
;
2478 GraphicsImportComponent gi
;
2481 ImageDescriptionHandle desc_handle
;
2482 short draw_all_pixels
;
2483 Lisp_Object specified_bg
;
2488 err
= OpenADefaultComponent (GraphicsImporterComponentType
, type
, &gi
);
2491 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2496 /* read from file system spec */
2497 err
= GraphicsImportSetDataFile (gi
, fss
);
2500 image_error ("Cannot set fsspec to graphics importer for '%s'",
2507 /* read from data handle */
2508 err
= GraphicsImportSetDataHandle (gi
, dh
);
2511 image_error ("Cannot set data handle to graphics importer for `%s'",
2516 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2517 if (err
!= noErr
|| desc_handle
== NULL
)
2519 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2522 width
= img
->width
= (*desc_handle
)->width
;
2523 height
= img
->height
= (*desc_handle
)->height
;
2524 DisposeHandle ((Handle
)desc_handle
);
2526 if (!check_image_size (f
, width
, height
))
2528 image_error ("Invalid image size", Qnil
, Qnil
);
2532 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2534 /* Don't check the error code here. It may have an undocumented
2538 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2542 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2544 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2545 if (!STRINGP (specified_bg
) ||
2546 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2548 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2549 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2550 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2551 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2555 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2557 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2562 GetGWorld (&old_port
, &old_gdh
);
2563 SetGWorld (ximg
, NULL
);
2564 bg_color
.red
= color
.red
;
2565 bg_color
.green
= color
.green
;
2566 bg_color
.blue
= color
.blue
;
2567 RGBBackColor (&bg_color
);
2568 #if TARGET_API_MAC_CARBON
2569 GetPortBounds (ximg
, &rect
);
2572 EraseRect (&(ximg
->portRect
));
2574 SetGWorld (old_port
, old_gdh
);
2576 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2577 GraphicsImportDraw (gi
);
2578 CloseComponent (gi
);
2580 /* Maybe fill in the background field while we have ximg handy. */
2581 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2582 IMAGE_BACKGROUND (img
, f
, ximg
);
2584 /* Put the image into the pixmap. */
2585 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2586 x_destroy_x_image (ximg
);
2590 CloseComponent (gi
);
2595 /* Load an image using the QuickTime Graphics Importer.
2596 Note: The alpha channel does not work for PNG images. */
2598 image_load_quicktime (f
, img
, type
)
2603 Lisp_Object specified_file
;
2604 Lisp_Object specified_data
;
2607 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2608 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2610 if (NILP (specified_data
))
2612 /* Read from a file */
2616 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2620 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2622 image_error ("Cannot open `%s'", file
, Qnil
);
2625 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2629 /* Memory source! */
2633 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2636 image_error ("Cannot allocate data handle for `%s'",
2640 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2648 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2649 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2650 So don't use this function directly but determine at runtime
2651 whether it exists. */
2652 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2653 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2654 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2658 init_image_func_pointer ()
2660 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2662 MyCGImageCreateWithPNGDataProvider
2663 = (CGImageCreateWithPNGDataProviderProcType
)
2664 NSAddressOfSymbol (NSLookupAndBindSymbol
2665 ("_CGImageCreateWithPNGDataProvider"));
2668 MyCGImageCreateWithPNGDataProvider
= NULL
;
2673 image_load_quartz2d (f
, img
, png_p
)
2678 Lisp_Object file
, specified_file
;
2679 Lisp_Object specified_data
, specified_bg
;
2680 struct gcpro gcpro1
;
2681 CGDataProviderRef source
;
2685 XImagePtr ximg
= NULL
;
2686 CGContextRef context
;
2689 /* Open the file. */
2690 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2691 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2696 if (NILP (specified_data
))
2701 file
= x_find_image_file (specified_file
);
2702 if (!STRINGP (file
))
2704 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2708 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2709 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2710 kCFURLPOSIXPathStyle
, 0);
2712 source
= CGDataProviderCreateWithURL (url
);
2716 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2717 SBYTES (specified_data
), NULL
);
2720 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2721 kCGRenderingIntentDefault
);
2723 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2724 kCGRenderingIntentDefault
);
2726 CGDataProviderRelease (source
);
2730 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2733 width
= img
->width
= CGImageGetWidth (image
);
2734 height
= img
->height
= CGImageGetHeight (image
);
2736 if (!check_image_size (f
, width
, height
))
2738 CGImageRelease (image
);
2740 image_error ("Invalid image size", Qnil
, Qnil
);
2746 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2747 if (!STRINGP (specified_bg
) ||
2748 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2750 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2751 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2752 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2753 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2757 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2759 CGImageRelease (image
);
2763 rectangle
= CGRectMake (0, 0, width
, height
);
2764 QDBeginCGContext (ximg
, &context
);
2767 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2768 color
.green
/ 65535.0,
2769 color
.blue
/ 65535.0, 1.0);
2770 CGContextFillRect (context
, rectangle
);
2772 CGContextDrawImage (context
, rectangle
, image
);
2773 QDEndCGContext (ximg
, &context
);
2774 CGImageRelease (image
);
2776 /* Maybe fill in the background field while we have ximg handy. */
2777 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2778 IMAGE_BACKGROUND (img
, f
, ximg
);
2780 /* Put the image into the pixmap. */
2781 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2782 x_destroy_x_image (ximg
);
2791 /***********************************************************************
2793 ***********************************************************************/
2795 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2796 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2797 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2798 unsigned char *, unsigned char *));
2799 static int xbm_image_p
P_ ((Lisp_Object object
));
2800 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2801 unsigned char *, unsigned char *,
2802 int *, int *, unsigned char **));
2803 static int xbm_file_p
P_ ((Lisp_Object
));
2806 /* Indices of image specification fields in xbm_format, below. */
2808 enum xbm_keyword_index
2826 /* Vector of image_keyword structures describing the format
2827 of valid XBM image specifications. */
2829 static struct image_keyword xbm_format
[XBM_LAST
] =
2831 {":type", IMAGE_SYMBOL_VALUE
, 1},
2832 {":file", IMAGE_STRING_VALUE
, 0},
2833 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2834 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2835 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2836 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2837 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2838 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2839 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2840 {":relief", IMAGE_INTEGER_VALUE
, 0},
2841 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2842 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2843 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2846 /* Structure describing the image type XBM. */
2848 static struct image_type xbm_type
=
2857 /* Tokens returned from xbm_scan. */
2866 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2867 A valid specification is a list starting with the symbol `image'
2868 The rest of the list is a property list which must contain an
2871 If the specification specifies a file to load, it must contain
2872 an entry `:file FILENAME' where FILENAME is a string.
2874 If the specification is for a bitmap loaded from memory it must
2875 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2876 WIDTH and HEIGHT are integers > 0. DATA may be:
2878 1. a string large enough to hold the bitmap data, i.e. it must
2879 have a size >= (WIDTH + 7) / 8 * HEIGHT
2881 2. a bool-vector of size >= WIDTH * HEIGHT
2883 3. a vector of strings or bool-vectors, one for each line of the
2886 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2887 may not be specified in this case because they are defined in the
2890 Both the file and data forms may contain the additional entries
2891 `:background COLOR' and `:foreground COLOR'. If not present,
2892 foreground and background of the frame on which the image is
2893 displayed is used. */
2896 xbm_image_p (object
)
2899 struct image_keyword kw
[XBM_LAST
];
2901 bcopy (xbm_format
, kw
, sizeof kw
);
2902 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2905 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2907 if (kw
[XBM_FILE
].count
)
2909 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2912 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2914 /* In-memory XBM file. */
2915 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2923 /* Entries for `:width', `:height' and `:data' must be present. */
2924 if (!kw
[XBM_WIDTH
].count
2925 || !kw
[XBM_HEIGHT
].count
2926 || !kw
[XBM_DATA
].count
)
2929 data
= kw
[XBM_DATA
].value
;
2930 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2931 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2933 /* Check type of data, and width and height against contents of
2939 /* Number of elements of the vector must be >= height. */
2940 if (XVECTOR (data
)->size
< height
)
2943 /* Each string or bool-vector in data must be large enough
2944 for one line of the image. */
2945 for (i
= 0; i
< height
; ++i
)
2947 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2952 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2955 else if (BOOL_VECTOR_P (elt
))
2957 if (XBOOL_VECTOR (elt
)->size
< width
)
2964 else if (STRINGP (data
))
2967 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2970 else if (BOOL_VECTOR_P (data
))
2972 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2983 /* Scan a bitmap file. FP is the stream to read from. Value is
2984 either an enumerator from enum xbm_token, or a character for a
2985 single-character token, or 0 at end of file. If scanning an
2986 identifier, store the lexeme of the identifier in SVAL. If
2987 scanning a number, store its value in *IVAL. */
2990 xbm_scan (s
, end
, sval
, ival
)
2991 unsigned char **s
, *end
;
2999 /* Skip white space. */
3000 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3005 else if (isdigit (c
))
3007 int value
= 0, digit
;
3009 if (c
== '0' && *s
< end
)
3012 if (c
== 'x' || c
== 'X')
3019 else if (c
>= 'a' && c
<= 'f')
3020 digit
= c
- 'a' + 10;
3021 else if (c
>= 'A' && c
<= 'F')
3022 digit
= c
- 'A' + 10;
3025 value
= 16 * value
+ digit
;
3028 else if (isdigit (c
))
3032 && (c
= *(*s
)++, isdigit (c
)))
3033 value
= 8 * value
+ c
- '0';
3040 && (c
= *(*s
)++, isdigit (c
)))
3041 value
= 10 * value
+ c
- '0';
3049 else if (isalpha (c
) || c
== '_')
3053 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
3060 else if (c
== '/' && **s
== '*')
3062 /* C-style comment. */
3064 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
3078 /* Create a Windows bitmap from X bitmap data. */
3080 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
3082 static unsigned char swap_nibble
[16]
3083 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3084 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3085 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3086 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3088 unsigned char *bits
, *p
;
3091 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
3092 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3093 bits
= (unsigned char *) alloca (height
* w2
);
3094 bzero (bits
, height
* w2
);
3095 for (i
= 0; i
< height
; i
++)
3098 for (j
= 0; j
< w1
; j
++)
3100 /* Bitswap XBM bytes to match how Windows does things. */
3101 unsigned char c
= *data
++;
3102 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
3103 | (swap_nibble
[(c
>>4) & 0xf]));
3106 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3112 convert_mono_to_color_image (f
, img
, foreground
, background
)
3115 COLORREF foreground
, background
;
3117 HDC hdc
, old_img_dc
, new_img_dc
;
3118 HGDIOBJ old_prev
, new_prev
;
3121 hdc
= get_frame_dc (f
);
3122 old_img_dc
= CreateCompatibleDC (hdc
);
3123 new_img_dc
= CreateCompatibleDC (hdc
);
3124 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3125 release_frame_dc (f
, hdc
);
3126 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3127 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3128 SetTextColor (new_img_dc
, background
);
3129 SetBkColor (new_img_dc
, foreground
);
3131 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3134 SelectObject (old_img_dc
, old_prev
);
3135 SelectObject (new_img_dc
, new_prev
);
3136 DeleteDC (old_img_dc
);
3137 DeleteDC (new_img_dc
);
3138 DeleteObject (img
->pixmap
);
3139 if (new_pixmap
== 0)
3140 fprintf (stderr
, "Failed to convert image to color.\n");
3142 img
->pixmap
= new_pixmap
;
3145 #define XBM_BIT_SHUFFLE(b) (~(b))
3149 #define XBM_BIT_SHUFFLE(b) (b)
3151 #endif /* HAVE_NTGUI */
3155 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
3159 RGB_PIXEL_COLOR fg
, bg
;
3160 int non_default_colors
;
3164 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3166 /* If colors were specified, transfer the bitmap to a color one. */
3167 if (non_default_colors
)
3168 convert_mono_to_color_image (f
, img
, fg
, bg
);
3171 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3174 img
->width
, img
->height
,
3176 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3177 #endif /* HAVE_NTGUI */
3182 /* Replacement for XReadBitmapFileData which isn't available under old
3183 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3184 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3185 the image. Return in *DATA the bitmap data allocated with xmalloc.
3186 Value is non-zero if successful. DATA null means just test if
3187 CONTENTS looks like an in-memory XBM file. */
3190 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3192 unsigned char *contents
, *end
;
3193 int *width
, *height
;
3194 unsigned char **data
;
3196 unsigned char *s
= contents
;
3197 char buffer
[BUFSIZ
];
3200 int bytes_per_line
, i
, nbytes
;
3206 LA1 = xbm_scan (&s, end, buffer, &value)
3208 #define expect(TOKEN) \
3209 if (LA1 != (TOKEN)) \
3214 #define expect_ident(IDENT) \
3215 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3220 *width
= *height
= -1;
3223 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3225 /* Parse defines for width, height and hot-spots. */
3229 expect_ident ("define");
3230 expect (XBM_TK_IDENT
);
3232 if (LA1
== XBM_TK_NUMBER
)
3234 char *p
= strrchr (buffer
, '_');
3235 p
= p
? p
+ 1 : buffer
;
3236 if (strcmp (p
, "width") == 0)
3238 else if (strcmp (p
, "height") == 0)
3241 expect (XBM_TK_NUMBER
);
3244 if (!check_image_size (f
, *width
, *height
))
3246 else if (data
== NULL
)
3249 /* Parse bits. Must start with `static'. */
3250 expect_ident ("static");
3251 if (LA1
== XBM_TK_IDENT
)
3253 if (strcmp (buffer
, "unsigned") == 0)
3256 expect_ident ("char");
3258 else if (strcmp (buffer
, "short") == 0)
3262 if (*width
% 16 && *width
% 16 < 9)
3265 else if (strcmp (buffer
, "char") == 0)
3273 expect (XBM_TK_IDENT
);
3279 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3280 nbytes
= bytes_per_line
* *height
;
3281 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3285 for (i
= 0; i
< nbytes
; i
+= 2)
3288 expect (XBM_TK_NUMBER
);
3290 *p
++ = XBM_BIT_SHUFFLE (val
);
3291 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3292 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3294 if (LA1
== ',' || LA1
== '}')
3302 for (i
= 0; i
< nbytes
; ++i
)
3305 expect (XBM_TK_NUMBER
);
3307 *p
++ = XBM_BIT_SHUFFLE (val
);
3309 if (LA1
== ',' || LA1
== '}')
3334 /* Load XBM image IMG which will be displayed on frame F from buffer
3335 CONTENTS. END is the end of the buffer. Value is non-zero if
3339 xbm_load_image (f
, img
, contents
, end
)
3342 unsigned char *contents
, *end
;
3345 unsigned char *data
;
3348 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3351 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3352 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3353 int non_default_colors
= 0;
3356 xassert (img
->width
> 0 && img
->height
> 0);
3358 /* Get foreground and background colors, maybe allocate colors. */
3359 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3362 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3363 non_default_colors
= 1;
3365 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3368 background
= x_alloc_image_color (f
, img
, value
, background
);
3369 img
->background
= background
;
3370 img
->background_valid
= 1;
3371 non_default_colors
= 1;
3374 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3375 foreground
, background
,
3376 non_default_colors
);
3379 if (img
->pixmap
== NO_PIXMAP
)
3381 x_clear_image (f
, img
);
3382 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3388 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3394 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3401 return (STRINGP (data
)
3402 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3409 /* Fill image IMG which is used on frame F with pixmap data. Value is
3410 non-zero if successful. */
3418 Lisp_Object file_name
;
3420 xassert (xbm_image_p (img
->spec
));
3422 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3423 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3424 if (STRINGP (file_name
))
3427 unsigned char *contents
;
3429 struct gcpro gcpro1
;
3431 file
= x_find_image_file (file_name
);
3433 if (!STRINGP (file
))
3435 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3440 contents
= slurp_file (SDATA (file
), &size
);
3441 if (contents
== NULL
)
3443 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3448 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3453 struct image_keyword fmt
[XBM_LAST
];
3455 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3456 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3457 int non_default_colors
= 0;
3460 int in_memory_file_p
= 0;
3462 /* See if data looks like an in-memory XBM file. */
3463 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3464 in_memory_file_p
= xbm_file_p (data
);
3466 /* Parse the image specification. */
3467 bcopy (xbm_format
, fmt
, sizeof fmt
);
3468 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3471 /* Get specified width, and height. */
3472 if (!in_memory_file_p
)
3474 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3475 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3476 xassert (img
->width
> 0 && img
->height
> 0);
3479 /* Get foreground and background colors, maybe allocate colors. */
3480 if (fmt
[XBM_FOREGROUND
].count
3481 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3483 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3485 non_default_colors
= 1;
3488 if (fmt
[XBM_BACKGROUND
].count
3489 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3491 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3493 non_default_colors
= 1;
3496 if (in_memory_file_p
)
3497 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3506 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3508 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3509 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3511 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3513 bcopy (SDATA (line
), p
, nbytes
);
3515 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3518 else if (STRINGP (data
))
3519 bits
= SDATA (data
);
3521 bits
= XBOOL_VECTOR (data
)->data
;
3523 /* Create the pixmap. */
3525 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3526 foreground
, background
,
3527 non_default_colors
);
3532 image_error ("Unable to create pixmap for XBM image `%s'",
3534 x_clear_image (f
, img
);
3544 /***********************************************************************
3546 ***********************************************************************/
3548 #if defined (HAVE_XPM) || defined (MAC_OS)
3550 static int xpm_image_p
P_ ((Lisp_Object object
));
3551 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3552 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3554 #endif /* HAVE_XPM || MAC_OS */
3558 /* Indicate to xpm.h that we don't have Xlib. */
3560 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3561 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3562 #define XColor xpm_XColor
3563 #define XImage xpm_XImage
3564 #define Display xpm_Display
3565 #define PIXEL_ALREADY_TYPEDEFED
3566 #include "X11/xpm.h"
3571 #undef PIXEL_ALREADY_TYPEDEFED
3573 #include "X11/xpm.h"
3574 #endif /* HAVE_NTGUI */
3575 #endif /* HAVE_XPM */
3577 #if defined (HAVE_XPM) || defined (MAC_OS)
3578 /* The symbol `xpm' identifying XPM-format images. */
3582 /* Indices of image specification fields in xpm_format, below. */
3584 enum xpm_keyword_index
3600 /* Vector of image_keyword structures describing the format
3601 of valid XPM image specifications. */
3603 static struct image_keyword xpm_format
[XPM_LAST
] =
3605 {":type", IMAGE_SYMBOL_VALUE
, 1},
3606 {":file", IMAGE_STRING_VALUE
, 0},
3607 {":data", IMAGE_STRING_VALUE
, 0},
3608 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3609 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3610 {":relief", IMAGE_INTEGER_VALUE
, 0},
3611 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3612 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3613 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3614 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3615 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3618 /* Structure describing the image type XPM. */
3620 static struct image_type xpm_type
=
3629 #ifdef HAVE_X_WINDOWS
3631 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3632 functions for allocating image colors. Our own functions handle
3633 color allocation failures more gracefully than the ones on the XPM
3636 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3637 #define ALLOC_XPM_COLORS
3639 #endif /* HAVE_X_WINDOWS */
3641 #ifdef ALLOC_XPM_COLORS
3643 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3644 static void xpm_free_color_cache
P_ ((void));
3645 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3646 static int xpm_color_bucket
P_ ((char *));
3647 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3650 /* An entry in a hash table used to cache color definitions of named
3651 colors. This cache is necessary to speed up XPM image loading in
3652 case we do color allocations ourselves. Without it, we would need
3653 a call to XParseColor per pixel in the image. */
3655 struct xpm_cached_color
3657 /* Next in collision chain. */
3658 struct xpm_cached_color
*next
;
3660 /* Color definition (RGB and pixel color). */
3667 /* The hash table used for the color cache, and its bucket vector
3670 #define XPM_COLOR_CACHE_BUCKETS 1001
3671 struct xpm_cached_color
**xpm_color_cache
;
3673 /* Initialize the color cache. */
3676 xpm_init_color_cache (f
, attrs
)
3678 XpmAttributes
*attrs
;
3680 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3681 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3682 memset (xpm_color_cache
, 0, nbytes
);
3683 init_color_table ();
3685 if (attrs
->valuemask
& XpmColorSymbols
)
3690 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3691 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3692 attrs
->colorsymbols
[i
].value
, &color
))
3694 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3696 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3701 /* Free the color cache. */
3704 xpm_free_color_cache ()
3706 struct xpm_cached_color
*p
, *next
;
3709 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3710 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3716 xfree (xpm_color_cache
);
3717 xpm_color_cache
= NULL
;
3718 free_color_table ();
3721 /* Return the bucket index for color named COLOR_NAME in the color
3725 xpm_color_bucket (color_name
)
3731 for (s
= color_name
; *s
; ++s
)
3733 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3737 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3738 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3741 static struct xpm_cached_color
*
3742 xpm_cache_color (f
, color_name
, color
, bucket
)
3749 struct xpm_cached_color
*p
;
3752 bucket
= xpm_color_bucket (color_name
);
3754 nbytes
= sizeof *p
+ strlen (color_name
);
3755 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3756 strcpy (p
->name
, color_name
);
3758 p
->next
= xpm_color_cache
[bucket
];
3759 xpm_color_cache
[bucket
] = p
;
3763 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3764 return the cached definition in *COLOR. Otherwise, make a new
3765 entry in the cache and allocate the color. Value is zero if color
3766 allocation failed. */
3769 xpm_lookup_color (f
, color_name
, color
)
3774 struct xpm_cached_color
*p
;
3775 int h
= xpm_color_bucket (color_name
);
3777 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3778 if (strcmp (p
->name
, color_name
) == 0)
3783 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3786 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3788 p
= xpm_cache_color (f
, color_name
, color
, h
);
3790 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3791 with transparency, and it's useful. */
3792 else if (strcmp ("opaque", color_name
) == 0)
3794 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3795 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3796 p
= xpm_cache_color (f
, color_name
, color
, h
);
3803 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3804 CLOSURE is a pointer to the frame on which we allocate the
3805 color. Return in *COLOR the allocated color. Value is non-zero
3809 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3816 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3820 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3821 is a pointer to the frame on which we allocate the color. Value is
3822 non-zero if successful. */
3825 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3835 #endif /* ALLOC_XPM_COLORS */
3840 /* XPM library details. */
3842 DEF_IMGLIB_FN (XpmFreeAttributes
);
3843 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3844 DEF_IMGLIB_FN (XpmReadFileToImage
);
3845 DEF_IMGLIB_FN (XImageFree
);
3848 init_xpm_functions (Lisp_Object libraries
)
3852 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3855 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3856 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3857 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3858 LOAD_IMGLIB_FN (library
, XImageFree
);
3862 #endif /* HAVE_NTGUI */
3865 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3866 for XPM images. Such a list must consist of conses whose car and
3870 xpm_valid_color_symbols_p (color_symbols
)
3871 Lisp_Object color_symbols
;
3873 while (CONSP (color_symbols
))
3875 Lisp_Object sym
= XCAR (color_symbols
);
3877 || !STRINGP (XCAR (sym
))
3878 || !STRINGP (XCDR (sym
)))
3880 color_symbols
= XCDR (color_symbols
);
3883 return NILP (color_symbols
);
3887 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3890 xpm_image_p (object
)
3893 struct image_keyword fmt
[XPM_LAST
];
3894 bcopy (xpm_format
, fmt
, sizeof fmt
);
3895 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3896 /* Either `:file' or `:data' must be present. */
3897 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3898 /* Either no `:color-symbols' or it's a list of conses
3899 whose car and cdr are strings. */
3900 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3901 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3904 #endif /* HAVE_XPM || MAC_OS */
3906 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3908 x_create_bitmap_from_xpm_data (f
, bits
)
3912 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3914 XpmAttributes attrs
;
3915 Pixmap bitmap
, mask
;
3917 bzero (&attrs
, sizeof attrs
);
3919 attrs
.visual
= FRAME_X_VISUAL (f
);
3920 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3921 attrs
.valuemask
|= XpmVisual
;
3922 attrs
.valuemask
|= XpmColormap
;
3924 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3925 bits
, &bitmap
, &mask
, &attrs
);
3926 if (rc
!= XpmSuccess
)
3928 XpmFreeAttributes (&attrs
);
3932 id
= x_allocate_bitmap_record (f
);
3933 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3934 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3935 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3936 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3937 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3938 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3939 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3940 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3942 XpmFreeAttributes (&attrs
);
3945 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3947 /* Load image IMG which will be displayed on frame F. Value is
3948 non-zero if successful. */
3958 XpmAttributes attrs
;
3959 Lisp_Object specified_file
, color_symbols
;
3962 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3963 #endif /* HAVE_NTGUI */
3965 /* Configure the XPM lib. Use the visual of frame F. Allocate
3966 close colors. Return colors allocated. */
3967 bzero (&attrs
, sizeof attrs
);
3970 attrs
.visual
= FRAME_X_VISUAL (f
);
3971 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3972 attrs
.valuemask
|= XpmVisual
;
3973 attrs
.valuemask
|= XpmColormap
;
3974 #endif /* HAVE_NTGUI */
3976 #ifdef ALLOC_XPM_COLORS
3977 /* Allocate colors with our own functions which handle
3978 failing color allocation more gracefully. */
3979 attrs
.color_closure
= f
;
3980 attrs
.alloc_color
= xpm_alloc_color
;
3981 attrs
.free_colors
= xpm_free_colors
;
3982 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3983 #else /* not ALLOC_XPM_COLORS */
3984 /* Let the XPM lib allocate colors. */
3985 attrs
.valuemask
|= XpmReturnAllocPixels
;
3986 #ifdef XpmAllocCloseColors
3987 attrs
.alloc_close_colors
= 1;
3988 attrs
.valuemask
|= XpmAllocCloseColors
;
3989 #else /* not XpmAllocCloseColors */
3990 attrs
.closeness
= 600;
3991 attrs
.valuemask
|= XpmCloseness
;
3992 #endif /* not XpmAllocCloseColors */
3993 #endif /* ALLOC_XPM_COLORS */
3995 /* If image specification contains symbolic color definitions, add
3996 these to `attrs'. */
3997 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3998 if (CONSP (color_symbols
))
4001 XpmColorSymbol
*xpm_syms
;
4004 attrs
.valuemask
|= XpmColorSymbols
;
4006 /* Count number of symbols. */
4007 attrs
.numsymbols
= 0;
4008 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
4011 /* Allocate an XpmColorSymbol array. */
4012 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
4013 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
4014 bzero (xpm_syms
, size
);
4015 attrs
.colorsymbols
= xpm_syms
;
4017 /* Fill the color symbol array. */
4018 for (tail
= color_symbols
, i
= 0;
4020 ++i
, tail
= XCDR (tail
))
4022 Lisp_Object name
= XCAR (XCAR (tail
));
4023 Lisp_Object color
= XCDR (XCAR (tail
));
4024 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
4025 strcpy (xpm_syms
[i
].name
, SDATA (name
));
4026 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
4027 strcpy (xpm_syms
[i
].value
, SDATA (color
));
4031 /* Create a pixmap for the image, either from a file, or from a
4032 string buffer containing data in the same format as an XPM file. */
4033 #ifdef ALLOC_XPM_COLORS
4034 xpm_init_color_cache (f
, &attrs
);
4037 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4041 HDC frame_dc
= get_frame_dc (f
);
4042 hdc
= CreateCompatibleDC (frame_dc
);
4043 release_frame_dc (f
, frame_dc
);
4045 #endif /* HAVE_NTGUI */
4047 if (STRINGP (specified_file
))
4049 Lisp_Object file
= x_find_image_file (specified_file
);
4050 if (!STRINGP (file
))
4052 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4057 /* XpmReadFileToPixmap is not available in the Windows port of
4058 libxpm. But XpmReadFileToImage almost does what we want. */
4059 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
4060 &xpm_image
, &xpm_mask
,
4063 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4064 SDATA (file
), &img
->pixmap
, &img
->mask
,
4066 #endif /* HAVE_NTGUI */
4070 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
4072 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4073 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4074 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
4075 &xpm_image
, &xpm_mask
,
4078 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4080 &img
->pixmap
, &img
->mask
,
4082 #endif /* HAVE_NTGUI */
4085 if (rc
== XpmSuccess
)
4087 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4088 img
->colors
= colors_in_color_table (&img
->ncolors
);
4089 #else /* not ALLOC_XPM_COLORS */
4093 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4094 plus some duplicate attributes. */
4095 if (xpm_image
&& xpm_image
->bitmap
)
4097 img
->pixmap
= xpm_image
->bitmap
;
4098 /* XImageFree in libXpm frees XImage struct without destroying
4099 the bitmap, which is what we want. */
4100 fn_XImageFree (xpm_image
);
4102 if (xpm_mask
&& xpm_mask
->bitmap
)
4104 /* The mask appears to be inverted compared with what we expect.
4105 TODO: invert our expectations. See other places where we
4106 have to invert bits because our idea of masks is backwards. */
4108 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4110 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4111 SelectObject (hdc
, old_obj
);
4113 img
->mask
= xpm_mask
->bitmap
;
4114 fn_XImageFree (xpm_mask
);
4119 #endif /* HAVE_NTGUI */
4121 /* Remember allocated colors. */
4122 img
->ncolors
= attrs
.nalloc_pixels
;
4123 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4124 * sizeof *img
->colors
);
4125 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4127 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4128 #ifdef DEBUG_X_COLORS
4129 register_color (img
->colors
[i
]);
4132 #endif /* not ALLOC_XPM_COLORS */
4134 img
->width
= attrs
.width
;
4135 img
->height
= attrs
.height
;
4136 xassert (img
->width
> 0 && img
->height
> 0);
4138 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4140 fn_XpmFreeAttributes (&attrs
);
4142 XpmFreeAttributes (&attrs
);
4143 #endif /* HAVE_NTGUI */
4149 #endif /* HAVE_NTGUI */
4154 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4157 case XpmFileInvalid
:
4158 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4162 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4165 case XpmColorFailed
:
4166 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4170 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4175 #ifdef ALLOC_XPM_COLORS
4176 xpm_free_color_cache ();
4178 return rc
== XpmSuccess
;
4181 #endif /* HAVE_XPM */
4185 /* XPM support functions for Mac OS where libxpm is not available.
4186 Only XPM version 3 (without any extensions) is supported. */
4188 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
4189 const unsigned char **, int *));
4190 static Lisp_Object xpm_make_color_table_v
4191 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4192 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4193 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
4195 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4196 const unsigned char *, int));
4197 static Lisp_Object xpm_make_color_table_h
4198 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
4199 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
4200 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
4202 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4203 const unsigned char *, int));
4204 static int xpm_str_to_color_key
P_ ((const char *));
4205 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4206 const unsigned char *, const unsigned char *));
4208 /* Tokens returned from xpm_scan. */
4217 /* Scan an XPM data and return a character (< 256) or a token defined
4218 by enum xpm_token above. *S and END are the start (inclusive) and
4219 the end (exclusive) addresses of the data, respectively. Advance
4220 *S while scanning. If token is either XPM_TK_IDENT or
4221 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4222 length of the corresponding token, respectively. */
4225 xpm_scan (s
, end
, beg
, len
)
4226 const unsigned char **s
, *end
, **beg
;
4233 /* Skip white-space. */
4234 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4237 /* gnus-pointer.xpm uses '-' in its identifier.
4238 sb-dir-plus.xpm uses '+' in its identifier. */
4239 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4243 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4246 return XPM_TK_IDENT
;
4251 while (*s
< end
&& **s
!= '"')
4256 return XPM_TK_STRING
;
4260 if (*s
< end
&& **s
== '*')
4262 /* C-style comment. */
4266 while (*s
< end
&& *(*s
)++ != '*')
4269 while (*s
< end
&& **s
!= '/');
4283 /* Functions for color table lookup in XPM data. A Key is a string
4284 specifying the color of each pixel in XPM data. A value is either
4285 an integer that specifies a pixel color, Qt that specifies
4286 transparency, or Qnil for the unspecified color. If the length of
4287 the key string is one, a vector is used as a table. Otherwise, a
4288 hash table is used. */
4291 xpm_make_color_table_v (put_func
, get_func
)
4292 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4293 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4295 *put_func
= xpm_put_color_table_v
;
4296 *get_func
= xpm_get_color_table_v
;
4297 return Fmake_vector (make_number (256), Qnil
);
4301 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4302 Lisp_Object color_table
;
4303 const unsigned char *chars_start
;
4307 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4311 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4312 Lisp_Object color_table
;
4313 const unsigned char *chars_start
;
4316 return XVECTOR (color_table
)->contents
[*chars_start
];
4320 xpm_make_color_table_h (put_func
, get_func
)
4321 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4322 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4324 *put_func
= xpm_put_color_table_h
;
4325 *get_func
= xpm_get_color_table_h
;
4326 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4327 make_float (DEFAULT_REHASH_SIZE
),
4328 make_float (DEFAULT_REHASH_THRESHOLD
),
4333 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4334 Lisp_Object color_table
;
4335 const unsigned char *chars_start
;
4339 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4341 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4343 hash_lookup (table
, chars
, &hash_code
);
4344 hash_put (table
, chars
, color
, hash_code
);
4348 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4349 Lisp_Object color_table
;
4350 const unsigned char *chars_start
;
4353 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4354 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4357 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4360 enum xpm_color_key
{
4368 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4371 xpm_str_to_color_key (s
)
4377 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4379 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4385 xpm_load_image (f
, img
, contents
, end
)
4388 const unsigned char *contents
, *end
;
4390 const unsigned char *s
= contents
, *beg
, *str
;
4391 unsigned char buffer
[BUFSIZ
];
4392 int width
, height
, x
, y
;
4393 int num_colors
, chars_per_pixel
;
4395 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4396 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4397 Lisp_Object frame
, color_symbols
, color_table
;
4398 int best_key
, have_mask
= 0;
4399 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4402 LA1 = xpm_scan (&s, end, &beg, &len)
4404 #define expect(TOKEN) \
4405 if (LA1 != (TOKEN)) \
4410 #define expect_ident(IDENT) \
4411 if (LA1 == XPM_TK_IDENT \
4412 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4417 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4421 expect_ident ("static");
4422 expect_ident ("char");
4424 expect (XPM_TK_IDENT
);
4429 expect (XPM_TK_STRING
);
4432 memcpy (buffer
, beg
, len
);
4434 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4435 &num_colors
, &chars_per_pixel
) != 4
4436 || width
<= 0 || height
<= 0
4437 || num_colors
<= 0 || chars_per_pixel
<= 0)
4440 if (!check_image_size (f
, width
, height
))
4442 image_error ("Invalid image size", Qnil
, Qnil
);
4448 XSETFRAME (frame
, f
);
4449 if (!NILP (Fxw_display_color_p (frame
)))
4450 best_key
= XPM_COLOR_KEY_C
;
4451 else if (!NILP (Fx_display_grayscale_p (frame
)))
4452 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4453 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4455 best_key
= XPM_COLOR_KEY_M
;
4457 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4458 if (chars_per_pixel
== 1)
4459 color_table
= xpm_make_color_table_v (&put_color_table
,
4462 color_table
= xpm_make_color_table_h (&put_color_table
,
4465 while (num_colors
-- > 0)
4467 unsigned char *color
, *max_color
;
4468 int key
, next_key
, max_key
= 0;
4469 Lisp_Object symbol_color
= Qnil
, color_val
;
4472 expect (XPM_TK_STRING
);
4473 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4475 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4476 buffer
[len
- chars_per_pixel
] = '\0';
4478 str
= strtok (buffer
, " \t");
4481 key
= xpm_str_to_color_key (str
);
4486 color
= strtok (NULL
, " \t");
4490 while ((str
= strtok (NULL
, " \t")) != NULL
)
4492 next_key
= xpm_str_to_color_key (str
);
4495 color
[strlen (color
)] = ' ';
4498 if (key
== XPM_COLOR_KEY_S
)
4500 if (NILP (symbol_color
))
4501 symbol_color
= build_string (color
);
4503 else if (max_key
< key
&& key
<= best_key
)
4513 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4515 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4517 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4519 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4521 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4523 color_val
= make_number (cdef
.pixel
);
4526 if (NILP (color_val
) && max_key
> 0)
4528 if (xstricmp (max_color
, "None") == 0)
4530 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4531 color_val
= make_number (cdef
.pixel
);
4533 if (!NILP (color_val
))
4534 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4539 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4540 &ximg
, &img
->pixmap
)
4541 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4542 &mask_img
, &img
->mask
))
4544 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4548 for (y
= 0; y
< height
; y
++)
4550 expect (XPM_TK_STRING
);
4552 if (len
< width
* chars_per_pixel
)
4554 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4556 Lisp_Object color_val
=
4557 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4559 XPutPixel (ximg
, x
, y
,
4560 (INTEGERP (color_val
) ? XINT (color_val
)
4561 : FRAME_FOREGROUND_PIXEL (f
)));
4562 XPutPixel (mask_img
, x
, y
,
4563 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4564 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4571 img
->height
= height
;
4573 /* Maybe fill in the background field while we have ximg handy. */
4574 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4575 IMAGE_BACKGROUND (img
, f
, ximg
);
4577 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4578 x_destroy_x_image (ximg
);
4581 /* Fill in the background_transparent field while we have the
4583 image_background_transparent (img
, f
, mask_img
);
4585 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4586 x_destroy_x_image (mask_img
);
4590 x_destroy_x_image (mask_img
);
4591 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4592 img
->mask
= NO_PIXMAP
;
4598 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4600 x_destroy_x_image (ximg
);
4601 x_destroy_x_image (mask_img
);
4602 x_clear_image (f
, img
);
4616 Lisp_Object file_name
;
4618 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4619 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4620 if (STRINGP (file_name
))
4623 unsigned char *contents
;
4625 struct gcpro gcpro1
;
4627 file
= x_find_image_file (file_name
);
4629 if (!STRINGP (file
))
4631 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4636 contents
= slurp_file (SDATA (file
), &size
);
4637 if (contents
== NULL
)
4639 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4644 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4652 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4653 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4654 SDATA (data
) + SBYTES (data
));
4664 /***********************************************************************
4666 ***********************************************************************/
4668 #ifdef COLOR_TABLE_SUPPORT
4670 /* An entry in the color table mapping an RGB color to a pixel color. */
4675 unsigned long pixel
;
4677 /* Next in color table collision list. */
4678 struct ct_color
*next
;
4681 /* The bucket vector size to use. Must be prime. */
4685 /* Value is a hash of the RGB color given by R, G, and B. */
4687 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4689 /* The color hash table. */
4691 struct ct_color
**ct_table
;
4693 /* Number of entries in the color table. */
4695 int ct_colors_allocated
;
4697 /* Initialize the color table. */
4702 int size
= CT_SIZE
* sizeof (*ct_table
);
4703 ct_table
= (struct ct_color
**) xmalloc (size
);
4704 bzero (ct_table
, size
);
4705 ct_colors_allocated
= 0;
4709 /* Free memory associated with the color table. */
4715 struct ct_color
*p
, *next
;
4717 for (i
= 0; i
< CT_SIZE
; ++i
)
4718 for (p
= ct_table
[i
]; p
; p
= next
)
4729 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4730 entry for that color already is in the color table, return the
4731 pixel color of that entry. Otherwise, allocate a new color for R,
4732 G, B, and make an entry in the color table. */
4734 static unsigned long
4735 lookup_rgb_color (f
, r
, g
, b
)
4739 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4740 int i
= hash
% CT_SIZE
;
4742 Display_Info
*dpyinfo
;
4744 /* Handle TrueColor visuals specially, which improves performance by
4745 two orders of magnitude. Freeing colors on TrueColor visuals is
4746 a nop, and pixel colors specify RGB values directly. See also
4747 the Xlib spec, chapter 3.1. */
4748 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4749 if (dpyinfo
->red_bits
> 0)
4751 unsigned long pr
, pg
, pb
;
4753 /* Apply gamma-correction like normal color allocation does. */
4757 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4758 gamma_correct (f
, &color
);
4759 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4762 /* Scale down RGB values to the visual's bits per RGB, and shift
4763 them to the right position in the pixel color. Note that the
4764 original RGB values are 16-bit values, as usual in X. */
4765 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4766 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4767 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4769 /* Assemble the pixel color. */
4770 return pr
| pg
| pb
;
4773 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4774 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4780 #ifdef HAVE_X_WINDOWS
4789 cmap
= FRAME_X_COLORMAP (f
);
4790 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4793 ++ct_colors_allocated
;
4794 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4798 p
->pixel
= color
.pixel
;
4799 p
->next
= ct_table
[i
];
4803 return FRAME_FOREGROUND_PIXEL (f
);
4808 color
= PALETTERGB (r
, g
, b
);
4810 color
= RGB_TO_ULONG (r
, g
, b
);
4811 #endif /* HAVE_NTGUI */
4812 ++ct_colors_allocated
;
4813 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4818 p
->next
= ct_table
[i
];
4820 #endif /* HAVE_X_WINDOWS */
4828 /* Look up pixel color PIXEL which is used on frame F in the color
4829 table. If not already present, allocate it. Value is PIXEL. */
4831 static unsigned long
4832 lookup_pixel_color (f
, pixel
)
4834 unsigned long pixel
;
4836 int i
= pixel
% CT_SIZE
;
4839 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4840 if (p
->pixel
== pixel
)
4849 #ifdef HAVE_X_WINDOWS
4850 cmap
= FRAME_X_COLORMAP (f
);
4851 color
.pixel
= pixel
;
4852 x_query_color (f
, &color
);
4853 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4856 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4857 color
.pixel
= pixel
;
4858 XQueryColor (NULL
, cmap
, &color
);
4859 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4861 #endif /* HAVE_X_WINDOWS */
4865 ++ct_colors_allocated
;
4867 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4872 p
->next
= ct_table
[i
];
4876 return FRAME_FOREGROUND_PIXEL (f
);
4882 /* Value is a vector of all pixel colors contained in the color table,
4883 allocated via xmalloc. Set *N to the number of colors. */
4885 static unsigned long *
4886 colors_in_color_table (n
)
4891 unsigned long *colors
;
4893 if (ct_colors_allocated
== 0)
4900 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4902 *n
= ct_colors_allocated
;
4904 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4905 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4906 colors
[j
++] = p
->pixel
;
4912 #else /* COLOR_TABLE_SUPPORT */
4914 static unsigned long
4915 lookup_rgb_color (f
, r
, g
, b
)
4919 unsigned long pixel
;
4922 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4923 gamma_correct (f
, &pixel
);
4927 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4928 #endif /* HAVE_NTGUI */
4937 #endif /* COLOR_TABLE_SUPPORT */
4940 /***********************************************************************
4942 ***********************************************************************/
4944 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4945 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4946 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4949 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4950 #endif /* HAVE_NTGUI */
4952 /* Non-zero means draw a cross on images having `:conversion
4955 int cross_disabled_images
;
4957 /* Edge detection matrices for different edge-detection
4960 static int emboss_matrix
[9] = {
4962 2, -1, 0, /* y - 1 */
4964 0, 1, -2 /* y + 1 */
4967 static int laplace_matrix
[9] = {
4969 1, 0, 0, /* y - 1 */
4971 0, 0, -1 /* y + 1 */
4974 /* Value is the intensity of the color whose red/green/blue values
4977 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4980 /* On frame F, return an array of XColor structures describing image
4981 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4982 non-zero means also fill the red/green/blue members of the XColor
4983 structures. Value is a pointer to the array of XColors structures,
4984 allocated with xmalloc; it must be freed by the caller. */
4987 x_to_xcolors (f
, img
, rgb_p
)
4994 XImagePtr_or_DC ximg
;
4998 #endif /* HAVE_NTGUI */
5000 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
5003 /* Get the X image IMG->pixmap. */
5004 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
5005 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
5007 /* Load the image into a memory device context. */
5008 hdc
= get_frame_dc (f
);
5009 ximg
= CreateCompatibleDC (hdc
);
5010 release_frame_dc (f
, hdc
);
5011 prev
= SelectObject (ximg
, img
->pixmap
);
5012 #endif /* HAVE_NTGUI */
5014 /* Fill the `pixel' members of the XColor array. I wished there
5015 were an easy and portable way to circumvent XGetPixel. */
5017 for (y
= 0; y
< img
->height
; ++y
)
5021 #ifdef HAVE_X_WINDOWS
5022 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5023 p
->pixel
= XGetPixel (ximg
, x
, y
);
5025 x_query_colors (f
, row
, img
->width
);
5029 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5031 /* W32_TODO: palette support needed here? */
5032 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
5036 p
->red
= RED16_FROM_ULONG (p
->pixel
);
5037 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
5038 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
5041 p
->red
= 256 * GetRValue (p
->pixel
);
5042 p
->green
= 256 * GetGValue (p
->pixel
);
5043 p
->blue
= 256 * GetBValue (p
->pixel
);
5044 #endif /* HAVE_NTGUI */
5047 #endif /* HAVE_X_WINDOWS */
5050 Destroy_Image (ximg
, prev
);
5057 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5058 created with CreateDIBSection, with the pointer to the bit values
5059 stored in ximg->data. */
5062 XPutPixel (ximg
, x
, y
, color
)
5067 int width
= ximg
->info
.bmiHeader
.biWidth
;
5068 int height
= ximg
->info
.bmiHeader
.biHeight
;
5069 unsigned char * pixel
;
5071 /* True color images. */
5072 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
5074 int rowbytes
= width
* 3;
5075 /* Ensure scanlines are aligned on 4 byte boundaries. */
5077 rowbytes
+= 4 - (rowbytes
% 4);
5079 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
5080 /* Windows bitmaps are in BGR order. */
5081 *pixel
= GetBValue (color
);
5082 *(pixel
+ 1) = GetGValue (color
);
5083 *(pixel
+ 2) = GetRValue (color
);
5085 /* Monochrome images. */
5086 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
5088 int rowbytes
= width
/ 8;
5089 /* Ensure scanlines are aligned on 4 byte boundaries. */
5091 rowbytes
+= 4 - (rowbytes
% 4);
5092 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
5093 /* Filter out palette info. */
5094 if (color
& 0x00ffffff)
5095 *pixel
= *pixel
| (1 << x
% 8);
5097 *pixel
= *pixel
& ~(1 << x
% 8);
5100 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
5103 #endif /* HAVE_NTGUI */
5105 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5106 RGB members are set. F is the frame on which this all happens.
5107 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5110 x_from_xcolors (f
, img
, colors
)
5120 init_color_table ();
5122 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5125 for (y
= 0; y
< img
->height
; ++y
)
5126 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5128 unsigned long pixel
;
5129 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5130 XPutPixel (oimg
, x
, y
, pixel
);
5134 x_clear_image_1 (f
, img
, 1, 0, 1);
5136 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5137 x_destroy_x_image (oimg
);
5138 img
->pixmap
= pixmap
;
5139 #ifdef COLOR_TABLE_SUPPORT
5140 img
->colors
= colors_in_color_table (&img
->ncolors
);
5141 free_color_table ();
5142 #endif /* COLOR_TABLE_SUPPORT */
5146 /* On frame F, perform edge-detection on image IMG.
5148 MATRIX is a nine-element array specifying the transformation
5149 matrix. See emboss_matrix for an example.
5151 COLOR_ADJUST is a color adjustment added to each pixel of the
5155 x_detect_edges (f
, img
, matrix
, color_adjust
)
5158 int matrix
[9], color_adjust
;
5160 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5164 for (i
= sum
= 0; i
< 9; ++i
)
5165 sum
+= abs (matrix
[i
]);
5167 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5169 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5171 for (y
= 0; y
< img
->height
; ++y
)
5173 p
= COLOR (new, 0, y
);
5174 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5175 p
= COLOR (new, img
->width
- 1, y
);
5176 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5179 for (x
= 1; x
< img
->width
- 1; ++x
)
5181 p
= COLOR (new, x
, 0);
5182 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5183 p
= COLOR (new, x
, img
->height
- 1);
5184 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5187 for (y
= 1; y
< img
->height
- 1; ++y
)
5189 p
= COLOR (new, 1, y
);
5191 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5193 int r
, g
, b
, y1
, x1
;
5196 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5197 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5200 XColor
*t
= COLOR (colors
, x1
, y1
);
5201 r
+= matrix
[i
] * t
->red
;
5202 g
+= matrix
[i
] * t
->green
;
5203 b
+= matrix
[i
] * t
->blue
;
5206 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5207 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5208 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5209 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5214 x_from_xcolors (f
, img
, new);
5220 /* Perform the pre-defined `emboss' edge-detection on image IMG
5228 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5232 /* Transform image IMG which is used on frame F with a Laplace
5233 edge-detection algorithm. The result is an image that can be used
5234 to draw disabled buttons, for example. */
5241 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5245 /* Perform edge-detection on image IMG on frame F, with specified
5246 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5248 MATRIX must be either
5250 - a list of at least 9 numbers in row-major form
5251 - a vector of at least 9 numbers
5253 COLOR_ADJUST nil means use a default; otherwise it must be a
5257 x_edge_detection (f
, img
, matrix
, color_adjust
)
5260 Lisp_Object matrix
, color_adjust
;
5268 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5269 ++i
, matrix
= XCDR (matrix
))
5270 trans
[i
] = XFLOATINT (XCAR (matrix
));
5272 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5274 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5275 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5278 if (NILP (color_adjust
))
5279 color_adjust
= make_number (0xffff / 2);
5281 if (i
== 9 && NUMBERP (color_adjust
))
5282 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5286 /* Transform image IMG on frame F so that it looks disabled. */
5289 x_disable_image (f
, img
)
5293 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5295 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5297 int n_planes
= dpyinfo
->n_planes
;
5298 #endif /* HAVE_NTGUI */
5302 /* Color (or grayscale). Convert to gray, and equalize. Just
5303 drawing such images with a stipple can look very odd, so
5304 we're using this method instead. */
5305 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5307 const int h
= 15000;
5308 const int l
= 30000;
5310 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5314 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5315 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5316 p
->red
= p
->green
= p
->blue
= i2
;
5319 x_from_xcolors (f
, img
, colors
);
5322 /* Draw a cross over the disabled image, if we must or if we
5324 if (n_planes
< 2 || cross_disabled_images
)
5327 Display
*dpy
= FRAME_X_DISPLAY (f
);
5331 #define MaskForeground(f) PIX_MASK_DRAW
5333 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5336 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5337 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5338 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5339 img
->width
- 1, img
->height
- 1);
5340 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5346 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5347 XSetForeground (dpy
, gc
, MaskForeground (f
));
5348 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5349 img
->width
- 1, img
->height
- 1);
5350 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5358 hdc
= get_frame_dc (f
);
5359 bmpdc
= CreateCompatibleDC (hdc
);
5360 release_frame_dc (f
, hdc
);
5362 prev
= SelectObject (bmpdc
, img
->pixmap
);
5364 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5365 MoveToEx (bmpdc
, 0, 0, NULL
);
5366 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5367 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5368 LineTo (bmpdc
, img
->width
- 1, 0);
5372 SelectObject (bmpdc
, img
->mask
);
5373 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5374 MoveToEx (bmpdc
, 0, 0, NULL
);
5375 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5376 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5377 LineTo (bmpdc
, img
->width
- 1, 0);
5379 SelectObject (bmpdc
, prev
);
5381 #endif /* HAVE_NTGUI */
5386 /* Build a mask for image IMG which is used on frame F. FILE is the
5387 name of an image file, for error messages. HOW determines how to
5388 determine the background color of IMG. If it is a list '(R G B)',
5389 with R, G, and B being integers >= 0, take that as the color of the
5390 background. Otherwise, determine the background color of IMG
5391 heuristically. Value is non-zero if successful. */
5394 x_build_heuristic_mask (f
, img
, how
)
5399 XImagePtr_or_DC ximg
;
5407 #endif /* HAVE_NTGUI */
5408 int x
, y
, rc
, use_img_background
;
5409 unsigned long bg
= 0;
5413 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5414 img
->mask
= NO_PIXMAP
;
5415 img
->background_transparent_valid
= 0;
5419 /* Create an image and pixmap serving as mask. */
5420 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5421 &mask_img
, &img
->mask
);
5425 /* Get the X image of IMG->pixmap. */
5426 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5427 img
->width
, img
->height
,
5430 /* Create the bit array serving as mask. */
5431 row_width
= (img
->width
+ 7) / 8;
5432 mask_img
= xmalloc (row_width
* img
->height
);
5433 bzero (mask_img
, row_width
* img
->height
);
5435 /* Create a memory device context for IMG->pixmap. */
5436 frame_dc
= get_frame_dc (f
);
5437 ximg
= CreateCompatibleDC (frame_dc
);
5438 release_frame_dc (f
, frame_dc
);
5439 prev
= SelectObject (ximg
, img
->pixmap
);
5440 #endif /* HAVE_NTGUI */
5442 /* Determine the background color of ximg. If HOW is `(R G B)'
5443 take that as color. Otherwise, use the image's background color. */
5444 use_img_background
= 1;
5450 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5452 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5456 if (i
== 3 && NILP (how
))
5458 char color_name
[30];
5459 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5462 0x00ffffff & /* Filter out palette info. */
5463 #endif /* HAVE_NTGUI */
5464 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5465 use_img_background
= 0;
5469 if (use_img_background
)
5470 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5472 /* Set all bits in mask_img to 1 whose color in ximg is different
5473 from the background color bg. */
5475 for (y
= 0; y
< img
->height
; ++y
)
5476 for (x
= 0; x
< img
->width
; ++x
)
5477 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5478 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5480 /* Fill in the background_transparent field while we have the mask handy. */
5481 image_background_transparent (img
, f
, mask_img
);
5483 /* Put mask_img into img->mask. */
5484 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5485 x_destroy_x_image (mask_img
);
5488 for (y
= 0; y
< img
->height
; ++y
)
5489 for (x
= 0; x
< img
->width
; ++x
)
5491 COLORREF p
= GetPixel (ximg
, x
, y
);
5493 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5496 /* Create the mask image. */
5497 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5499 /* Fill in the background_transparent field while we have the mask handy. */
5500 SelectObject (ximg
, img
->mask
);
5501 image_background_transparent (img
, f
, ximg
);
5503 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5505 #endif /* HAVE_NTGUI */
5507 Destroy_Image (ximg
, prev
);
5513 /***********************************************************************
5514 PBM (mono, gray, color)
5515 ***********************************************************************/
5517 static int pbm_image_p
P_ ((Lisp_Object object
));
5518 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5519 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5521 /* The symbol `pbm' identifying images of this type. */
5525 /* Indices of image specification fields in gs_format, below. */
5527 enum pbm_keyword_index
5543 /* Vector of image_keyword structures describing the format
5544 of valid user-defined image specifications. */
5546 static struct image_keyword pbm_format
[PBM_LAST
] =
5548 {":type", IMAGE_SYMBOL_VALUE
, 1},
5549 {":file", IMAGE_STRING_VALUE
, 0},
5550 {":data", IMAGE_STRING_VALUE
, 0},
5551 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5552 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5553 {":relief", IMAGE_INTEGER_VALUE
, 0},
5554 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5555 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5556 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5557 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5558 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5561 /* Structure describing the image type `pbm'. */
5563 static struct image_type pbm_type
=
5573 /* Return non-zero if OBJECT is a valid PBM image specification. */
5576 pbm_image_p (object
)
5579 struct image_keyword fmt
[PBM_LAST
];
5581 bcopy (pbm_format
, fmt
, sizeof fmt
);
5583 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5586 /* Must specify either :data or :file. */
5587 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5591 /* Scan a decimal number from *S and return it. Advance *S while
5592 reading the number. END is the end of the string. Value is -1 at
5596 pbm_scan_number (s
, end
)
5597 unsigned char **s
, *end
;
5599 int c
= 0, val
= -1;
5603 /* Skip white-space. */
5604 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5609 /* Skip comment to end of line. */
5610 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5613 else if (isdigit (c
))
5615 /* Read decimal number. */
5617 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5618 val
= 10 * val
+ c
- '0';
5630 #if 0 /* Unused. ++kfs */
5632 /* Read FILE into memory. Value is a pointer to a buffer allocated
5633 with xmalloc holding FILE's contents. Value is null if an error
5634 occurred. *SIZE is set to the size of the file. */
5637 pbm_read_file (file
, size
)
5645 if (stat (SDATA (file
), &st
) == 0
5646 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5647 && (buf
= (char *) xmalloc (st
.st_size
),
5648 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5667 #endif /* HAVE_NTGUI */
5669 /* Load PBM image IMG for use on frame F. */
5677 int width
, height
, max_color_idx
= 0;
5679 Lisp_Object file
, specified_file
;
5680 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5681 struct gcpro gcpro1
;
5682 unsigned char *contents
= NULL
;
5683 unsigned char *end
, *p
;
5686 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5690 if (STRINGP (specified_file
))
5692 file
= x_find_image_file (specified_file
);
5693 if (!STRINGP (file
))
5695 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5700 contents
= slurp_file (SDATA (file
), &size
);
5701 if (contents
== NULL
)
5703 image_error ("Error reading `%s'", file
, Qnil
);
5709 end
= contents
+ size
;
5714 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5716 end
= p
+ SBYTES (data
);
5719 /* Check magic number. */
5720 if (end
- p
< 2 || *p
++ != 'P')
5722 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5732 raw_p
= 0, type
= PBM_MONO
;
5736 raw_p
= 0, type
= PBM_GRAY
;
5740 raw_p
= 0, type
= PBM_COLOR
;
5744 raw_p
= 1, type
= PBM_MONO
;
5748 raw_p
= 1, type
= PBM_GRAY
;
5752 raw_p
= 1, type
= PBM_COLOR
;
5756 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5760 /* Read width, height, maximum color-component. Characters
5761 starting with `#' up to the end of a line are ignored. */
5762 width
= pbm_scan_number (&p
, end
);
5763 height
= pbm_scan_number (&p
, end
);
5765 if (type
!= PBM_MONO
)
5767 max_color_idx
= pbm_scan_number (&p
, end
);
5768 if (raw_p
&& max_color_idx
> 255)
5769 max_color_idx
= 255;
5772 if (!check_image_size (f
, width
, height
)
5773 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5776 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5777 &ximg
, &img
->pixmap
))
5780 /* Initialize the color hash table. */
5781 init_color_table ();
5783 if (type
== PBM_MONO
)
5786 struct image_keyword fmt
[PBM_LAST
];
5787 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5788 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5790 /* Parse the image specification. */
5791 bcopy (pbm_format
, fmt
, sizeof fmt
);
5792 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5794 /* Get foreground and background colors, maybe allocate colors. */
5795 if (fmt
[PBM_FOREGROUND
].count
5796 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5797 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5798 if (fmt
[PBM_BACKGROUND
].count
5799 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5801 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5802 img
->background
= bg
;
5803 img
->background_valid
= 1;
5806 for (y
= 0; y
< height
; ++y
)
5807 for (x
= 0; x
< width
; ++x
)
5815 x_destroy_x_image (ximg
);
5816 x_clear_image (f
, img
);
5817 image_error ("Invalid image size in image `%s'",
5827 g
= pbm_scan_number (&p
, end
);
5829 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5835 && ((type
== PBM_GRAY
)
5836 ? (p
+ height
* width
> end
)
5837 : (p
+ 3 * height
* width
> end
)))
5839 x_destroy_x_image (ximg
);
5840 x_clear_image (f
, img
);
5841 image_error ("Invalid image size in image `%s'",
5846 for (y
= 0; y
< height
; ++y
)
5847 for (x
= 0; x
< width
; ++x
)
5851 if (type
== PBM_GRAY
)
5852 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5861 r
= pbm_scan_number (&p
, end
);
5862 g
= pbm_scan_number (&p
, end
);
5863 b
= pbm_scan_number (&p
, end
);
5866 if (r
< 0 || g
< 0 || b
< 0)
5868 x_destroy_x_image (ximg
);
5869 image_error ("Invalid pixel value in image `%s'",
5874 /* RGB values are now in the range 0..max_color_idx.
5875 Scale this to the range 0..0xffff supported by X. */
5876 r
= (double) r
* 65535 / max_color_idx
;
5877 g
= (double) g
* 65535 / max_color_idx
;
5878 b
= (double) b
* 65535 / max_color_idx
;
5879 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5883 #ifdef COLOR_TABLE_SUPPORT
5884 /* Store in IMG->colors the colors allocated for the image, and
5885 free the color table. */
5886 img
->colors
= colors_in_color_table (&img
->ncolors
);
5887 free_color_table ();
5888 #endif /* COLOR_TABLE_SUPPORT */
5891 img
->height
= height
;
5893 /* Maybe fill in the background field while we have ximg handy. */
5895 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5896 /* Casting avoids a GCC warning. */
5897 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5899 /* Put the image into a pixmap. */
5900 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5901 x_destroy_x_image (ximg
);
5903 /* X and W32 versions did it here, MAC version above. ++kfs
5905 img->height = height; */
5913 /***********************************************************************
5915 ***********************************************************************/
5917 #if defined (HAVE_PNG) || defined (MAC_OS)
5919 /* Function prototypes. */
5921 static int png_image_p
P_ ((Lisp_Object object
));
5922 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5924 /* The symbol `png' identifying images of this type. */
5928 /* Indices of image specification fields in png_format, below. */
5930 enum png_keyword_index
5945 /* Vector of image_keyword structures describing the format
5946 of valid user-defined image specifications. */
5948 static struct image_keyword png_format
[PNG_LAST
] =
5950 {":type", IMAGE_SYMBOL_VALUE
, 1},
5951 {":data", IMAGE_STRING_VALUE
, 0},
5952 {":file", IMAGE_STRING_VALUE
, 0},
5953 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5954 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5955 {":relief", IMAGE_INTEGER_VALUE
, 0},
5956 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5957 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5958 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5959 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5962 /* Structure describing the image type `png'. */
5964 static struct image_type png_type
=
5973 /* Return non-zero if OBJECT is a valid PNG image specification. */
5976 png_image_p (object
)
5979 struct image_keyword fmt
[PNG_LAST
];
5980 bcopy (png_format
, fmt
, sizeof fmt
);
5982 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5985 /* Must specify either the :data or :file keyword. */
5986 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5989 #endif /* HAVE_PNG || MAC_OS */
5994 #if defined HAVE_LIBPNG_PNG_H
5995 # include <libpng/png.h>
6001 /* PNG library details. */
6003 DEF_IMGLIB_FN (png_get_io_ptr
);
6004 DEF_IMGLIB_FN (png_check_sig
);
6005 DEF_IMGLIB_FN (png_create_read_struct
);
6006 DEF_IMGLIB_FN (png_create_info_struct
);
6007 DEF_IMGLIB_FN (png_destroy_read_struct
);
6008 DEF_IMGLIB_FN (png_set_read_fn
);
6009 DEF_IMGLIB_FN (png_set_sig_bytes
);
6010 DEF_IMGLIB_FN (png_read_info
);
6011 DEF_IMGLIB_FN (png_get_IHDR
);
6012 DEF_IMGLIB_FN (png_get_valid
);
6013 DEF_IMGLIB_FN (png_set_strip_16
);
6014 DEF_IMGLIB_FN (png_set_expand
);
6015 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
6016 DEF_IMGLIB_FN (png_set_background
);
6017 DEF_IMGLIB_FN (png_get_bKGD
);
6018 DEF_IMGLIB_FN (png_read_update_info
);
6019 DEF_IMGLIB_FN (png_get_channels
);
6020 DEF_IMGLIB_FN (png_get_rowbytes
);
6021 DEF_IMGLIB_FN (png_read_image
);
6022 DEF_IMGLIB_FN (png_read_end
);
6023 DEF_IMGLIB_FN (png_error
);
6026 init_png_functions (Lisp_Object libraries
)
6030 /* Try loading libpng under probable names. */
6031 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
6034 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
6035 LOAD_IMGLIB_FN (library
, png_check_sig
);
6036 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
6037 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
6038 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
6039 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
6040 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
6041 LOAD_IMGLIB_FN (library
, png_read_info
);
6042 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
6043 LOAD_IMGLIB_FN (library
, png_get_valid
);
6044 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
6045 LOAD_IMGLIB_FN (library
, png_set_expand
);
6046 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
6047 LOAD_IMGLIB_FN (library
, png_set_background
);
6048 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
6049 LOAD_IMGLIB_FN (library
, png_read_update_info
);
6050 LOAD_IMGLIB_FN (library
, png_get_channels
);
6051 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
6052 LOAD_IMGLIB_FN (library
, png_read_image
);
6053 LOAD_IMGLIB_FN (library
, png_read_end
);
6054 LOAD_IMGLIB_FN (library
, png_error
);
6059 #define fn_png_get_io_ptr png_get_io_ptr
6060 #define fn_png_check_sig png_check_sig
6061 #define fn_png_create_read_struct png_create_read_struct
6062 #define fn_png_create_info_struct png_create_info_struct
6063 #define fn_png_destroy_read_struct png_destroy_read_struct
6064 #define fn_png_set_read_fn png_set_read_fn
6065 #define fn_png_set_sig_bytes png_set_sig_bytes
6066 #define fn_png_read_info png_read_info
6067 #define fn_png_get_IHDR png_get_IHDR
6068 #define fn_png_get_valid png_get_valid
6069 #define fn_png_set_strip_16 png_set_strip_16
6070 #define fn_png_set_expand png_set_expand
6071 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6072 #define fn_png_set_background png_set_background
6073 #define fn_png_get_bKGD png_get_bKGD
6074 #define fn_png_read_update_info png_read_update_info
6075 #define fn_png_get_channels png_get_channels
6076 #define fn_png_get_rowbytes png_get_rowbytes
6077 #define fn_png_read_image png_read_image
6078 #define fn_png_read_end png_read_end
6079 #define fn_png_error png_error
6081 #endif /* HAVE_NTGUI */
6083 /* Error and warning handlers installed when the PNG library
6087 my_png_error (png_ptr
, msg
)
6088 png_struct
*png_ptr
;
6091 xassert (png_ptr
!= NULL
);
6092 image_error ("PNG error: %s", build_string (msg
), Qnil
);
6093 longjmp (png_ptr
->jmpbuf
, 1);
6098 my_png_warning (png_ptr
, msg
)
6099 png_struct
*png_ptr
;
6102 xassert (png_ptr
!= NULL
);
6103 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
6106 /* Memory source for PNG decoding. */
6108 struct png_memory_storage
6110 unsigned char *bytes
; /* The data */
6111 size_t len
; /* How big is it? */
6112 int index
; /* Where are we? */
6116 /* Function set as reader function when reading PNG image from memory.
6117 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6118 bytes from the input to DATA. */
6121 png_read_from_memory (png_ptr
, data
, length
)
6122 png_structp png_ptr
;
6126 struct png_memory_storage
*tbr
6127 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
6129 if (length
> tbr
->len
- tbr
->index
)
6130 fn_png_error (png_ptr
, "Read error");
6132 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6133 tbr
->index
= tbr
->index
+ length
;
6137 /* Function set as reader function when reading PNG image from a file.
6138 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6139 bytes from the input to DATA. */
6142 png_read_from_file (png_ptr
, data
, length
)
6143 png_structp png_ptr
;
6147 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6149 if (fread (data
, 1, length
, fp
) < length
)
6150 fn_png_error (png_ptr
, "Read error");
6154 /* Load PNG image IMG for use on frame F. Value is non-zero if
6162 Lisp_Object file
, specified_file
;
6163 Lisp_Object specified_data
;
6165 XImagePtr ximg
, mask_img
= NULL
;
6166 struct gcpro gcpro1
;
6167 png_struct
*png_ptr
= NULL
;
6168 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6169 FILE *volatile fp
= NULL
;
6171 png_byte
* volatile pixels
= NULL
;
6172 png_byte
** volatile rows
= NULL
;
6173 png_uint_32 width
, height
;
6174 int bit_depth
, color_type
, interlace_type
;
6176 png_uint_32 row_bytes
;
6178 double screen_gamma
;
6179 struct png_memory_storage tbr
; /* Data to be read */
6181 /* Find out what file to load. */
6182 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6183 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6187 if (NILP (specified_data
))
6189 file
= x_find_image_file (specified_file
);
6190 if (!STRINGP (file
))
6192 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6197 /* Open the image file. */
6198 fp
= fopen (SDATA (file
), "rb");
6201 image_error ("Cannot open image file `%s'", file
, Qnil
);
6206 /* Check PNG signature. */
6207 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6208 || !fn_png_check_sig (sig
, sizeof sig
))
6210 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6218 /* Read from memory. */
6219 tbr
.bytes
= SDATA (specified_data
);
6220 tbr
.len
= SBYTES (specified_data
);
6223 /* Check PNG signature. */
6224 if (tbr
.len
< sizeof sig
6225 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6227 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6232 /* Need to skip past the signature. */
6233 tbr
.bytes
+= sizeof (sig
);
6236 /* Initialize read and info structs for PNG lib. Casting return
6237 value avoids a GCC warning on W32. */
6238 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6243 if (fp
) fclose (fp
);
6248 /* Casting return value avoids a GCC warning on W32. */
6249 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6252 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6253 if (fp
) fclose (fp
);
6258 /* Casting return value avoids a GCC warning on W32. */
6259 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6262 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6263 if (fp
) fclose (fp
);
6268 /* Set error jump-back. We come back here when the PNG library
6269 detects an error. */
6270 if (setjmp (png_ptr
->jmpbuf
))
6274 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6277 if (fp
) fclose (fp
);
6282 /* Read image info. */
6283 if (!NILP (specified_data
))
6284 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6286 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6288 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6289 fn_png_read_info (png_ptr
, info_ptr
);
6290 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6291 &interlace_type
, NULL
, NULL
);
6293 if (!check_image_size (f
, width
, height
))
6296 /* If image contains simply transparency data, we prefer to
6297 construct a clipping mask. */
6298 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6303 /* This function is easier to write if we only have to handle
6304 one data format: RGB or RGBA with 8 bits per channel. Let's
6305 transform other formats into that format. */
6307 /* Strip more than 8 bits per channel. */
6308 if (bit_depth
== 16)
6309 fn_png_set_strip_16 (png_ptr
);
6311 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6313 fn_png_set_expand (png_ptr
);
6315 /* Convert grayscale images to RGB. */
6316 if (color_type
== PNG_COLOR_TYPE_GRAY
6317 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6318 fn_png_set_gray_to_rgb (png_ptr
);
6320 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
6322 #if 0 /* Avoid double gamma correction for PNG images. */
6323 { /* Tell the PNG lib to handle gamma correction for us. */
6326 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6327 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
6328 /* The libpng documentation says this is right in this case. */
6329 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6332 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
6333 /* Image contains gamma information. */
6334 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
6336 /* Use the standard default for the image gamma. */
6337 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6341 /* Handle alpha channel by combining the image with a background
6342 color. Do this only if a real alpha channel is supplied. For
6343 simple transparency, we prefer a clipping mask. */
6346 png_color_16
*image_bg
;
6347 Lisp_Object specified_bg
6348 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6350 if (STRINGP (specified_bg
))
6351 /* The user specified `:background', use that. */
6353 /* W32 version incorrectly used COLORREF here!! ++kfs */
6355 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6357 png_color_16 user_bg
;
6359 bzero (&user_bg
, sizeof user_bg
);
6360 user_bg
.red
= color
.red
>> 8;
6361 user_bg
.green
= color
.green
>> 8;
6362 user_bg
.blue
= color
.blue
>> 8;
6364 fn_png_set_background (png_ptr
, &user_bg
,
6365 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6368 /* The commented-out code checked if the png specifies a default
6369 background color, and uses that. Since we use the current
6370 frame background, it is OK for us to ignore this.
6372 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
6373 fn_png_set_background (png_ptr, image_bg,
6374 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6378 /* Image does not contain a background color with which
6379 to combine the image data via an alpha channel. Use
6380 the frame's background instead. */
6381 #ifdef HAVE_X_WINDOWS
6383 png_color_16 frame_background
;
6385 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6386 x_query_color (f
, &color
);
6388 bzero (&frame_background
, sizeof frame_background
);
6389 frame_background
.red
= color
.red
>> 8;
6390 frame_background
.green
= color
.green
>> 8;
6391 frame_background
.blue
= color
.blue
>> 8;
6392 #endif /* HAVE_X_WINDOWS */
6396 png_color_16 frame_background
;
6397 color
= FRAME_BACKGROUND_PIXEL (f
);
6398 #if 0 /* W32 TODO : Colormap support. */
6399 x_query_color (f
, &color
);
6401 bzero (&frame_background
, sizeof frame_background
);
6402 frame_background
.red
= GetRValue (color
);
6403 frame_background
.green
= GetGValue (color
);
6404 frame_background
.blue
= GetBValue (color
);
6405 #endif /* HAVE_NTGUI */
6408 unsigned long color
;
6409 png_color_16 frame_background
;
6410 color
= FRAME_BACKGROUND_PIXEL (f
);
6411 #if 0 /* MAC/W32 TODO : Colormap support. */
6412 x_query_color (f
, &color
);
6414 bzero (&frame_background
, sizeof frame_background
);
6415 frame_background
.red
= RED_FROM_ULONG (color
);
6416 frame_background
.green
= GREEN_FROM_ULONG (color
);
6417 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6420 fn_png_set_background (png_ptr
, &frame_background
,
6421 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6425 /* Update info structure. */
6426 fn_png_read_update_info (png_ptr
, info_ptr
);
6428 /* Get number of channels. Valid values are 1 for grayscale images
6429 and images with a palette, 2 for grayscale images with transparency
6430 information (alpha channel), 3 for RGB images, and 4 for RGB
6431 images with alpha channel, i.e. RGBA. If conversions above were
6432 sufficient we should only have 3 or 4 channels here. */
6433 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6434 xassert (channels
== 3 || channels
== 4);
6436 /* Number of bytes needed for one row of the image. */
6437 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6439 /* Allocate memory for the image. */
6440 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6441 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6442 for (i
= 0; i
< height
; ++i
)
6443 rows
[i
] = pixels
+ i
* row_bytes
;
6445 /* Read the entire image. */
6446 fn_png_read_image (png_ptr
, rows
);
6447 fn_png_read_end (png_ptr
, info_ptr
);
6454 /* Create the X image and pixmap. */
6455 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6459 /* Create an image and pixmap serving as mask if the PNG image
6460 contains an alpha channel. */
6463 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6464 &mask_img
, &img
->mask
))
6466 x_destroy_x_image (ximg
);
6467 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6468 img
->pixmap
= NO_PIXMAP
;
6472 /* Fill the X image and mask from PNG data. */
6473 init_color_table ();
6475 for (y
= 0; y
< height
; ++y
)
6477 png_byte
*p
= rows
[y
];
6479 for (x
= 0; x
< width
; ++x
)
6486 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6487 /* An alpha channel, aka mask channel, associates variable
6488 transparency with an image. Where other image formats
6489 support binary transparency---fully transparent or fully
6490 opaque---PNG allows up to 254 levels of partial transparency.
6491 The PNG library implements partial transparency by combining
6492 the image with a specified background color.
6494 I'm not sure how to handle this here nicely: because the
6495 background on which the image is displayed may change, for
6496 real alpha channel support, it would be necessary to create
6497 a new image for each possible background.
6499 What I'm doing now is that a mask is created if we have
6500 boolean transparency information. Otherwise I'm using
6501 the frame's background color to combine the image with. */
6506 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6512 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6513 /* Set IMG's background color from the PNG image, unless the user
6517 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6519 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6520 img
->background_valid
= 1;
6524 #ifdef COLOR_TABLE_SUPPORT
6525 /* Remember colors allocated for this image. */
6526 img
->colors
= colors_in_color_table (&img
->ncolors
);
6527 free_color_table ();
6528 #endif /* COLOR_TABLE_SUPPORT */
6531 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6536 img
->height
= height
;
6538 /* Maybe fill in the background field while we have ximg handy.
6539 Casting avoids a GCC warning. */
6540 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6542 /* Put the image into the pixmap, then free the X image and its buffer. */
6543 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6544 x_destroy_x_image (ximg
);
6546 /* Same for the mask. */
6549 /* Fill in the background_transparent field while we have the
6550 mask handy. Casting avoids a GCC warning. */
6551 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6553 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6554 x_destroy_x_image (mask_img
);
6561 #else /* HAVE_PNG */
6570 if (MyCGImageCreateWithPNGDataProvider
)
6571 return image_load_quartz2d (f
, img
, 1);
6574 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6578 #endif /* !HAVE_PNG */
6582 /***********************************************************************
6584 ***********************************************************************/
6586 #if defined (HAVE_JPEG) || defined (MAC_OS)
6588 static int jpeg_image_p
P_ ((Lisp_Object object
));
6589 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6591 /* The symbol `jpeg' identifying images of this type. */
6595 /* Indices of image specification fields in gs_format, below. */
6597 enum jpeg_keyword_index
6606 JPEG_HEURISTIC_MASK
,
6612 /* Vector of image_keyword structures describing the format
6613 of valid user-defined image specifications. */
6615 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6617 {":type", IMAGE_SYMBOL_VALUE
, 1},
6618 {":data", IMAGE_STRING_VALUE
, 0},
6619 {":file", IMAGE_STRING_VALUE
, 0},
6620 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6621 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6622 {":relief", IMAGE_INTEGER_VALUE
, 0},
6623 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6624 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6625 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6626 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6629 /* Structure describing the image type `jpeg'. */
6631 static struct image_type jpeg_type
=
6640 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6643 jpeg_image_p (object
)
6646 struct image_keyword fmt
[JPEG_LAST
];
6648 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6650 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6653 /* Must specify either the :data or :file keyword. */
6654 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6657 #endif /* HAVE_JPEG || MAC_OS */
6661 /* Work around a warning about HAVE_STDLIB_H being redefined in
6663 #ifdef HAVE_STDLIB_H
6664 #define HAVE_STDLIB_H_1
6665 #undef HAVE_STDLIB_H
6666 #endif /* HAVE_STLIB_H */
6668 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6669 /* In older releases of the jpeg library, jpeglib.h will define boolean
6670 differently depending on __WIN32__, so make sure it is defined. */
6674 #include <jpeglib.h>
6678 #ifdef HAVE_STLIB_H_1
6679 #define HAVE_STDLIB_H 1
6684 /* JPEG library details. */
6685 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6686 DEF_IMGLIB_FN (jpeg_start_decompress
);
6687 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6688 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6689 DEF_IMGLIB_FN (jpeg_read_header
);
6690 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6691 DEF_IMGLIB_FN (jpeg_std_error
);
6692 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6695 init_jpeg_functions (Lisp_Object libraries
)
6699 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6702 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6703 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6704 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6705 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6706 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6707 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6708 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6709 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6713 /* Wrapper since we can't directly assign the function pointer
6714 to another function pointer that was declared more completely easily. */
6716 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
6717 j_decompress_ptr cinfo
;
6720 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6725 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6726 #define fn_jpeg_start_decompress jpeg_start_decompress
6727 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6728 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6729 #define fn_jpeg_read_header jpeg_read_header
6730 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6731 #define fn_jpeg_std_error jpeg_std_error
6732 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6734 #endif /* HAVE_NTGUI */
6736 struct my_jpeg_error_mgr
6738 struct jpeg_error_mgr pub
;
6739 jmp_buf setjmp_buffer
;
6744 my_error_exit (cinfo
)
6747 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6748 longjmp (mgr
->setjmp_buffer
, 1);
6752 /* Init source method for JPEG data source manager. Called by
6753 jpeg_read_header() before any data is actually read. See
6754 libjpeg.doc from the JPEG lib distribution. */
6757 our_common_init_source (cinfo
)
6758 j_decompress_ptr cinfo
;
6763 /* Method to terminate data source. Called by
6764 jpeg_finish_decompress() after all data has been processed. */
6767 our_common_term_source (cinfo
)
6768 j_decompress_ptr cinfo
;
6773 /* Fill input buffer method for JPEG data source manager. Called
6774 whenever more data is needed. We read the whole image in one step,
6775 so this only adds a fake end of input marker at the end. */
6778 our_memory_fill_input_buffer (cinfo
)
6779 j_decompress_ptr cinfo
;
6781 /* Insert a fake EOI marker. */
6782 struct jpeg_source_mgr
*src
= cinfo
->src
;
6783 static JOCTET buffer
[2];
6785 buffer
[0] = (JOCTET
) 0xFF;
6786 buffer
[1] = (JOCTET
) JPEG_EOI
;
6788 src
->next_input_byte
= buffer
;
6789 src
->bytes_in_buffer
= 2;
6794 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6795 is the JPEG data source manager. */
6798 our_memory_skip_input_data (cinfo
, num_bytes
)
6799 j_decompress_ptr cinfo
;
6802 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6806 if (num_bytes
> src
->bytes_in_buffer
)
6807 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6809 src
->bytes_in_buffer
-= num_bytes
;
6810 src
->next_input_byte
+= num_bytes
;
6815 /* Set up the JPEG lib for reading an image from DATA which contains
6816 LEN bytes. CINFO is the decompression info structure created for
6817 reading the image. */
6820 jpeg_memory_src (cinfo
, data
, len
)
6821 j_decompress_ptr cinfo
;
6825 struct jpeg_source_mgr
*src
;
6827 if (cinfo
->src
== NULL
)
6829 /* First time for this JPEG object? */
6830 cinfo
->src
= (struct jpeg_source_mgr
*)
6831 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6832 sizeof (struct jpeg_source_mgr
));
6833 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6834 src
->next_input_byte
= data
;
6837 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6838 src
->init_source
= our_common_init_source
;
6839 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6840 src
->skip_input_data
= our_memory_skip_input_data
;
6841 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6842 src
->term_source
= our_common_term_source
;
6843 src
->bytes_in_buffer
= len
;
6844 src
->next_input_byte
= data
;
6848 struct jpeg_stdio_mgr
6850 struct jpeg_source_mgr mgr
;
6857 /* Size of buffer to read JPEG from file.
6858 Not too big, as we want to use alloc_small. */
6859 #define JPEG_STDIO_BUFFER_SIZE 8192
6862 /* Fill input buffer method for JPEG data source manager. Called
6863 whenever more data is needed. The data is read from a FILE *. */
6866 our_stdio_fill_input_buffer (cinfo
)
6867 j_decompress_ptr cinfo
;
6869 struct jpeg_stdio_mgr
*src
;
6871 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6876 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6878 src
->mgr
.bytes_in_buffer
= bytes
;
6881 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6883 src
->buffer
[0] = (JOCTET
) 0xFF;
6884 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6885 src
->mgr
.bytes_in_buffer
= 2;
6887 src
->mgr
.next_input_byte
= src
->buffer
;
6894 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6895 is the JPEG data source manager. */
6898 our_stdio_skip_input_data (cinfo
, num_bytes
)
6899 j_decompress_ptr cinfo
;
6902 struct jpeg_stdio_mgr
*src
;
6903 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6905 while (num_bytes
> 0 && !src
->finished
)
6907 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6909 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6910 src
->mgr
.next_input_byte
+= num_bytes
;
6915 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6916 src
->mgr
.bytes_in_buffer
= 0;
6917 src
->mgr
.next_input_byte
= NULL
;
6919 our_stdio_fill_input_buffer (cinfo
);
6925 /* Set up the JPEG lib for reading an image from a FILE *.
6926 CINFO is the decompression info structure created for
6927 reading the image. */
6930 jpeg_file_src (cinfo
, fp
)
6931 j_decompress_ptr cinfo
;
6934 struct jpeg_stdio_mgr
*src
;
6936 if (cinfo
->src
!= NULL
)
6937 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6940 /* First time for this JPEG object? */
6941 cinfo
->src
= (struct jpeg_source_mgr
*)
6942 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6943 sizeof (struct jpeg_stdio_mgr
));
6944 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6945 src
->buffer
= (JOCTET
*)
6946 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6947 JPEG_STDIO_BUFFER_SIZE
);
6952 src
->mgr
.init_source
= our_common_init_source
;
6953 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6954 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6955 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6956 src
->mgr
.term_source
= our_common_term_source
;
6957 src
->mgr
.bytes_in_buffer
= 0;
6958 src
->mgr
.next_input_byte
= NULL
;
6962 /* Load image IMG for use on frame F. Patterned after example.c
6963 from the JPEG lib. */
6970 struct jpeg_decompress_struct cinfo
;
6971 struct my_jpeg_error_mgr mgr
;
6972 Lisp_Object file
, specified_file
;
6973 Lisp_Object specified_data
;
6974 FILE * volatile fp
= NULL
;
6976 int row_stride
, x
, y
;
6977 XImagePtr ximg
= NULL
;
6979 unsigned long *colors
;
6981 struct gcpro gcpro1
;
6983 /* Open the JPEG file. */
6984 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6985 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6989 if (NILP (specified_data
))
6991 file
= x_find_image_file (specified_file
);
6992 if (!STRINGP (file
))
6994 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6999 fp
= fopen (SDATA (file
), "rb");
7002 image_error ("Cannot open `%s'", file
, Qnil
);
7008 /* Customize libjpeg's error handling to call my_error_exit when an
7009 error is detected. This function will perform a longjmp.
7010 Casting return value avoids a GCC warning on W32. */
7011 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
7012 mgr
.pub
.error_exit
= my_error_exit
;
7014 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
7018 /* Called from my_error_exit. Display a JPEG error. */
7019 char buffer
[JMSG_LENGTH_MAX
];
7020 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
7021 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
7022 build_string (buffer
));
7025 /* Close the input file and destroy the JPEG object. */
7027 fclose ((FILE *) fp
);
7028 fn_jpeg_destroy_decompress (&cinfo
);
7030 /* If we already have an XImage, free that. */
7031 x_destroy_x_image (ximg
);
7033 /* Free pixmap and colors. */
7034 x_clear_image (f
, img
);
7040 /* Create the JPEG decompression object. Let it read from fp.
7041 Read the JPEG image header. */
7042 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
7044 if (NILP (specified_data
))
7045 jpeg_file_src (&cinfo
, (FILE *) fp
);
7047 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
7048 SBYTES (specified_data
));
7050 fn_jpeg_read_header (&cinfo
, 1);
7052 /* Customize decompression so that color quantization will be used.
7053 Start decompression. */
7054 cinfo
.quantize_colors
= 1;
7055 fn_jpeg_start_decompress (&cinfo
);
7056 width
= img
->width
= cinfo
.output_width
;
7057 height
= img
->height
= cinfo
.output_height
;
7059 if (!check_image_size (f
, width
, height
))
7061 image_error ("Invalid image size", Qnil
, Qnil
);
7062 longjmp (mgr
.setjmp_buffer
, 2);
7065 /* Create X image and pixmap. */
7066 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7067 longjmp (mgr
.setjmp_buffer
, 2);
7069 /* Allocate colors. When color quantization is used,
7070 cinfo.actual_number_of_colors has been set with the number of
7071 colors generated, and cinfo.colormap is a two-dimensional array
7072 of color indices in the range 0..cinfo.actual_number_of_colors.
7073 No more than 255 colors will be generated. */
7077 if (cinfo
.out_color_components
> 2)
7078 ir
= 0, ig
= 1, ib
= 2;
7079 else if (cinfo
.out_color_components
> 1)
7080 ir
= 0, ig
= 1, ib
= 0;
7082 ir
= 0, ig
= 0, ib
= 0;
7084 /* Use the color table mechanism because it handles colors that
7085 cannot be allocated nicely. Such colors will be replaced with
7086 a default color, and we don't have to care about which colors
7087 can be freed safely, and which can't. */
7088 init_color_table ();
7089 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
7092 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
7094 /* Multiply RGB values with 255 because X expects RGB values
7095 in the range 0..0xffff. */
7096 int r
= cinfo
.colormap
[ir
][i
] << 8;
7097 int g
= cinfo
.colormap
[ig
][i
] << 8;
7098 int b
= cinfo
.colormap
[ib
][i
] << 8;
7099 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7102 #ifdef COLOR_TABLE_SUPPORT
7103 /* Remember those colors actually allocated. */
7104 img
->colors
= colors_in_color_table (&img
->ncolors
);
7105 free_color_table ();
7106 #endif /* COLOR_TABLE_SUPPORT */
7110 row_stride
= width
* cinfo
.output_components
;
7111 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
7113 for (y
= 0; y
< height
; ++y
)
7115 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
7116 for (x
= 0; x
< cinfo
.output_width
; ++x
)
7117 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
7121 fn_jpeg_finish_decompress (&cinfo
);
7122 fn_jpeg_destroy_decompress (&cinfo
);
7124 fclose ((FILE *) fp
);
7126 /* Maybe fill in the background field while we have ximg handy. */
7127 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7128 /* Casting avoids a GCC warning. */
7129 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7131 /* Put the image into the pixmap. */
7132 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7133 x_destroy_x_image (ximg
);
7138 #else /* HAVE_JPEG */
7147 return image_load_quartz2d (f
, img
, 0);
7149 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7154 #endif /* !HAVE_JPEG */
7158 /***********************************************************************
7160 ***********************************************************************/
7162 #if defined (HAVE_TIFF) || defined (MAC_OS)
7164 static int tiff_image_p
P_ ((Lisp_Object object
));
7165 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7167 /* The symbol `tiff' identifying images of this type. */
7171 /* Indices of image specification fields in tiff_format, below. */
7173 enum tiff_keyword_index
7182 TIFF_HEURISTIC_MASK
,
7188 /* Vector of image_keyword structures describing the format
7189 of valid user-defined image specifications. */
7191 static struct image_keyword tiff_format
[TIFF_LAST
] =
7193 {":type", IMAGE_SYMBOL_VALUE
, 1},
7194 {":data", IMAGE_STRING_VALUE
, 0},
7195 {":file", IMAGE_STRING_VALUE
, 0},
7196 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7197 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7198 {":relief", IMAGE_INTEGER_VALUE
, 0},
7199 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7200 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7201 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7202 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7205 /* Structure describing the image type `tiff'. */
7207 static struct image_type tiff_type
=
7216 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7219 tiff_image_p (object
)
7222 struct image_keyword fmt
[TIFF_LAST
];
7223 bcopy (tiff_format
, fmt
, sizeof fmt
);
7225 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7228 /* Must specify either the :data or :file keyword. */
7229 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7232 #endif /* HAVE_TIFF || MAC_OS */
7240 /* TIFF library details. */
7241 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7242 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7243 DEF_IMGLIB_FN (TIFFOpen
);
7244 DEF_IMGLIB_FN (TIFFClientOpen
);
7245 DEF_IMGLIB_FN (TIFFGetField
);
7246 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7247 DEF_IMGLIB_FN (TIFFClose
);
7250 init_tiff_functions (Lisp_Object libraries
)
7254 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7257 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7258 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7259 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7260 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7261 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7262 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7263 LOAD_IMGLIB_FN (library
, TIFFClose
);
7269 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7270 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7271 #define fn_TIFFOpen TIFFOpen
7272 #define fn_TIFFClientOpen TIFFClientOpen
7273 #define fn_TIFFGetField TIFFGetField
7274 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7275 #define fn_TIFFClose TIFFClose
7277 #endif /* HAVE_NTGUI */
7280 /* Reading from a memory buffer for TIFF images Based on the PNG
7281 memory source, but we have to provide a lot of extra functions.
7284 We really only need to implement read and seek, but I am not
7285 convinced that the TIFF library is smart enough not to destroy
7286 itself if we only hand it the function pointers we need to
7291 unsigned char *bytes
;
7298 tiff_read_from_memory (data
, buf
, size
)
7303 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7305 if (size
> src
->len
- src
->index
)
7307 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7313 tiff_write_from_memory (data
, buf
, size
)
7322 tiff_seek_in_memory (data
, off
, whence
)
7327 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7332 case SEEK_SET
: /* Go from beginning of source. */
7336 case SEEK_END
: /* Go from end of source. */
7337 idx
= src
->len
+ off
;
7340 case SEEK_CUR
: /* Go from current position. */
7341 idx
= src
->index
+ off
;
7344 default: /* Invalid `whence'. */
7348 if (idx
> src
->len
|| idx
< 0)
7356 tiff_close_memory (data
)
7364 tiff_mmap_memory (data
, pbase
, psize
)
7369 /* It is already _IN_ memory. */
7374 tiff_unmap_memory (data
, base
, size
)
7379 /* We don't need to do this. */
7383 tiff_size_of_memory (data
)
7386 return ((tiff_memory_source
*) data
)->len
;
7391 tiff_error_handler (title
, format
, ap
)
7392 const char *title
, *format
;
7398 len
= sprintf (buf
, "TIFF error: %s ", title
);
7399 vsprintf (buf
+ len
, format
, ap
);
7400 add_to_log (buf
, Qnil
, Qnil
);
7405 tiff_warning_handler (title
, format
, ap
)
7406 const char *title
, *format
;
7412 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7413 vsprintf (buf
+ len
, format
, ap
);
7414 add_to_log (buf
, Qnil
, Qnil
);
7418 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7426 Lisp_Object file
, specified_file
;
7427 Lisp_Object specified_data
;
7429 int width
, height
, x
, y
;
7433 struct gcpro gcpro1
;
7434 tiff_memory_source memsrc
;
7436 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7437 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7441 fn_TIFFSetErrorHandler (tiff_error_handler
);
7442 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7444 if (NILP (specified_data
))
7446 /* Read from a file */
7447 file
= x_find_image_file (specified_file
);
7448 if (!STRINGP (file
))
7450 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7455 /* Try to open the image file. Casting return value avoids a
7456 GCC warning on W32. */
7457 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7460 image_error ("Cannot open `%s'", file
, Qnil
);
7467 /* Memory source! */
7468 memsrc
.bytes
= SDATA (specified_data
);
7469 memsrc
.len
= SBYTES (specified_data
);
7472 /* Casting return value avoids a GCC warning on W32. */
7473 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7474 (TIFFReadWriteProc
) tiff_read_from_memory
,
7475 (TIFFReadWriteProc
) tiff_write_from_memory
,
7476 tiff_seek_in_memory
,
7478 tiff_size_of_memory
,
7484 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7490 /* Get width and height of the image, and allocate a raster buffer
7491 of width x height 32-bit values. */
7492 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7493 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7495 if (!check_image_size (f
, width
, height
))
7497 image_error ("Invalid image size", Qnil
, Qnil
);
7502 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7504 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7505 fn_TIFFClose (tiff
);
7508 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7514 /* Create the X image and pixmap. */
7515 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7522 /* Initialize the color table. */
7523 init_color_table ();
7525 /* Process the pixel raster. Origin is in the lower-left corner. */
7526 for (y
= 0; y
< height
; ++y
)
7528 uint32
*row
= buf
+ y
* width
;
7530 for (x
= 0; x
< width
; ++x
)
7532 uint32 abgr
= row
[x
];
7533 int r
= TIFFGetR (abgr
) << 8;
7534 int g
= TIFFGetG (abgr
) << 8;
7535 int b
= TIFFGetB (abgr
) << 8;
7536 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7540 #ifdef COLOR_TABLE_SUPPORT
7541 /* Remember the colors allocated for the image. Free the color table. */
7542 img
->colors
= colors_in_color_table (&img
->ncolors
);
7543 free_color_table ();
7544 #endif /* COLOR_TABLE_SUPPORT */
7547 img
->height
= height
;
7549 /* Maybe fill in the background field while we have ximg handy. */
7550 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7551 /* Casting avoids a GCC warning on W32. */
7552 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7554 /* Put the image into the pixmap, then free the X image and its buffer. */
7555 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7556 x_destroy_x_image (ximg
);
7563 #else /* HAVE_TIFF */
7571 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7575 #endif /* !HAVE_TIFF */
7579 /***********************************************************************
7581 ***********************************************************************/
7583 #if defined (HAVE_GIF) || defined (MAC_OS)
7585 static int gif_image_p
P_ ((Lisp_Object object
));
7586 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7587 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7589 /* The symbol `gif' identifying images of this type. */
7593 /* Indices of image specification fields in gif_format, below. */
7595 enum gif_keyword_index
7611 /* Vector of image_keyword structures describing the format
7612 of valid user-defined image specifications. */
7614 static struct image_keyword gif_format
[GIF_LAST
] =
7616 {":type", IMAGE_SYMBOL_VALUE
, 1},
7617 {":data", IMAGE_STRING_VALUE
, 0},
7618 {":file", IMAGE_STRING_VALUE
, 0},
7619 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7620 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7621 {":relief", IMAGE_INTEGER_VALUE
, 0},
7622 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7623 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7624 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7625 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7626 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7629 /* Structure describing the image type `gif'. */
7631 static struct image_type gif_type
=
7640 /* Free X resources of GIF image IMG which is used on frame F. */
7643 gif_clear_image (f
, img
)
7647 /* IMG->data.ptr_val may contain extension data. */
7648 img
->data
.lisp_val
= Qnil
;
7649 x_clear_image (f
, img
);
7652 /* Return non-zero if OBJECT is a valid GIF image specification. */
7655 gif_image_p (object
)
7658 struct image_keyword fmt
[GIF_LAST
];
7659 bcopy (gif_format
, fmt
, sizeof fmt
);
7661 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7664 /* Must specify either the :data or :file keyword. */
7665 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7668 #endif /* HAVE_GIF || MAC_OS */
7672 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7673 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7674 Undefine before redefining to avoid a preprocessor warning. */
7678 /* avoid conflict with QuickdrawText.h */
7679 #define DrawText gif_DrawText
7680 #include <gif_lib.h>
7683 #else /* HAVE_NTGUI || MAC_OS */
7685 #include <gif_lib.h>
7687 #endif /* HAVE_NTGUI || MAC_OS */
7692 /* GIF library details. */
7693 DEF_IMGLIB_FN (DGifCloseFile
);
7694 DEF_IMGLIB_FN (DGifSlurp
);
7695 DEF_IMGLIB_FN (DGifOpen
);
7696 DEF_IMGLIB_FN (DGifOpenFileName
);
7699 init_gif_functions (Lisp_Object libraries
)
7703 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7706 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7707 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7708 LOAD_IMGLIB_FN (library
, DGifOpen
);
7709 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7715 #define fn_DGifCloseFile DGifCloseFile
7716 #define fn_DGifSlurp DGifSlurp
7717 #define fn_DGifOpen DGifOpen
7718 #define fn_DGifOpenFileName DGifOpenFileName
7720 #endif /* HAVE_NTGUI */
7722 /* Reading a GIF image from memory
7723 Based on the PNG memory stuff to a certain extent. */
7727 unsigned char *bytes
;
7733 /* Make the current memory source available to gif_read_from_memory.
7734 It's done this way because not all versions of libungif support
7735 a UserData field in the GifFileType structure. */
7736 static gif_memory_source
*current_gif_memory_src
;
7739 gif_read_from_memory (file
, buf
, len
)
7744 gif_memory_source
*src
= current_gif_memory_src
;
7746 if (len
> src
->len
- src
->index
)
7749 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7755 /* Load GIF image IMG for use on frame F. Value is non-zero if
7763 Lisp_Object file
, specified_file
;
7764 Lisp_Object specified_data
;
7765 int rc
, width
, height
, x
, y
, i
;
7767 ColorMapObject
*gif_color_map
;
7768 unsigned long pixel_colors
[256];
7770 struct gcpro gcpro1
;
7772 int ino
, image_height
, image_width
;
7773 gif_memory_source memsrc
;
7774 unsigned char *raster
;
7776 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7777 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7781 if (NILP (specified_data
))
7783 file
= x_find_image_file (specified_file
);
7784 if (!STRINGP (file
))
7786 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7791 /* Open the GIF file. Casting return value avoids a GCC warning
7793 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7796 image_error ("Cannot open `%s'", file
, Qnil
);
7803 /* Read from memory! */
7804 current_gif_memory_src
= &memsrc
;
7805 memsrc
.bytes
= SDATA (specified_data
);
7806 memsrc
.len
= SBYTES (specified_data
);
7809 /* Casting return value avoids a GCC warning on W32. */
7810 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
7813 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7819 /* Before reading entire contents, check the declared image size. */
7820 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7822 image_error ("Invalid image size", Qnil
, Qnil
);
7823 fn_DGifCloseFile (gif
);
7828 /* Read entire contents. */
7829 rc
= fn_DGifSlurp (gif
);
7830 if (rc
== GIF_ERROR
)
7832 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7833 fn_DGifCloseFile (gif
);
7838 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7839 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7840 if (ino
>= gif
->ImageCount
)
7842 image_error ("Invalid image number `%s' in image `%s'",
7844 fn_DGifCloseFile (gif
);
7849 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7850 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7851 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7852 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7853 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7854 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7856 width
= img
->width
= max (gif
->SWidth
,
7857 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7858 img
->corners
[RIGHT_CORNER
]));
7859 height
= img
->height
= max (gif
->SHeight
,
7860 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7861 img
->corners
[BOT_CORNER
]));
7863 if (!check_image_size (f
, width
, height
))
7865 image_error ("Invalid image size", Qnil
, Qnil
);
7866 fn_DGifCloseFile (gif
);
7871 /* Create the X image and pixmap. */
7872 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7874 fn_DGifCloseFile (gif
);
7879 /* Allocate colors. */
7880 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7882 gif_color_map
= gif
->SColorMap
;
7883 init_color_table ();
7884 bzero (pixel_colors
, sizeof pixel_colors
);
7886 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7888 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7889 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7890 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7891 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7894 #ifdef COLOR_TABLE_SUPPORT
7895 img
->colors
= colors_in_color_table (&img
->ncolors
);
7896 free_color_table ();
7897 #endif /* COLOR_TABLE_SUPPORT */
7899 /* Clear the part of the screen image that are not covered by
7900 the image from the GIF file. Full animated GIF support
7901 requires more than can be done here (see the gif89 spec,
7902 disposal methods). Let's simply assume that the part
7903 not covered by a sub-image is in the frame's background color. */
7904 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7905 for (x
= 0; x
< width
; ++x
)
7906 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7908 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7909 for (x
= 0; x
< width
; ++x
)
7910 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7912 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7914 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7915 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7916 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7917 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7920 /* Read the GIF image into the X image. We use a local variable
7921 `raster' here because RasterBits below is a char *, and invites
7922 problems with bytes >= 0x80. */
7923 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7925 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7927 static int interlace_start
[] = {0, 4, 2, 1};
7928 static int interlace_increment
[] = {8, 8, 4, 2};
7930 int row
= interlace_start
[0];
7934 for (y
= 0; y
< image_height
; y
++)
7936 if (row
>= image_height
)
7938 row
= interlace_start
[++pass
];
7939 while (row
>= image_height
)
7940 row
= interlace_start
[++pass
];
7943 for (x
= 0; x
< image_width
; x
++)
7945 int i
= raster
[(y
* image_width
) + x
];
7946 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7947 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7950 row
+= interlace_increment
[pass
];
7955 for (y
= 0; y
< image_height
; ++y
)
7956 for (x
= 0; x
< image_width
; ++x
)
7958 int i
= raster
[y
* image_width
+ x
];
7959 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7960 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7964 /* Save GIF image extension data for `image-extension-data'.
7965 Format is (count IMAGES FUNCTION "BYTES" ...). */
7966 img
->data
.lisp_val
= Qnil
;
7967 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7969 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7970 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7971 /* Append (... FUNCTION "BYTES") */
7972 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7973 Fcons (make_number (ext
->Function
),
7974 img
->data
.lisp_val
));
7975 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7977 if (gif
->ImageCount
> 1)
7978 img
->data
.lisp_val
= Fcons (Qcount
,
7979 Fcons (make_number (gif
->ImageCount
),
7980 img
->data
.lisp_val
));
7982 fn_DGifCloseFile (gif
);
7984 /* Maybe fill in the background field while we have ximg handy. */
7985 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7986 /* Casting avoids a GCC warning. */
7987 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7989 /* Put the image into the pixmap, then free the X image and its buffer. */
7990 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7991 x_destroy_x_image (ximg
);
7997 #else /* !HAVE_GIF */
8005 Lisp_Object specified_file
, file
;
8006 Lisp_Object specified_data
;
8008 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
8016 Lisp_Object specified_bg
;
8021 TimeScale time_scale
;
8022 TimeValue time
, duration
;
8027 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
8028 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8030 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8033 if (NILP (specified_data
))
8035 /* Read from a file */
8039 err
= find_image_fsspec (specified_file
, &file
, &fss
);
8043 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
8048 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
8049 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
8053 if (!graphic_p
&& !movie_p
)
8055 if (prefer_graphic_p
)
8056 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
8057 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
8060 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
8061 CloseMovieFile (refnum
);
8064 image_error ("Error reading `%s'", file
, Qnil
);
8070 /* Memory source! */
8072 long file_type_atom
[3];
8074 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
8077 image_error ("Cannot allocate data handle for `%s'",
8082 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
8083 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
8084 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
8085 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
8088 err
= PtrAndHand ("\p", dref
, 1);
8090 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
8093 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
8096 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
8097 &movie_p
, &prefer_graphic_p
, 0);
8101 if (!graphic_p
&& !movie_p
)
8103 if (prefer_graphic_p
)
8107 DisposeHandle (dref
);
8108 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
8112 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
8113 HandleDataHandlerSubType
);
8114 DisposeHandle (dref
);
8119 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
8120 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
8121 track
= GetMovieIndTrack (movie
, 1);
8122 media
= GetTrackMedia (track
);
8123 nsamples
= GetMediaSampleCount (media
);
8124 if (ino
>= nsamples
)
8126 image_error ("Invalid image number `%s' in image `%s'",
8130 time_scale
= GetMediaTimeScale (media
);
8132 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8133 if (!STRINGP (specified_bg
) ||
8134 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
8136 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8137 color
.red
= RED16_FROM_ULONG (color
.pixel
);
8138 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
8139 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
8141 GetMovieBox (movie
, &rect
);
8142 width
= img
->width
= rect
.right
- rect
.left
;
8143 height
= img
->height
= rect
.bottom
- rect
.top
;
8144 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8147 GetGWorld (&old_port
, &old_gdh
);
8148 SetGWorld (ximg
, NULL
);
8149 bg_color
.red
= color
.red
;
8150 bg_color
.green
= color
.green
;
8151 bg_color
.blue
= color
.blue
;
8152 RGBBackColor (&bg_color
);
8153 SetGWorld (old_port
, old_gdh
);
8154 SetMovieActive (movie
, 1);
8155 SetMovieGWorld (movie
, ximg
, NULL
);
8156 SampleNumToMediaTime (media
, ino
+ 1, &time
, &duration
);
8157 SetMovieTimeValue (movie
, time
);
8158 MoviesTask (movie
, 0L);
8159 DisposeTrackMedia (media
);
8160 DisposeMovieTrack (track
);
8161 DisposeMovie (movie
);
8165 /* Save GIF image extension data for `image-extension-data'.
8166 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8168 Lisp_Object gce
= make_uninit_string (4);
8169 int centisec
= ((float)duration
/ time_scale
) * 100.0f
+ 0.5f
;
8171 /* Fill the delay time field. */
8172 SSET (gce
, 1, centisec
& 0xff);
8173 SSET (gce
, 2, (centisec
>> 8) & 0xff);
8174 /* We don't know about other fields. */
8178 img
->data
.lisp_val
= list4 (Qcount
, make_number (nsamples
),
8179 make_number (0xf9), gce
);
8182 /* Maybe fill in the background field while we have ximg handy. */
8183 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
8184 IMAGE_BACKGROUND (img
, f
, ximg
);
8186 /* Put the image into the pixmap. */
8187 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8188 x_destroy_x_image (ximg
);
8192 image_error ("Cannot open `%s'", file
, Qnil
);
8195 DisposeTrackMedia (media
);
8197 DisposeMovieTrack (track
);
8199 DisposeMovie (movie
);
8206 #endif /* HAVE_GIF */
8210 /***********************************************************************
8212 ***********************************************************************/
8214 #if defined (HAVE_RSVG)
8216 /* Function prototypes. */
8218 static int svg_image_p
P_ ((Lisp_Object object
));
8219 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
8221 static int svg_load_image
P_ ((struct frame
*, struct image
*,
8222 unsigned char *, unsigned int));
8224 /* The symbol `svg' identifying images of this type. */
8228 /* Indices of image specification fields in svg_format, below. */
8230 enum svg_keyword_index
8245 /* Vector of image_keyword structures describing the format
8246 of valid user-defined image specifications. */
8248 static struct image_keyword svg_format
[SVG_LAST
] =
8250 {":type", IMAGE_SYMBOL_VALUE
, 1},
8251 {":data", IMAGE_STRING_VALUE
, 0},
8252 {":file", IMAGE_STRING_VALUE
, 0},
8253 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8254 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8255 {":relief", IMAGE_INTEGER_VALUE
, 0},
8256 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8257 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8258 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8259 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8262 /* Structure describing the image type `svg'. Its the same type of
8263 structure defined for all image formats, handled by emacs image
8264 functions. See struct image_type in dispextern.h. */
8266 static struct image_type svg_type
=
8268 /* An identifier showing that this is an image structure for the SVG format. */
8270 /* Handle to a function that can be used to identify a SVG file. */
8272 /* Handle to function used to load a SVG file. */
8274 /* Handle to function to free sresources for SVG. */
8276 /* An internal field to link to the next image type in a list of
8277 image types, will be filled in when registering the format. */
8282 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8283 this by calling parse_image_spec and supplying the keywords that
8284 identify the SVG format. */
8287 svg_image_p (object
)
8290 struct image_keyword fmt
[SVG_LAST
];
8291 bcopy (svg_format
, fmt
, sizeof fmt
);
8293 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
8296 /* Must specify either the :data or :file keyword. */
8297 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
8300 #include <librsvg/rsvg.h>
8304 /* SVG library functions. */
8305 DEF_IMGLIB_FN (rsvg_handle_new
);
8306 DEF_IMGLIB_FN (rsvg_handle_set_size_callback
);
8307 DEF_IMGLIB_FN (rsvg_handle_write
);
8308 DEF_IMGLIB_FN (rsvg_handle_close
);
8309 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
8310 DEF_IMGLIB_FN (rsvg_handle_free
);
8312 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
8313 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
8314 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
8315 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
8316 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
8317 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
8318 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
8319 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
8321 DEF_IMGLIB_FN (g_type_init
);
8322 DEF_IMGLIB_FN (g_object_unref
);
8323 DEF_IMGLIB_FN (g_error_free
);
8325 Lisp_Object Qgdk_pixbuf
, Qglib
;
8328 init_svg_functions (Lisp_Object libraries
)
8330 HMODULE library
, gdklib
, glib
;
8332 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
8333 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
8334 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
8337 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
8338 LOAD_IMGLIB_FN (library
, rsvg_handle_set_size_callback
);
8339 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
8340 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
8341 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
8342 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
8344 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
8345 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
8346 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
8347 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
8348 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
8349 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
8350 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
8351 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
8353 LOAD_IMGLIB_FN (glib
, g_type_init
);
8354 LOAD_IMGLIB_FN (glib
, g_object_unref
);
8355 LOAD_IMGLIB_FN (glib
, g_error_free
);
8360 /* The following aliases for library functions allow dynamic loading
8361 to be used on some platforms. */
8362 #define fn_rsvg_handle_new rsvg_handle_new
8363 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8364 #define fn_rsvg_handle_write rsvg_handle_write
8365 #define fn_rsvg_handle_close rsvg_handle_close
8366 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8367 #define fn_rsvg_handle_free rsvg_handle_free
8369 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8370 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8371 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8372 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8373 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8374 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8375 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8376 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8378 #define fn_g_type_init g_type_init
8379 #define fn_g_object_unref g_object_unref
8380 #define fn_g_error_free g_error_free
8381 #endif /* !HAVE_NTGUI */
8383 /* Load SVG image IMG for use on frame F. Value is non-zero if
8384 successful. this function will go into the svg_type structure, and
8385 the prototype thus needs to be compatible with that structure. */
8393 Lisp_Object file_name
;
8395 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8396 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
8397 if (STRINGP (file_name
))
8400 unsigned char *contents
;
8402 struct gcpro gcpro1
;
8404 file
= x_find_image_file (file_name
);
8406 if (!STRINGP (file
))
8408 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
8413 /* Read the entire file into memory. */
8414 contents
= slurp_file (SDATA (file
), &size
);
8415 if (contents
== NULL
)
8417 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8421 /* If the file was slurped into memory properly, parse it. */
8422 success_p
= svg_load_image (f
, img
, contents
, size
);
8426 /* Else its not a file, its a lisp object. Load the image from a
8427 lisp object rather than a file. */
8432 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8433 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8439 /* svg_load_image is a helper function for svg_load, which does the actual
8440 loading given contents and size, apart from frame and image
8441 structures, passed from svg_load.
8443 Uses librsvg to do most of the image processing.
8445 Returns non-zero when sucessful. */
8447 svg_load_image (f
, img
, contents
, size
)
8448 /* Pointer to emacs frame sturcture. */
8450 /* Pointer to emacs image structure. */
8452 /* String containing the SVG XML data to be parsed. */
8453 unsigned char *contents
;
8454 /* Size of data in bytes. */
8457 RsvgHandle
*rsvg_handle
;
8458 GError
*error
= NULL
;
8462 const guint8
*pixels
;
8465 Lisp_Object specified_bg
;
8470 /* g_type_init is a glib function that must be called prior to using
8471 gnome type library functions. */
8473 /* Make a handle to a new rsvg object. */
8474 rsvg_handle
= fn_rsvg_handle_new ();
8476 /* Parse the contents argument and fill in the rsvg_handle. */
8477 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8481 /* The parsing is complete, rsvg_handle is ready to used, close it
8482 for further writes. */
8483 fn_rsvg_handle_close (rsvg_handle
, &error
);
8486 /* We can now get a valid pixel buffer from the svg file, if all
8488 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8491 /* Extract some meta data from the svg handle. */
8492 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8493 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8494 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8495 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8497 /* Validate the svg meta data. */
8498 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8499 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8500 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8501 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8503 /* Try to create a x pixmap to hold the svg pixmap. */
8504 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8506 fn_g_object_unref (pixbuf
);
8510 init_color_table ();
8512 /* Handle alpha channel by combining the image with a background
8514 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8515 if (STRINGP (specified_bg
)
8516 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8518 background
.red
>>= 8;
8519 background
.green
>>= 8;
8520 background
.blue
>>= 8;
8524 #ifdef HAVE_X_WINDOWS
8525 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8526 x_query_color (f
, &background
);
8528 /* SVG pixmaps specify transparency in the last byte, so right
8529 shift 8 bits to get rid of it, since emacs doesn't support
8531 background
.red
>>= 8;
8532 background
.green
>>= 8;
8533 background
.blue
>>= 8;
8534 #elif defined (MAC_OS)
8535 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8536 background
.red
= RED_FROM_ULONG (background
.pixel
);
8537 background
.green
= GREEN_FROM_ULONG (background
.pixel
);
8538 background
.blue
= BLUE_FROM_ULONG (background
.pixel
);
8539 #elif defined (HAVE_NTGUI)
8540 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8541 #if 0 /* W32 TODO : Colormap support. */
8542 x_query_color (f
, &background
);
8545 /* SVG pixmaps specify transparency in the last byte, so right
8546 shift 8 bits to get rid of it, since emacs doesn't support
8548 background
.red
>>= 8;
8549 background
.green
>>= 8;
8550 background
.blue
>>= 8;
8551 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8556 /* This loop handles opacity values, since Emacs assumes
8557 non-transparent images. Each pixel must be "flattened" by
8558 calculating he resulting color, given the transparency of the
8559 pixel, and the image background color. */
8560 for (y
= 0; y
< height
; ++y
)
8562 for (x
= 0; x
< width
; ++x
)
8572 opacity
= *pixels
++;
8574 red
= ((red
* opacity
)
8575 + (background
.red
* ((1 << 8) - opacity
)));
8576 green
= ((green
* opacity
)
8577 + (background
.green
* ((1 << 8) - opacity
)));
8578 blue
= ((blue
* opacity
)
8579 + (background
.blue
* ((1 << 8) - opacity
)));
8581 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8584 pixels
+= rowstride
- 4 * width
;
8587 #ifdef COLOR_TABLE_SUPPORT
8588 /* Remember colors allocated for this image. */
8589 img
->colors
= colors_in_color_table (&img
->ncolors
);
8590 free_color_table ();
8591 #endif /* COLOR_TABLE_SUPPORT */
8593 fn_g_object_unref (pixbuf
);
8596 img
->height
= height
;
8598 /* Maybe fill in the background field while we have ximg handy.
8599 Casting avoids a GCC warning. */
8600 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8602 /* Put the image into the pixmap, then free the X image and its
8604 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8605 x_destroy_x_image (ximg
);
8610 /* FIXME: Use error->message so the user knows what is the actual
8611 problem with the image. */
8612 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8613 fn_g_error_free (error
);
8617 #endif /* defined (HAVE_RSVG) */
8622 /***********************************************************************
8624 ***********************************************************************/
8626 #ifdef HAVE_X_WINDOWS
8627 #define HAVE_GHOSTSCRIPT 1
8628 #endif /* HAVE_X_WINDOWS */
8630 /* The symbol `postscript' identifying images of this type. */
8632 Lisp_Object Qpostscript
;
8634 #ifdef HAVE_GHOSTSCRIPT
8636 static int gs_image_p
P_ ((Lisp_Object object
));
8637 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8638 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8640 /* Keyword symbols. */
8642 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8644 /* Indices of image specification fields in gs_format, below. */
8646 enum gs_keyword_index
8664 /* Vector of image_keyword structures describing the format
8665 of valid user-defined image specifications. */
8667 static struct image_keyword gs_format
[GS_LAST
] =
8669 {":type", IMAGE_SYMBOL_VALUE
, 1},
8670 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8671 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8672 {":file", IMAGE_STRING_VALUE
, 1},
8673 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8674 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8675 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8676 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8677 {":relief", IMAGE_INTEGER_VALUE
, 0},
8678 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8679 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8680 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8681 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8684 /* Structure describing the image type `ghostscript'. */
8686 static struct image_type gs_type
=
8696 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8699 gs_clear_image (f
, img
)
8703 /* IMG->data.ptr_val may contain a recorded colormap. */
8704 xfree (img
->data
.ptr_val
);
8705 x_clear_image (f
, img
);
8709 /* Return non-zero if OBJECT is a valid Ghostscript image
8716 struct image_keyword fmt
[GS_LAST
];
8720 bcopy (gs_format
, fmt
, sizeof fmt
);
8722 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8725 /* Bounding box must be a list or vector containing 4 integers. */
8726 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8729 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8730 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8735 else if (VECTORP (tem
))
8737 if (XVECTOR (tem
)->size
!= 4)
8739 for (i
= 0; i
< 4; ++i
)
8740 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8750 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8759 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8760 struct gcpro gcpro1
, gcpro2
;
8762 double in_width
, in_height
;
8763 Lisp_Object pixel_colors
= Qnil
;
8765 /* Compute pixel size of pixmap needed from the given size in the
8766 image specification. Sizes in the specification are in pt. 1 pt
8767 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8769 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8770 in_width
= XFASTINT (pt_width
) / 72.0;
8771 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8772 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8773 in_height
= XFASTINT (pt_height
) / 72.0;
8774 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8776 if (!check_image_size (f
, img
->width
, img
->height
))
8778 image_error ("Invalid image size", Qnil
, Qnil
);
8782 /* Create the pixmap. */
8783 xassert (img
->pixmap
== NO_PIXMAP
);
8785 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8787 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8788 img
->width
, img
->height
,
8789 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8794 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8798 /* Call the loader to fill the pixmap. It returns a process object
8799 if successful. We do not record_unwind_protect here because
8800 other places in redisplay like calling window scroll functions
8801 don't either. Let the Lisp loader use `unwind-protect' instead. */
8802 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8804 sprintf (buffer
, "%lu %lu",
8805 (unsigned long) FRAME_X_WINDOW (f
),
8806 (unsigned long) img
->pixmap
);
8807 window_and_pixmap_id
= build_string (buffer
);
8809 sprintf (buffer
, "%lu %lu",
8810 FRAME_FOREGROUND_PIXEL (f
),
8811 FRAME_BACKGROUND_PIXEL (f
));
8812 pixel_colors
= build_string (buffer
);
8814 XSETFRAME (frame
, f
);
8815 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8817 loader
= intern ("gs-load-image");
8819 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8820 make_number (img
->width
),
8821 make_number (img
->height
),
8822 window_and_pixmap_id
,
8825 return PROCESSP (img
->data
.lisp_val
);
8829 /* Kill the Ghostscript process that was started to fill PIXMAP on
8830 frame F. Called from XTread_socket when receiving an event
8831 telling Emacs that Ghostscript has finished drawing. */
8834 x_kill_gs_process (pixmap
, f
)
8838 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8842 /* Find the image containing PIXMAP. */
8843 for (i
= 0; i
< c
->used
; ++i
)
8844 if (c
->images
[i
]->pixmap
== pixmap
)
8847 /* Should someone in between have cleared the image cache, for
8848 instance, give up. */
8852 /* Kill the GS process. We should have found PIXMAP in the image
8853 cache and its image should contain a process object. */
8855 xassert (PROCESSP (img
->data
.lisp_val
));
8856 Fkill_process (img
->data
.lisp_val
, Qnil
);
8857 img
->data
.lisp_val
= Qnil
;
8859 #if defined (HAVE_X_WINDOWS)
8861 /* On displays with a mutable colormap, figure out the colors
8862 allocated for the image by looking at the pixels of an XImage for
8864 class = FRAME_X_VISUAL (f
)->class;
8865 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8871 /* Try to get an XImage for img->pixmep. */
8872 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8873 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8878 /* Initialize the color table. */
8879 init_color_table ();
8881 /* For each pixel of the image, look its color up in the
8882 color table. After having done so, the color table will
8883 contain an entry for each color used by the image. */
8884 for (y
= 0; y
< img
->height
; ++y
)
8885 for (x
= 0; x
< img
->width
; ++x
)
8887 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8888 lookup_pixel_color (f
, pixel
);
8891 /* Record colors in the image. Free color table and XImage. */
8892 #ifdef COLOR_TABLE_SUPPORT
8893 img
->colors
= colors_in_color_table (&img
->ncolors
);
8894 free_color_table ();
8896 XDestroyImage (ximg
);
8898 #if 0 /* This doesn't seem to be the case. If we free the colors
8899 here, we get a BadAccess later in x_clear_image when
8900 freeing the colors. */
8901 /* We have allocated colors once, but Ghostscript has also
8902 allocated colors on behalf of us. So, to get the
8903 reference counts right, free them once. */
8905 x_free_colors (f
, img
->colors
, img
->ncolors
);
8909 image_error ("Cannot get X image of `%s'; colors will not be freed",
8914 #endif /* HAVE_X_WINDOWS */
8916 /* Now that we have the pixmap, compute mask and transform the
8917 image if requested. */
8919 postprocess_image (f
, img
);
8923 #endif /* HAVE_GHOSTSCRIPT */
8926 /***********************************************************************
8928 ***********************************************************************/
8932 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8933 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8937 return valid_image_p (spec
) ? Qt
: Qnil
;
8941 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8947 if (valid_image_p (spec
))
8948 id
= lookup_image (SELECTED_FRAME (), spec
);
8951 return make_number (id
);
8954 #endif /* GLYPH_DEBUG != 0 */
8957 /***********************************************************************
8959 ***********************************************************************/
8962 /* Image types that rely on external libraries are loaded dynamically
8963 if the library is available. */
8964 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8965 define_image_type (image_type, init_lib_fn (libraries))
8967 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8968 define_image_type (image_type, 1)
8969 #endif /* HAVE_NTGUI */
8971 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8972 doc
: /* Initialize image library implementing image type TYPE.
8973 Return non-nil if TYPE is a supported image type.
8975 Image types pbm and xbm are prebuilt; other types are loaded here.
8976 Libraries to load are specified in alist LIBRARIES (usually, the value
8977 of `image-library-alist', which see). */)
8979 Lisp_Object type
, libraries
;
8983 /* Don't try to reload the library. */
8984 tested
= Fassq (type
, Vimage_type_cache
);
8986 return XCDR (tested
);
8988 #if defined (HAVE_XPM) || defined (MAC_OS)
8989 if (EQ (type
, Qxpm
))
8990 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8993 #if defined (HAVE_JPEG) || defined (MAC_OS)
8994 if (EQ (type
, Qjpeg
))
8995 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8998 #if defined (HAVE_TIFF) || defined (MAC_OS)
8999 if (EQ (type
, Qtiff
))
9000 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
9003 #if defined (HAVE_GIF) || defined (MAC_OS)
9004 if (EQ (type
, Qgif
))
9005 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
9008 #if defined (HAVE_PNG) || defined (MAC_OS)
9009 if (EQ (type
, Qpng
))
9010 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
9013 #if defined (HAVE_RSVG)
9014 if (EQ (type
, Qsvg
))
9015 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
9018 #ifdef HAVE_GHOSTSCRIPT
9019 if (EQ (type
, Qpostscript
))
9020 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
9023 /* If the type is not recognized, avoid testing it ever again. */
9024 CACHE_IMAGE_TYPE (type
, Qnil
);
9031 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
9033 /* Initialize this only once, since that's what we do with Vimage_types
9034 and they are supposed to be in sync. Initializing here gives correct
9035 operation on GNU/Linux of calling dump-emacs after loading some images. */
9038 /* Must be defined now becase we're going to update it below, while
9039 defining the supported image types. */
9040 DEFVAR_LISP ("image-types", &Vimage_types
,
9041 doc
: /* List of potentially supported image types.
9042 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
9043 To check whether it is really supported, use `image-type-available-p'. */);
9044 Vimage_types
= Qnil
;
9046 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
9047 doc
: /* Alist of image types vs external libraries needed to display them.
9049 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9050 representing a supported image type, and the rest are strings giving
9051 alternate filenames for the corresponding external libraries.
9053 Emacs tries to load the libraries in the order they appear on the
9054 list; if none is loaded, the running session of Emacs won't
9055 support the image type. Types 'pbm and 'xbm don't need to be
9056 listed; they are always supported. */);
9057 Vimage_library_alist
= Qnil
;
9058 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
9060 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
9061 doc
: /* Maximum size of images.
9062 Emacs will not load an image into memory if its pixel width or
9063 pixel height exceeds this limit.
9065 If the value is an integer, it directly specifies the maximum
9066 image height and width, measured in pixels. If it is a floating
9067 point number, it specifies the maximum image height and width
9068 as a ratio to the frame height and width. If the value is
9069 non-numeric, there is no explicit limit on the size of images. */);
9070 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
9072 Vimage_type_cache
= Qnil
;
9073 staticpro (&Vimage_type_cache
);
9075 Qpbm
= intern ("pbm");
9077 ADD_IMAGE_TYPE (Qpbm
);
9079 Qxbm
= intern ("xbm");
9081 ADD_IMAGE_TYPE (Qxbm
);
9083 define_image_type (&xbm_type
, 1);
9084 define_image_type (&pbm_type
, 1);
9086 QCascent
= intern (":ascent");
9087 staticpro (&QCascent
);
9088 QCmargin
= intern (":margin");
9089 staticpro (&QCmargin
);
9090 QCrelief
= intern (":relief");
9091 staticpro (&QCrelief
);
9092 QCconversion
= intern (":conversion");
9093 staticpro (&QCconversion
);
9094 QCcolor_symbols
= intern (":color-symbols");
9095 staticpro (&QCcolor_symbols
);
9096 QCheuristic_mask
= intern (":heuristic-mask");
9097 staticpro (&QCheuristic_mask
);
9098 QCindex
= intern (":index");
9099 staticpro (&QCindex
);
9100 QCmatrix
= intern (":matrix");
9101 staticpro (&QCmatrix
);
9102 QCcolor_adjustment
= intern (":color-adjustment");
9103 staticpro (&QCcolor_adjustment
);
9104 QCmask
= intern (":mask");
9105 staticpro (&QCmask
);
9107 Qlaplace
= intern ("laplace");
9108 staticpro (&Qlaplace
);
9109 Qemboss
= intern ("emboss");
9110 staticpro (&Qemboss
);
9111 Qedge_detection
= intern ("edge-detection");
9112 staticpro (&Qedge_detection
);
9113 Qheuristic
= intern ("heuristic");
9114 staticpro (&Qheuristic
);
9116 Qpostscript
= intern ("postscript");
9117 staticpro (&Qpostscript
);
9118 #ifdef HAVE_GHOSTSCRIPT
9119 ADD_IMAGE_TYPE (Qpostscript
);
9120 QCloader
= intern (":loader");
9121 staticpro (&QCloader
);
9122 QCbounding_box
= intern (":bounding-box");
9123 staticpro (&QCbounding_box
);
9124 QCpt_width
= intern (":pt-width");
9125 staticpro (&QCpt_width
);
9126 QCpt_height
= intern (":pt-height");
9127 staticpro (&QCpt_height
);
9128 #endif /* HAVE_GHOSTSCRIPT */
9130 #if defined (HAVE_XPM) || defined (MAC_OS)
9131 Qxpm
= intern ("xpm");
9133 ADD_IMAGE_TYPE (Qxpm
);
9136 #if defined (HAVE_JPEG) || defined (MAC_OS)
9137 Qjpeg
= intern ("jpeg");
9139 ADD_IMAGE_TYPE (Qjpeg
);
9142 #if defined (HAVE_TIFF) || defined (MAC_OS)
9143 Qtiff
= intern ("tiff");
9145 ADD_IMAGE_TYPE (Qtiff
);
9148 #if defined (HAVE_GIF) || defined (MAC_OS)
9149 Qgif
= intern ("gif");
9151 ADD_IMAGE_TYPE (Qgif
);
9154 #if defined (HAVE_PNG) || defined (MAC_OS)
9155 Qpng
= intern ("png");
9157 ADD_IMAGE_TYPE (Qpng
);
9160 #if defined (HAVE_RSVG)
9161 Qsvg
= intern ("svg");
9163 ADD_IMAGE_TYPE (Qsvg
);
9165 Qgdk_pixbuf
= intern ("gdk-pixbuf");
9166 staticpro (&Qgdk_pixbuf
);
9167 Qglib
= intern ("glib");
9169 #endif /* HAVE_NTGUI */
9170 #endif /* HAVE_RSVG */
9172 defsubr (&Sinit_image_library
);
9173 defsubr (&Sclear_image_cache
);
9174 defsubr (&Simage_refresh
);
9175 defsubr (&Simage_size
);
9176 defsubr (&Simage_mask_p
);
9177 defsubr (&Simage_extension_data
);
9181 defsubr (&Slookup_image
);
9184 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
9185 doc
: /* Non-nil means always draw a cross over disabled images.
9186 Disabled images are those having a `:conversion disabled' property.
9187 A cross is always drawn on black & white displays. */);
9188 cross_disabled_images
= 0;
9190 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
9191 doc
: /* List of directories to search for window system bitmap files. */);
9192 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
9194 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
9195 doc
: /* Time after which cached images are removed from the cache.
9196 When an image has not been displayed this many seconds, remove it
9197 from the image cache. Value must be an integer or nil with nil
9198 meaning don't clear the cache. */);
9199 Vimage_cache_eviction_delay
= make_number (30 * 60);
9205 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
9206 init_image_func_pointer ();
9210 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9211 (do not change this comment) */