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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
38 #include "dispextern.h"
39 #include "blockinput.h"
48 #include <sys/types.h>
51 #define COLOR_TABLE_SUPPORT 1
53 typedef struct x_bitmap_record Bitmap_Record
;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
57 #define RGB_PIXEL_COLOR unsigned long
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
70 typedef struct w32_bitmap_record Bitmap_Record
;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
82 #endif /* HAVE_NTGUI */
90 #include <sys/param.h>
92 #if TARGET_API_MAC_CARBON
94 #include <QuickTime/QuickTime.h>
95 #else /* not MAC_OSX */
96 #include <QuickTime.h>
97 #endif /* not MAC_OSX */
98 #else /* not TARGET_API_MAC_CARBON */
101 #include <TextUtils.h>
102 #include <ImageCompression.h>
103 #include <QuickTimeComponents.h>
104 #endif /* not TARGET_API_MAC_CARBON */
106 /* MAC_TODO : Color tables on Mac. */
107 #undef COLOR_TABLE_SUPPORT
109 #define ZPixmap 0 /* arbitrary */
110 typedef struct mac_bitmap_record Bitmap_Record
;
112 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
115 #define RGB_PIXEL_COLOR unsigned long
117 /* A black pixel in a mask bitmap/pixmap means ``draw a source
118 pixel''. A white pixel means ``retain the current pixel''. */
119 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
120 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
122 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
123 #define x_defined_color mac_defined_color
124 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
125 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
126 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
131 /* Search path for bitmap files. */
133 Lisp_Object Vx_bitmap_file_path
;
136 static void x_disable_image
P_ ((struct frame
*, struct image
*));
137 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
140 static void init_color_table
P_ ((void));
141 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
142 #ifdef COLOR_TABLE_SUPPORT
143 static void free_color_table
P_ ((void));
144 static unsigned long *colors_in_color_table
P_ ((int *n
));
145 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
148 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
149 id, which is just an int that this section returns. Bitmaps are
150 reference counted so they can be shared among frames.
152 Bitmap indices are guaranteed to be > 0, so a negative number can
153 be used to indicate no bitmap.
155 If you use x_create_bitmap_from_data, then you must keep track of
156 the bitmaps yourself. That is, creating a bitmap from the same
157 data more than once will not be caught. */
162 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
163 Display
*display
; /* not used */
165 int x
, y
; /* not used */
166 unsigned int width
, height
; /* not used */
167 unsigned long plane_mask
; /* not used */
168 int format
; /* not used */
171 xassert (x
== 0 && y
== 0);
174 SetRect (&ri
, 0, 0, width
, height
);
175 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
177 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
180 LockPixels (GetGWorldPixMap (pixmap
));
186 XPutPixel (ximage
, x
, y
, pixel
)
191 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
192 short depth
= GetPixDepth (pixmap
);
194 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
197 char *base_addr
= GetPixBaseAddr (pixmap
);
198 short row_bytes
= GetPixRowBytes (pixmap
);
200 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
206 char *base_addr
= GetPixBaseAddr (pixmap
);
207 short row_bytes
= GetPixRowBytes (pixmap
);
209 if (pixel
== PIX_MASK_DRAW
)
210 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
212 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
220 GetGWorld (&old_port
, &old_gdh
);
221 SetGWorld (ximage
, NULL
);
223 color
.red
= RED16_FROM_ULONG (pixel
);
224 color
.green
= GREEN16_FROM_ULONG (pixel
);
225 color
.blue
= BLUE16_FROM_ULONG (pixel
);
227 SetCPixel (x
, y
, &color
);
229 SetGWorld (old_port
, old_gdh
);
234 XGetPixel (ximage
, x
, y
)
238 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
239 short depth
= GetPixDepth (pixmap
);
241 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
244 char *base_addr
= GetPixBaseAddr (pixmap
);
245 short row_bytes
= GetPixRowBytes (pixmap
);
247 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
253 char *base_addr
= GetPixBaseAddr (pixmap
);
254 short row_bytes
= GetPixRowBytes (pixmap
);
256 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
257 return PIX_MASK_DRAW
;
259 return PIX_MASK_RETAIN
;
267 GetGWorld (&old_port
, &old_gdh
);
268 SetGWorld (ximage
, NULL
);
270 GetCPixel (x
, y
, &color
);
272 SetGWorld (old_port
, old_gdh
);
273 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
281 UnlockPixels (GetGWorldPixMap (ximg
));
286 mac_create_cg_image_from_image (f
, img
)
291 CGImageRef result
= NULL
;
298 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
299 img
->width
, img
->height
, 1);
306 GetGWorld (&old_port
, &old_gdh
);
307 SetGWorld (mask
, NULL
);
308 BackColor (blackColor
); /* Don't mask. */
309 SetRect (&r
, 0, 0, img
->width
, img
->height
);
311 SetGWorld (old_port
, old_gdh
);
316 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
317 GetGWorldPixMap (mask
), &result
);
318 if (mask
!= img
->mask
)
319 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
325 #endif /* USE_CG_DRAWING */
329 /* Functions to access the contents of a bitmap, given an id. */
332 x_bitmap_height (f
, id
)
336 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
340 x_bitmap_width (f
, id
)
344 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
347 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
349 x_bitmap_pixmap (f
, id
)
353 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
357 #ifdef HAVE_X_WINDOWS
359 x_bitmap_mask (f
, id
)
363 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
367 /* Allocate a new bitmap record. Returns index of new record. */
370 x_allocate_bitmap_record (f
)
373 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
376 if (dpyinfo
->bitmaps
== NULL
)
378 dpyinfo
->bitmaps_size
= 10;
380 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
381 dpyinfo
->bitmaps_last
= 1;
385 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
386 return ++dpyinfo
->bitmaps_last
;
388 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
389 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
392 dpyinfo
->bitmaps_size
*= 2;
394 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
395 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
396 return ++dpyinfo
->bitmaps_last
;
399 /* Add one reference to the reference count of the bitmap with id ID. */
402 x_reference_bitmap (f
, id
)
406 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
409 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
412 x_create_bitmap_from_data (f
, bits
, width
, height
)
415 unsigned int width
, height
;
417 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
420 #ifdef HAVE_X_WINDOWS
422 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
423 bits
, width
, height
);
426 #endif /* HAVE_X_WINDOWS */
430 bitmap
= CreateBitmap (width
, height
,
431 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
432 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
436 #endif /* HAVE_NTGUI */
439 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
444 id
= x_allocate_bitmap_record (f
);
446 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
447 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
450 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
451 dpyinfo
->bitmaps
[id
- 1].height
= height
;
452 dpyinfo
->bitmaps
[id
- 1].width
= width
;
453 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
455 #ifdef HAVE_X_WINDOWS
456 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
457 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
458 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
459 #endif /* HAVE_X_WINDOWS */
462 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
463 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
464 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
465 #endif /* HAVE_NTGUI */
470 /* Create bitmap from file FILE for frame F. */
473 x_create_bitmap_from_file (f
, file
)
478 return -1; /* MAC_TODO : bitmap support */
482 return -1; /* W32_TODO : bitmap support */
483 #endif /* HAVE_NTGUI */
485 #ifdef HAVE_X_WINDOWS
486 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
487 unsigned int width
, height
;
489 int xhot
, yhot
, result
, id
;
494 /* Look for an existing bitmap with the same name. */
495 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
497 if (dpyinfo
->bitmaps
[id
].refcount
498 && dpyinfo
->bitmaps
[id
].file
499 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
501 ++dpyinfo
->bitmaps
[id
].refcount
;
506 /* Search bitmap-file-path for the file, if appropriate. */
507 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
512 filename
= (char *) SDATA (found
);
514 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
515 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
516 if (result
!= BitmapSuccess
)
519 id
= x_allocate_bitmap_record (f
);
520 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
521 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
522 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
523 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
524 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
525 dpyinfo
->bitmaps
[id
- 1].height
= height
;
526 dpyinfo
->bitmaps
[id
- 1].width
= width
;
527 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
530 #endif /* HAVE_X_WINDOWS */
536 Free_Bitmap_Record (dpyinfo
, bm
)
537 Display_Info
*dpyinfo
;
540 #ifdef HAVE_X_WINDOWS
541 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
543 XFreePixmap (dpyinfo
->display
, bm
->mask
);
544 #endif /* HAVE_X_WINDOWS */
547 DeleteObject (bm
->pixmap
);
548 #endif /* HAVE_NTGUI */
551 xfree (bm
->bitmap_data
); /* Added ++kfs */
552 bm
->bitmap_data
= NULL
;
562 /* Remove reference to bitmap with id number ID. */
565 x_destroy_bitmap (f
, id
)
569 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
573 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
575 if (--bm
->refcount
== 0)
578 Free_Bitmap_Record (dpyinfo
, bm
);
584 /* Free all the bitmaps for the display specified by DPYINFO. */
587 x_destroy_all_bitmaps (dpyinfo
)
588 Display_Info
*dpyinfo
;
591 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
593 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
594 if (bm
->refcount
> 0)
595 Free_Bitmap_Record (dpyinfo
, bm
);
597 dpyinfo
->bitmaps_last
= 0;
601 #ifdef HAVE_X_WINDOWS
603 /* Useful functions defined in the section
604 `Image type independent image structures' below. */
606 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
607 unsigned long height
));
609 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
610 int depth
, XImagePtr
*ximg
,
613 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
616 /* Create a mask of a bitmap. Note is this not a perfect mask.
617 It's nicer with some borders in this context */
620 x_create_bitmap_mask (f
, id
)
625 XImagePtr ximg
, mask_img
;
626 unsigned long width
, height
;
629 unsigned long x
, y
, xp
, xm
, yp
, ym
;
632 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
637 pixmap
= x_bitmap_pixmap (f
, id
);
638 width
= x_bitmap_width (f
, id
);
639 height
= x_bitmap_height (f
, id
);
642 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
651 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
656 XDestroyImage (ximg
);
660 bg
= four_corners_best (ximg
, width
, height
);
662 for (y
= 0; y
< ximg
->height
; ++y
)
664 for (x
= 0; x
< ximg
->width
; ++x
)
666 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
667 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
668 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
669 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
670 if (XGetPixel (ximg
, x
, y
) == bg
671 && XGetPixel (ximg
, x
, yp
) == bg
672 && XGetPixel (ximg
, x
, ym
) == bg
673 && XGetPixel (ximg
, xp
, y
) == bg
674 && XGetPixel (ximg
, xp
, yp
) == bg
675 && XGetPixel (ximg
, xp
, ym
) == bg
676 && XGetPixel (ximg
, xm
, y
) == bg
677 && XGetPixel (ximg
, xm
, yp
) == bg
678 && XGetPixel (ximg
, xm
, ym
) == bg
)
679 XPutPixel (mask_img
, x
, y
, 0);
681 XPutPixel (mask_img
, x
, y
, 1);
685 xassert (interrupt_input_blocked
);
686 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
687 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
689 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
691 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
692 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
694 XDestroyImage (ximg
);
695 x_destroy_x_image (mask_img
);
700 #endif /* HAVE_X_WINDOWS */
703 /***********************************************************************
705 ***********************************************************************/
707 /* Value is the number of elements of vector VECTOR. */
709 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
711 /* List of supported image types. Use define_image_type to add new
712 types. Use lookup_image_type to find a type for a given symbol. */
714 static struct image_type
*image_types
;
716 /* A list of symbols, one for each supported image type. */
718 Lisp_Object Vimage_types
;
720 /* An alist of image types and libraries that implement the type. */
722 Lisp_Object Vimage_library_alist
;
724 /* Cache for delayed-loading image types. */
726 static Lisp_Object Vimage_type_cache
;
728 /* The symbol `xbm' which is used as the type symbol for XBM images. */
734 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
735 extern Lisp_Object QCdata
, QCtype
;
736 extern Lisp_Object Qcenter
;
737 Lisp_Object QCascent
, QCmargin
, QCrelief
;
738 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
739 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
743 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
745 /* Time in seconds after which images should be removed from the cache
748 Lisp_Object Vimage_cache_eviction_delay
;
750 /* Function prototypes. */
752 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
753 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
754 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
755 static void x_laplace
P_ ((struct frame
*, struct image
*));
756 static void x_emboss
P_ ((struct frame
*, struct image
*));
757 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
760 #define CACHE_IMAGE_TYPE(type, status) \
761 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
763 #define ADD_IMAGE_TYPE(type) \
764 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
766 /* Define a new image type from TYPE. This adds a copy of TYPE to
767 image_types and caches the loading status of TYPE. */
770 define_image_type (type
, loaded
)
771 struct image_type
*type
;
780 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
781 The initialized data segment is read-only. */
782 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
783 bcopy (type
, p
, sizeof *p
);
784 p
->next
= image_types
;
789 CACHE_IMAGE_TYPE (*type
->type
, success
);
794 /* Look up image type SYMBOL, and return a pointer to its image_type
795 structure. Value is null if SYMBOL is not a known image type. */
797 static INLINE
struct image_type
*
798 lookup_image_type (symbol
)
801 struct image_type
*type
;
803 /* We must initialize the image-type if it hasn't been already. */
804 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
805 return 0; /* unimplemented */
807 for (type
= image_types
; type
; type
= type
->next
)
808 if (EQ (symbol
, *type
->type
))
815 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
816 valid image specification is a list whose car is the symbol
817 `image', and whose rest is a property list. The property list must
818 contain a value for key `:type'. That value must be the name of a
819 supported image type. The rest of the property list depends on the
823 valid_image_p (object
)
832 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
833 if (EQ (XCAR (tem
), QCtype
))
836 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
838 struct image_type
*type
;
839 type
= lookup_image_type (XCAR (tem
));
841 valid_p
= type
->valid_p (object
);
852 /* Log error message with format string FORMAT and argument ARG.
853 Signaling an error, e.g. when an image cannot be loaded, is not a
854 good idea because this would interrupt redisplay, and the error
855 message display would lead to another redisplay. This function
856 therefore simply displays a message. */
859 image_error (format
, arg1
, arg2
)
861 Lisp_Object arg1
, arg2
;
863 add_to_log (format
, arg1
, arg2
);
868 /***********************************************************************
870 ***********************************************************************/
872 enum image_value_type
874 IMAGE_DONT_CHECK_VALUE_TYPE
,
876 IMAGE_STRING_OR_NIL_VALUE
,
878 IMAGE_POSITIVE_INTEGER_VALUE
,
879 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
880 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
883 IMAGE_FUNCTION_VALUE
,
888 /* Structure used when parsing image specifications. */
892 /* Name of keyword. */
895 /* The type of value allowed. */
896 enum image_value_type type
;
898 /* Non-zero means key must be present. */
901 /* Used to recognize duplicate keywords in a property list. */
904 /* The value that was found. */
909 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
911 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
914 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
915 has the format (image KEYWORD VALUE ...). One of the keyword/
916 value pairs must be `:type TYPE'. KEYWORDS is a vector of
917 image_keywords structures of size NKEYWORDS describing other
918 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
921 parse_image_spec (spec
, keywords
, nkeywords
, type
)
923 struct image_keyword
*keywords
;
934 while (CONSP (plist
))
936 Lisp_Object key
, value
;
938 /* First element of a pair must be a symbol. */
940 plist
= XCDR (plist
);
944 /* There must follow a value. */
947 value
= XCAR (plist
);
948 plist
= XCDR (plist
);
950 /* Find key in KEYWORDS. Error if not found. */
951 for (i
= 0; i
< nkeywords
; ++i
)
952 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
958 /* Record that we recognized the keyword. If a keywords
959 was found more than once, it's an error. */
960 keywords
[i
].value
= value
;
963 if (keywords
[i
].count
> 1)
966 /* Check type of value against allowed type. */
967 switch (keywords
[i
].type
)
969 case IMAGE_STRING_VALUE
:
970 if (!STRINGP (value
))
974 case IMAGE_STRING_OR_NIL_VALUE
:
975 if (!STRINGP (value
) && !NILP (value
))
979 case IMAGE_SYMBOL_VALUE
:
980 if (!SYMBOLP (value
))
984 case IMAGE_POSITIVE_INTEGER_VALUE
:
985 if (!INTEGERP (value
) || XINT (value
) <= 0)
989 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
990 if (INTEGERP (value
) && XINT (value
) >= 0)
993 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
994 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
998 case IMAGE_ASCENT_VALUE
:
999 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1001 else if (INTEGERP (value
)
1002 && XINT (value
) >= 0
1003 && XINT (value
) <= 100)
1007 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1008 if (!INTEGERP (value
) || XINT (value
) < 0)
1012 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1015 case IMAGE_FUNCTION_VALUE
:
1016 value
= indirect_function (value
);
1018 || COMPILEDP (value
)
1019 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1023 case IMAGE_NUMBER_VALUE
:
1024 if (!INTEGERP (value
) && !FLOATP (value
))
1028 case IMAGE_INTEGER_VALUE
:
1029 if (!INTEGERP (value
))
1033 case IMAGE_BOOL_VALUE
:
1034 if (!NILP (value
) && !EQ (value
, Qt
))
1043 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1047 /* Check that all mandatory fields are present. */
1048 for (i
= 0; i
< nkeywords
; ++i
)
1049 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1052 return NILP (plist
);
1056 /* Return the value of KEY in image specification SPEC. Value is nil
1057 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1058 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1061 image_spec_value (spec
, key
, found
)
1062 Lisp_Object spec
, key
;
1067 xassert (valid_image_p (spec
));
1069 for (tail
= XCDR (spec
);
1070 CONSP (tail
) && CONSP (XCDR (tail
));
1071 tail
= XCDR (XCDR (tail
)))
1073 if (EQ (XCAR (tail
), key
))
1077 return XCAR (XCDR (tail
));
1087 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1088 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1089 PIXELS non-nil means return the size in pixels, otherwise return the
1090 size in canonical character units.
1091 FRAME is the frame on which the image will be displayed. FRAME nil
1092 or omitted means use the selected frame. */)
1093 (spec
, pixels
, frame
)
1094 Lisp_Object spec
, pixels
, frame
;
1099 if (valid_image_p (spec
))
1101 struct frame
*f
= check_x_frame (frame
);
1102 int id
= lookup_image (f
, spec
);
1103 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1104 int width
= img
->width
+ 2 * img
->hmargin
;
1105 int height
= img
->height
+ 2 * img
->vmargin
;
1108 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1109 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1111 size
= Fcons (make_number (width
), make_number (height
));
1114 error ("Invalid image specification");
1120 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1121 doc
: /* Return t if image SPEC has a mask bitmap.
1122 FRAME is the frame on which the image will be displayed. FRAME nil
1123 or omitted means use the selected frame. */)
1125 Lisp_Object spec
, frame
;
1130 if (valid_image_p (spec
))
1132 struct frame
*f
= check_x_frame (frame
);
1133 int id
= lookup_image (f
, spec
);
1134 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1139 error ("Invalid image specification");
1145 /***********************************************************************
1146 Image type independent image structures
1147 ***********************************************************************/
1149 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1150 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1151 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1153 #define MAX_IMAGE_SIZE 6.0
1154 Lisp_Object Vmax_image_size
;
1156 /* Allocate and return a new image structure for image specification
1157 SPEC. SPEC has a hash value of HASH. */
1159 static struct image
*
1160 make_image (spec
, hash
)
1164 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1166 xassert (valid_image_p (spec
));
1167 bzero (img
, sizeof *img
);
1168 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1169 xassert (img
->type
!= NULL
);
1171 img
->data
.lisp_val
= Qnil
;
1172 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1178 /* Free image IMG which was used on frame F, including its resources. */
1187 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1189 /* Remove IMG from the hash table of its cache. */
1191 img
->prev
->next
= img
->next
;
1193 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1196 img
->next
->prev
= img
->prev
;
1198 c
->images
[img
->id
] = NULL
;
1200 /* Free resources, then free IMG. */
1201 img
->type
->free (f
, img
);
1206 /* Return 1 if the given widths and heights are valid for display;
1207 otherwise, return 0. */
1210 check_image_size (f
, width
, height
)
1217 if (width
<= 0 || height
<= 0)
1220 if (INTEGERP (Vmax_image_size
))
1221 w
= h
= XINT (Vmax_image_size
);
1222 else if (FLOATP (Vmax_image_size
))
1226 w
= FRAME_PIXEL_WIDTH (f
);
1227 h
= FRAME_PIXEL_HEIGHT (f
);
1230 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1231 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1232 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1237 return (width
<= w
&& height
<= h
);
1240 /* Prepare image IMG for display on frame F. Must be called before
1241 drawing an image. */
1244 prepare_image_for_display (f
, img
)
1250 /* We're about to display IMG, so set its timestamp to `now'. */
1252 img
->timestamp
= EMACS_SECS (t
);
1254 /* If IMG doesn't have a pixmap yet, load it now, using the image
1255 type dependent loader function. */
1256 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1257 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1259 #if defined (MAC_OS) && USE_CG_DRAWING
1260 if (!img
->load_failed_p
&& img
->data
.ptr_val
== NULL
)
1262 img
->data
.ptr_val
= mac_create_cg_image_from_image (f
, img
);
1263 if (img
->data
.ptr_val
== NULL
)
1265 img
->load_failed_p
= 1;
1266 img
->type
->free (f
, img
);
1273 /* Value is the number of pixels for the ascent of image IMG when
1274 drawn in face FACE. */
1277 image_ascent (img
, face
, slice
)
1280 struct glyph_slice
*slice
;
1285 if (slice
->height
== img
->height
)
1286 height
= img
->height
+ img
->vmargin
;
1287 else if (slice
->y
== 0)
1288 height
= slice
->height
+ img
->vmargin
;
1290 height
= slice
->height
;
1292 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1297 /* W32 specific version. Why?. ++kfs */
1298 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1299 - FONT_BASE(face
->font
)) / 2;
1301 /* This expression is arranged so that if the image can't be
1302 exactly centered, it will be moved slightly up. This is
1303 because a typical font is `top-heavy' (due to the presence
1304 uppercase letters), so the image placement should err towards
1305 being top-heavy too. It also just generally looks better. */
1306 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1307 #endif /* HAVE_NTGUI */
1310 ascent
= height
/ 2;
1313 ascent
= (int) (height
* img
->ascent
/ 100.0);
1319 /* Image background colors. */
1321 /* Find the "best" corner color of a bitmap.
1322 On W32, XIMG is assumed to a device context with the bitmap selected. */
1324 static RGB_PIXEL_COLOR
1325 four_corners_best (ximg
, width
, height
)
1326 XImagePtr_or_DC ximg
;
1327 unsigned long width
, height
;
1329 RGB_PIXEL_COLOR corners
[4], best
;
1332 /* Get the colors at the corners of ximg. */
1333 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1334 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1335 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1336 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1338 /* Choose the most frequently found color as background. */
1339 for (i
= best_count
= 0; i
< 4; ++i
)
1343 for (j
= n
= 0; j
< 4; ++j
)
1344 if (corners
[i
] == corners
[j
])
1348 best
= corners
[i
], best_count
= n
;
1354 /* Portability macros */
1358 #define Destroy_Image(img_dc, prev) \
1359 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1361 #define Free_Pixmap(display, pixmap) \
1362 DeleteObject (pixmap)
1366 #define Destroy_Image(ximg, dummy) \
1367 XDestroyImage (ximg)
1369 #define Free_Pixmap(display, pixmap) \
1370 XFreePixmap (display, pixmap)
1372 #endif /* HAVE_NTGUI */
1375 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1376 it is guessed heuristically. If non-zero, XIMG is an existing
1377 XImage object (or device context with the image selected on W32) to
1378 use for the heuristic. */
1381 image_background (img
, f
, ximg
)
1384 XImagePtr_or_DC ximg
;
1386 if (! img
->background_valid
)
1387 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1389 int free_ximg
= !ximg
;
1392 #endif /* HAVE_NTGUI */
1397 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1398 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1400 HDC frame_dc
= get_frame_dc (f
);
1401 ximg
= CreateCompatibleDC (frame_dc
);
1402 release_frame_dc (f
, frame_dc
);
1403 prev
= SelectObject (ximg
, img
->pixmap
);
1404 #endif /* !HAVE_NTGUI */
1407 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1410 Destroy_Image (ximg
, prev
);
1412 img
->background_valid
= 1;
1415 return img
->background
;
1418 /* Return the `background_transparent' field of IMG. If IMG doesn't
1419 have one yet, it is guessed heuristically. If non-zero, MASK is an
1420 existing XImage object to use for the heuristic. */
1423 image_background_transparent (img
, f
, mask
)
1426 XImagePtr_or_DC mask
;
1428 if (! img
->background_transparent_valid
)
1429 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1433 int free_mask
= !mask
;
1436 #endif /* HAVE_NTGUI */
1441 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1442 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1444 HDC frame_dc
= get_frame_dc (f
);
1445 mask
= CreateCompatibleDC (frame_dc
);
1446 release_frame_dc (f
, frame_dc
);
1447 prev
= SelectObject (mask
, img
->mask
);
1448 #endif /* HAVE_NTGUI */
1451 img
->background_transparent
1452 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1455 Destroy_Image (mask
, prev
);
1458 img
->background_transparent
= 0;
1460 img
->background_transparent_valid
= 1;
1463 return img
->background_transparent
;
1467 /***********************************************************************
1468 Helper functions for X image types
1469 ***********************************************************************/
1471 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1473 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1474 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1476 Lisp_Object color_name
,
1477 unsigned long dflt
));
1480 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1481 free the pixmap if any. MASK_P non-zero means clear the mask
1482 pixmap if any. COLORS_P non-zero means free colors allocated for
1483 the image, if any. */
1486 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1489 int pixmap_p
, mask_p
, colors_p
;
1491 if (pixmap_p
&& img
->pixmap
)
1493 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1494 img
->pixmap
= NO_PIXMAP
;
1495 img
->background_valid
= 0;
1498 if (mask_p
&& img
->mask
)
1500 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1501 img
->mask
= NO_PIXMAP
;
1502 img
->background_transparent_valid
= 0;
1505 if (colors_p
&& img
->ncolors
)
1507 /* MAC_TODO: color table support. */
1508 /* W32_TODO: color table support. */
1509 #ifdef HAVE_X_WINDOWS
1510 x_free_colors (f
, img
->colors
, img
->ncolors
);
1511 #endif /* HAVE_X_WINDOWS */
1512 xfree (img
->colors
);
1517 #if defined (MAC_OS) && USE_CG_DRAWING
1518 if (img
->data
.ptr_val
)
1520 CGImageRelease (img
->data
.ptr_val
);
1521 img
->data
.ptr_val
= NULL
;
1526 /* Free X resources of image IMG which is used on frame F. */
1529 x_clear_image (f
, img
)
1534 x_clear_image_1 (f
, img
, 1, 1, 1);
1539 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1540 cannot be allocated, use DFLT. Add a newly allocated color to
1541 IMG->colors, so that it can be freed again. Value is the pixel
1544 static unsigned long
1545 x_alloc_image_color (f
, img
, color_name
, dflt
)
1548 Lisp_Object color_name
;
1552 unsigned long result
;
1554 xassert (STRINGP (color_name
));
1556 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1558 /* This isn't called frequently so we get away with simply
1559 reallocating the color vector to the needed size, here. */
1562 (unsigned long *) xrealloc (img
->colors
,
1563 img
->ncolors
* sizeof *img
->colors
);
1564 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1565 result
= color
.pixel
;
1575 /***********************************************************************
1577 ***********************************************************************/
1579 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1580 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1582 /* Return a new, initialized image cache that is allocated from the
1583 heap. Call free_image_cache to free an image cache. */
1585 struct image_cache
*
1588 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1591 bzero (c
, sizeof *c
);
1593 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1594 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1595 c
->buckets
= (struct image
**) xmalloc (size
);
1596 bzero (c
->buckets
, size
);
1601 /* Free image cache of frame F. Be aware that X frames share images
1605 free_image_cache (f
)
1608 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1613 /* Cache should not be referenced by any frame when freed. */
1614 xassert (c
->refcount
== 0);
1616 for (i
= 0; i
< c
->used
; ++i
)
1617 free_image (f
, c
->images
[i
]);
1621 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1626 /* Clear image cache of frame F. FORCE_P non-zero means free all
1627 images. FORCE_P zero means clear only images that haven't been
1628 displayed for some time. Should be called from time to time to
1629 reduce the number of loaded images. If image-eviction-seconds is
1630 non-nil, this frees images in the cache which weren't displayed for
1631 at least that many seconds. */
1634 clear_image_cache (f
, force_p
)
1638 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1640 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1647 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1649 /* Block input so that we won't be interrupted by a SIGIO
1650 while being in an inconsistent state. */
1653 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1655 struct image
*img
= c
->images
[i
];
1657 && (force_p
|| img
->timestamp
< old
))
1659 free_image (f
, img
);
1664 /* We may be clearing the image cache because, for example,
1665 Emacs was iconified for a longer period of time. In that
1666 case, current matrices may still contain references to
1667 images freed above. So, clear these matrices. */
1670 Lisp_Object tail
, frame
;
1672 FOR_EACH_FRAME (tail
, frame
)
1674 struct frame
*f
= XFRAME (frame
);
1675 if (FRAME_WINDOW_P (f
)
1676 && FRAME_X_IMAGE_CACHE (f
) == c
)
1677 clear_current_matrices (f
);
1680 ++windows_or_buffers_changed
;
1688 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1690 doc
: /* Clear the image cache of FRAME.
1691 FRAME nil or omitted means use the selected frame.
1692 FRAME t means clear the image caches of all frames. */)
1700 FOR_EACH_FRAME (tail
, frame
)
1701 if (FRAME_WINDOW_P (XFRAME (frame
)))
1702 clear_image_cache (XFRAME (frame
), 1);
1705 clear_image_cache (check_x_frame (frame
), 1);
1711 /* Compute masks and transform image IMG on frame F, as specified
1712 by the image's specification, */
1715 postprocess_image (f
, img
)
1719 /* Manipulation of the image's mask. */
1722 Lisp_Object conversion
, spec
;
1727 /* `:heuristic-mask t'
1729 means build a mask heuristically.
1730 `:heuristic-mask (R G B)'
1731 `:mask (heuristic (R G B))'
1732 means build a mask from color (R G B) in the
1735 means remove a mask, if any. */
1737 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1739 x_build_heuristic_mask (f
, img
, mask
);
1744 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1746 if (EQ (mask
, Qheuristic
))
1747 x_build_heuristic_mask (f
, img
, Qt
);
1748 else if (CONSP (mask
)
1749 && EQ (XCAR (mask
), Qheuristic
))
1751 if (CONSP (XCDR (mask
)))
1752 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1754 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1756 else if (NILP (mask
) && found_p
&& img
->mask
)
1758 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1759 img
->mask
= NO_PIXMAP
;
1764 /* Should we apply an image transformation algorithm? */
1765 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1766 if (EQ (conversion
, Qdisabled
))
1767 x_disable_image (f
, img
);
1768 else if (EQ (conversion
, Qlaplace
))
1770 else if (EQ (conversion
, Qemboss
))
1772 else if (CONSP (conversion
)
1773 && EQ (XCAR (conversion
), Qedge_detection
))
1776 tem
= XCDR (conversion
);
1778 x_edge_detection (f
, img
,
1779 Fplist_get (tem
, QCmatrix
),
1780 Fplist_get (tem
, QCcolor_adjustment
));
1786 /* Return the id of image with Lisp specification SPEC on frame F.
1787 SPEC must be a valid Lisp image specification (see valid_image_p). */
1790 lookup_image (f
, spec
)
1794 struct image_cache
*c
;
1798 struct gcpro gcpro1
;
1801 /* F must be a window-system frame, and SPEC must be a valid image
1803 xassert (FRAME_WINDOW_P (f
));
1804 xassert (valid_image_p (spec
));
1806 c
= FRAME_X_IMAGE_CACHE (f
);
1810 /* Look up SPEC in the hash table of the image cache. */
1811 hash
= sxhash (spec
, 0);
1812 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1814 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1815 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1818 if (img
&& img
->load_failed_p
)
1820 free_image (f
, img
);
1824 /* If not found, create a new image and cache it. */
1827 extern Lisp_Object Qpostscript
;
1830 img
= make_image (spec
, hash
);
1831 cache_image (f
, img
);
1832 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1834 /* If we can't load the image, and we don't have a width and
1835 height, use some arbitrary width and height so that we can
1836 draw a rectangle for it. */
1837 if (img
->load_failed_p
)
1841 value
= image_spec_value (spec
, QCwidth
, NULL
);
1842 img
->width
= (INTEGERP (value
)
1843 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1844 value
= image_spec_value (spec
, QCheight
, NULL
);
1845 img
->height
= (INTEGERP (value
)
1846 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1850 /* Handle image type independent image attributes
1851 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1852 `:background COLOR'. */
1853 Lisp_Object ascent
, margin
, relief
, bg
;
1855 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1856 if (INTEGERP (ascent
))
1857 img
->ascent
= XFASTINT (ascent
);
1858 else if (EQ (ascent
, Qcenter
))
1859 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1861 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1862 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1863 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1864 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1865 && INTEGERP (XCDR (margin
)))
1867 if (XINT (XCAR (margin
)) > 0)
1868 img
->hmargin
= XFASTINT (XCAR (margin
));
1869 if (XINT (XCDR (margin
)) > 0)
1870 img
->vmargin
= XFASTINT (XCDR (margin
));
1873 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1874 if (INTEGERP (relief
))
1876 img
->relief
= XINT (relief
);
1877 img
->hmargin
+= abs (img
->relief
);
1878 img
->vmargin
+= abs (img
->relief
);
1881 if (! img
->background_valid
)
1883 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1887 = x_alloc_image_color (f
, img
, bg
,
1888 FRAME_BACKGROUND_PIXEL (f
));
1889 img
->background_valid
= 1;
1893 /* Do image transformations and compute masks, unless we
1894 don't have the image yet. */
1895 if (!EQ (*img
->type
->type
, Qpostscript
))
1896 postprocess_image (f
, img
);
1902 /* We're using IMG, so set its timestamp to `now'. */
1903 EMACS_GET_TIME (now
);
1904 img
->timestamp
= EMACS_SECS (now
);
1908 /* Value is the image id. */
1913 /* Cache image IMG in the image cache of frame F. */
1916 cache_image (f
, img
)
1920 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1923 /* Find a free slot in c->images. */
1924 for (i
= 0; i
< c
->used
; ++i
)
1925 if (c
->images
[i
] == NULL
)
1928 /* If no free slot found, maybe enlarge c->images. */
1929 if (i
== c
->used
&& c
->used
== c
->size
)
1932 c
->images
= (struct image
**) xrealloc (c
->images
,
1933 c
->size
* sizeof *c
->images
);
1936 /* Add IMG to c->images, and assign IMG an id. */
1942 /* Add IMG to the cache's hash table. */
1943 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1944 img
->next
= c
->buckets
[i
];
1946 img
->next
->prev
= img
;
1948 c
->buckets
[i
] = img
;
1952 /* Call FN on every image in the image cache of frame F. Used to mark
1953 Lisp Objects in the image cache. */
1956 forall_images_in_image_cache (f
, fn
)
1958 void (*fn
) P_ ((struct image
*img
));
1960 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1962 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1966 for (i
= 0; i
< c
->used
; ++i
)
1975 /***********************************************************************
1976 X / MAC / W32 support code
1977 ***********************************************************************/
1981 /* Macro for defining functions that will be loaded from image DLLs. */
1982 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
1984 /* Macro for loading those image functions from the library. */
1985 #define LOAD_IMGLIB_FN(lib,func) { \
1986 fn_##func = (void *) GetProcAddress (lib, #func); \
1987 if (!fn_##func) return 0; \
1990 /* Load a DLL implementing an image type.
1991 The `image-library-alist' variable associates a symbol,
1992 identifying an image type, to a list of possible filenames.
1993 The function returns NULL if no library could be loaded for
1994 the given image type, or if the library was previously loaded;
1995 else the handle of the DLL. */
1997 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
1999 HMODULE library
= NULL
;
2001 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2003 Lisp_Object dlls
= Fassq (type
, libraries
);
2006 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2008 CHECK_STRING_CAR (dlls
);
2009 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2017 #endif /* HAVE_NTGUI */
2019 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2020 XImagePtr
*, Pixmap
*));
2021 static void x_destroy_x_image
P_ ((XImagePtr
));
2022 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2025 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2026 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2027 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2028 via xmalloc. Print error messages via image_error if an error
2029 occurs. Value is non-zero if successful.
2031 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2032 should indicate the bit depth of the image. */
2035 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2037 int width
, height
, depth
;
2041 #ifdef HAVE_X_WINDOWS
2042 Display
*display
= FRAME_X_DISPLAY (f
);
2043 Window window
= FRAME_X_WINDOW (f
);
2044 Screen
*screen
= FRAME_X_SCREEN (f
);
2046 xassert (interrupt_input_blocked
);
2049 depth
= DefaultDepthOfScreen (screen
);
2050 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2051 depth
, ZPixmap
, 0, NULL
, width
, height
,
2052 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2055 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2059 /* Allocate image raster. */
2060 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2062 /* Allocate a pixmap of the same size. */
2063 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2064 if (*pixmap
== NO_PIXMAP
)
2066 x_destroy_x_image (*ximg
);
2068 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2073 #endif /* HAVE_X_WINDOWS */
2077 BITMAPINFOHEADER
*header
;
2079 int scanline_width_bits
;
2081 int palette_colors
= 0;
2086 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2087 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2089 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2093 scanline_width_bits
= width
* depth
;
2094 remainder
= scanline_width_bits
% 32;
2097 scanline_width_bits
+= 32 - remainder
;
2099 /* Bitmaps with a depth less than 16 need a palette. */
2100 /* BITMAPINFO structure already contains the first RGBQUAD. */
2102 palette_colors
= 1 << depth
- 1;
2104 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2107 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2111 header
= &((*ximg
)->info
.bmiHeader
);
2112 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2113 header
->biSize
= sizeof (*header
);
2114 header
->biWidth
= width
;
2115 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2116 header
->biPlanes
= 1;
2117 header
->biBitCount
= depth
;
2118 header
->biCompression
= BI_RGB
;
2119 header
->biClrUsed
= palette_colors
;
2121 /* TODO: fill in palette. */
2124 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2125 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2126 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2127 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2128 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2129 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2130 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2131 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2134 hdc
= get_frame_dc (f
);
2136 /* Create a DIBSection and raster array for the bitmap,
2137 and store its handle in *pixmap. */
2138 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2139 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2140 /* casting avoids a GCC warning */
2141 (void **)&((*ximg
)->data
), NULL
, 0);
2143 /* Realize display palette and garbage all frames. */
2144 release_frame_dc (f
, hdc
);
2146 if (*pixmap
== NULL
)
2148 DWORD err
= GetLastError();
2149 Lisp_Object errcode
;
2150 /* All system errors are < 10000, so the following is safe. */
2151 XSETINT (errcode
, (int) err
);
2152 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2153 x_destroy_x_image (*ximg
);
2159 #endif /* HAVE_NTGUI */
2162 Display
*display
= FRAME_X_DISPLAY (f
);
2163 Window window
= FRAME_X_WINDOW (f
);
2165 xassert (interrupt_input_blocked
);
2167 /* Allocate a pixmap of the same size. */
2168 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2169 if (*pixmap
== NO_PIXMAP
)
2172 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2176 LockPixels (GetGWorldPixMap (*pixmap
));
2184 /* Destroy XImage XIMG. Free XIMG->data. */
2187 x_destroy_x_image (ximg
)
2190 xassert (interrupt_input_blocked
);
2193 #ifdef HAVE_X_WINDOWS
2196 XDestroyImage (ximg
);
2197 #endif /* HAVE_X_WINDOWS */
2199 /* Data will be freed by DestroyObject. */
2202 #endif /* HAVE_NTGUI */
2204 XDestroyImage (ximg
);
2210 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2211 are width and height of both the image and pixmap. */
2214 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2220 #ifdef HAVE_X_WINDOWS
2223 xassert (interrupt_input_blocked
);
2224 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2225 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2226 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2227 #endif /* HAVE_X_WINDOWS */
2230 #if 0 /* I don't think this is necessary looking at where it is used. */
2231 HDC hdc
= get_frame_dc (f
);
2232 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2233 release_frame_dc (f
, hdc
);
2235 #endif /* HAVE_NTGUI */
2238 xassert (ximg
== pixmap
);
2243 /***********************************************************************
2245 ***********************************************************************/
2247 static unsigned char *slurp_file
P_ ((char *, int *));
2250 /* Find image file FILE. Look in data-directory, then
2251 x-bitmap-file-path. Value is the encoded full name of the file
2252 found, or nil if not found. */
2255 x_find_image_file (file
)
2258 Lisp_Object file_found
, search_path
;
2259 struct gcpro gcpro1
, gcpro2
;
2263 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2264 GCPRO2 (file_found
, search_path
);
2266 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2267 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2273 file_found
= ENCODE_FILE (file_found
);
2282 /* Read FILE into memory. Value is a pointer to a buffer allocated
2283 with xmalloc holding FILE's contents. Value is null if an error
2284 occurred. *SIZE is set to the size of the file. */
2286 static unsigned char *
2287 slurp_file (file
, size
)
2292 unsigned char *buf
= NULL
;
2295 if (stat (file
, &st
) == 0
2296 && (fp
= fopen (file
, "rb")) != NULL
2297 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2298 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2321 /***********************************************************************
2322 MAC Image Load Functions
2323 ***********************************************************************/
2325 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2328 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2332 find_image_fsspec (specified_file
, file
, fss
)
2333 Lisp_Object specified_file
, *file
;
2339 *file
= x_find_image_file (specified_file
);
2340 if (!STRINGP (*file
))
2341 return fnfErr
; /* file or directory not found;
2342 incomplete pathname */
2343 /* Try to open the image file. */
2344 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (*file
),
2345 SBYTES (*file
), typeFSS
, &desc
);
2348 #if TARGET_API_MAC_CARBON
2349 err
= AEGetDescData (&desc
, fss
, sizeof (FSSpec
));
2351 *fss
= *(FSSpec
*)(*(desc
.dataHandle
));
2353 AEDisposeDesc (&desc
);
2359 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2367 GraphicsImportComponent gi
;
2370 ImageDescriptionHandle desc_handle
;
2371 short draw_all_pixels
;
2372 Lisp_Object specified_bg
;
2377 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2381 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2386 /* read from file system spec */
2387 err
= GraphicsImportSetDataFile (gi
, fss
);
2390 image_error ("Cannot set fsspec to graphics importer for '%s'",
2397 /* read from data handle */
2398 err
= GraphicsImportSetDataHandle (gi
, dh
);
2401 image_error ("Cannot set data handle to graphics importer for `%s'",
2406 err
= GraphicsImportGetImageDescription (gi
, &desc_handle
);
2407 if (err
!= noErr
|| desc_handle
== NULL
)
2409 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2412 width
= img
->width
= (*desc_handle
)->width
;
2413 height
= img
->height
= (*desc_handle
)->height
;
2414 DisposeHandle ((Handle
)desc_handle
);
2416 if (!check_image_size (f
, width
, height
))
2418 image_error ("Invalid image size", Qnil
, Qnil
);
2422 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2424 /* Don't check the error code here. It may have an undocumented
2428 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2432 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2434 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2435 if (!STRINGP (specified_bg
) ||
2436 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2438 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2439 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2440 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2441 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2445 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2447 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2452 GetGWorld (&old_port
, &old_gdh
);
2453 SetGWorld (ximg
, NULL
);
2454 bg_color
.red
= color
.red
;
2455 bg_color
.green
= color
.green
;
2456 bg_color
.blue
= color
.blue
;
2457 RGBBackColor (&bg_color
);
2458 #if TARGET_API_MAC_CARBON
2459 GetPortBounds (ximg
, &rect
);
2462 EraseRect (&(ximg
->portRect
));
2464 SetGWorld (old_port
, old_gdh
);
2466 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2467 GraphicsImportDraw (gi
);
2468 CloseComponent (gi
);
2470 /* Maybe fill in the background field while we have ximg handy. */
2471 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2472 IMAGE_BACKGROUND (img
, f
, ximg
);
2474 /* Put the image into the pixmap. */
2475 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2476 x_destroy_x_image (ximg
);
2480 CloseComponent (gi
);
2485 /* Load an image using the QuickTime Graphics Importer.
2486 Note: The alpha channel does not work for PNG images. */
2488 image_load_quicktime (f
, img
, type
)
2493 Lisp_Object specified_file
;
2494 Lisp_Object specified_data
;
2497 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2498 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2500 if (NILP (specified_data
))
2502 /* Read from a file */
2506 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2510 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2512 image_error ("Cannot open `%s'", file
, Qnil
);
2515 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2519 /* Memory source! */
2523 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2526 image_error ("Cannot allocate data handle for `%s'",
2530 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2538 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2539 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2540 So don't use this function directly but determine at runtime
2541 whether it exists. */
2542 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2543 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2544 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2548 init_image_func_pointer ()
2550 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2552 MyCGImageCreateWithPNGDataProvider
2553 = (CGImageCreateWithPNGDataProviderProcType
)
2554 NSAddressOfSymbol (NSLookupAndBindSymbol
2555 ("_CGImageCreateWithPNGDataProvider"));
2558 MyCGImageCreateWithPNGDataProvider
= NULL
;
2563 image_load_quartz2d (f
, img
, png_p
)
2568 Lisp_Object file
, specified_file
;
2569 Lisp_Object specified_data
, specified_bg
;
2570 struct gcpro gcpro1
;
2571 CGDataProviderRef source
;
2575 XImagePtr ximg
= NULL
;
2576 CGContextRef context
;
2579 /* Open the file. */
2580 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2581 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2586 if (NILP (specified_data
))
2591 file
= x_find_image_file (specified_file
);
2592 if (!STRINGP (file
))
2594 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2598 path
= cfstring_create_with_string (file
);
2599 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2600 kCFURLPOSIXPathStyle
, 0);
2602 source
= CGDataProviderCreateWithURL (url
);
2606 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2607 SBYTES (specified_data
), NULL
);
2610 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2611 kCGRenderingIntentDefault
);
2613 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2614 kCGRenderingIntentDefault
);
2616 CGDataProviderRelease (source
);
2620 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2623 width
= img
->width
= CGImageGetWidth (image
);
2624 height
= img
->height
= CGImageGetHeight (image
);
2626 if (!check_image_size (f
, width
, height
))
2628 CGImageRelease (image
);
2630 image_error ("Invalid image size", Qnil
, Qnil
);
2636 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2637 if (!STRINGP (specified_bg
) ||
2638 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2640 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2641 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2642 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2643 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2647 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2649 CGImageRelease (image
);
2653 rectangle
= CGRectMake (0, 0, width
, height
);
2654 QDBeginCGContext (ximg
, &context
);
2657 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2658 color
.green
/ 65535.0,
2659 color
.blue
/ 65535.0, 1.0);
2660 CGContextFillRect (context
, rectangle
);
2662 CGContextDrawImage (context
, rectangle
, image
);
2663 QDEndCGContext (ximg
, &context
);
2664 CGImageRelease (image
);
2666 /* Maybe fill in the background field while we have ximg handy. */
2667 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2668 IMAGE_BACKGROUND (img
, f
, ximg
);
2670 /* Put the image into the pixmap. */
2671 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2672 x_destroy_x_image (ximg
);
2681 /***********************************************************************
2683 ***********************************************************************/
2685 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2686 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2687 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2688 unsigned char *, unsigned char *));
2689 static int xbm_image_p
P_ ((Lisp_Object object
));
2690 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2691 unsigned char *, unsigned char *,
2692 int *, int *, unsigned char **));
2693 static int xbm_file_p
P_ ((Lisp_Object
));
2696 /* Indices of image specification fields in xbm_format, below. */
2698 enum xbm_keyword_index
2716 /* Vector of image_keyword structures describing the format
2717 of valid XBM image specifications. */
2719 static struct image_keyword xbm_format
[XBM_LAST
] =
2721 {":type", IMAGE_SYMBOL_VALUE
, 1},
2722 {":file", IMAGE_STRING_VALUE
, 0},
2723 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2724 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2725 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2726 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2727 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2728 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2729 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2730 {":relief", IMAGE_INTEGER_VALUE
, 0},
2731 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2732 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2733 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2736 /* Structure describing the image type XBM. */
2738 static struct image_type xbm_type
=
2747 /* Tokens returned from xbm_scan. */
2756 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2757 A valid specification is a list starting with the symbol `image'
2758 The rest of the list is a property list which must contain an
2761 If the specification specifies a file to load, it must contain
2762 an entry `:file FILENAME' where FILENAME is a string.
2764 If the specification is for a bitmap loaded from memory it must
2765 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2766 WIDTH and HEIGHT are integers > 0. DATA may be:
2768 1. a string large enough to hold the bitmap data, i.e. it must
2769 have a size >= (WIDTH + 7) / 8 * HEIGHT
2771 2. a bool-vector of size >= WIDTH * HEIGHT
2773 3. a vector of strings or bool-vectors, one for each line of the
2776 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2777 may not be specified in this case because they are defined in the
2780 Both the file and data forms may contain the additional entries
2781 `:background COLOR' and `:foreground COLOR'. If not present,
2782 foreground and background of the frame on which the image is
2783 displayed is used. */
2786 xbm_image_p (object
)
2789 struct image_keyword kw
[XBM_LAST
];
2791 bcopy (xbm_format
, kw
, sizeof kw
);
2792 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2795 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2797 if (kw
[XBM_FILE
].count
)
2799 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2802 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2804 /* In-memory XBM file. */
2805 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2813 /* Entries for `:width', `:height' and `:data' must be present. */
2814 if (!kw
[XBM_WIDTH
].count
2815 || !kw
[XBM_HEIGHT
].count
2816 || !kw
[XBM_DATA
].count
)
2819 data
= kw
[XBM_DATA
].value
;
2820 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2821 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2823 /* Check type of data, and width and height against contents of
2829 /* Number of elements of the vector must be >= height. */
2830 if (XVECTOR (data
)->size
< height
)
2833 /* Each string or bool-vector in data must be large enough
2834 for one line of the image. */
2835 for (i
= 0; i
< height
; ++i
)
2837 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2842 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2845 else if (BOOL_VECTOR_P (elt
))
2847 if (XBOOL_VECTOR (elt
)->size
< width
)
2854 else if (STRINGP (data
))
2857 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2860 else if (BOOL_VECTOR_P (data
))
2862 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2873 /* Scan a bitmap file. FP is the stream to read from. Value is
2874 either an enumerator from enum xbm_token, or a character for a
2875 single-character token, or 0 at end of file. If scanning an
2876 identifier, store the lexeme of the identifier in SVAL. If
2877 scanning a number, store its value in *IVAL. */
2880 xbm_scan (s
, end
, sval
, ival
)
2881 unsigned char **s
, *end
;
2889 /* Skip white space. */
2890 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2895 else if (isdigit (c
))
2897 int value
= 0, digit
;
2899 if (c
== '0' && *s
< end
)
2902 if (c
== 'x' || c
== 'X')
2909 else if (c
>= 'a' && c
<= 'f')
2910 digit
= c
- 'a' + 10;
2911 else if (c
>= 'A' && c
<= 'F')
2912 digit
= c
- 'A' + 10;
2915 value
= 16 * value
+ digit
;
2918 else if (isdigit (c
))
2922 && (c
= *(*s
)++, isdigit (c
)))
2923 value
= 8 * value
+ c
- '0';
2930 && (c
= *(*s
)++, isdigit (c
)))
2931 value
= 10 * value
+ c
- '0';
2939 else if (isalpha (c
) || c
== '_')
2943 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2950 else if (c
== '/' && **s
== '*')
2952 /* C-style comment. */
2954 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2968 /* Create a Windows bitmap from X bitmap data. */
2970 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2972 static unsigned char swap_nibble
[16]
2973 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2974 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2975 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2976 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2978 unsigned char *bits
, *p
;
2981 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2982 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2983 bits
= (unsigned char *) alloca (height
* w2
);
2984 bzero (bits
, height
* w2
);
2985 for (i
= 0; i
< height
; i
++)
2988 for (j
= 0; j
< w1
; j
++)
2990 /* Bitswap XBM bytes to match how Windows does things. */
2991 unsigned char c
= *data
++;
2992 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2993 | (swap_nibble
[(c
>>4) & 0xf]));
2996 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
3001 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
3004 COLORREF foreground
, background
;
3006 HDC hdc
, old_img_dc
, new_img_dc
;
3007 HGDIOBJ old_prev
, new_prev
;
3010 hdc
= get_frame_dc (f
);
3011 old_img_dc
= CreateCompatibleDC (hdc
);
3012 new_img_dc
= CreateCompatibleDC (hdc
);
3013 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
3014 release_frame_dc (f
, hdc
);
3015 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
3016 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
3017 SetTextColor (new_img_dc
, foreground
);
3018 SetBkColor (new_img_dc
, background
);
3020 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
3023 SelectObject (old_img_dc
, old_prev
);
3024 SelectObject (new_img_dc
, new_prev
);
3025 DeleteDC (old_img_dc
);
3026 DeleteDC (new_img_dc
);
3027 DeleteObject (img
->pixmap
);
3028 if (new_pixmap
== 0)
3029 fprintf (stderr
, "Failed to convert image to color.\n");
3031 img
->pixmap
= new_pixmap
;
3034 #define XBM_BIT_SHUFFLE(b) (~(b))
3038 #define XBM_BIT_SHUFFLE(b) (b)
3040 #endif /* HAVE_NTGUI */
3044 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
3048 RGB_PIXEL_COLOR fg
, bg
;
3049 int non_default_colors
;
3053 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
3055 /* If colors were specified, transfer the bitmap to a color one. */
3056 if (non_default_colors
)
3057 convert_mono_to_color_image (f
, img
, fg
, bg
);
3060 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
3063 img
->width
, img
->height
,
3065 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
3066 #endif /* HAVE_NTGUI */
3071 /* Replacement for XReadBitmapFileData which isn't available under old
3072 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3073 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3074 the image. Return in *DATA the bitmap data allocated with xmalloc.
3075 Value is non-zero if successful. DATA null means just test if
3076 CONTENTS looks like an in-memory XBM file. */
3079 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
3081 unsigned char *contents
, *end
;
3082 int *width
, *height
;
3083 unsigned char **data
;
3085 unsigned char *s
= contents
;
3086 char buffer
[BUFSIZ
];
3089 int bytes_per_line
, i
, nbytes
;
3095 LA1 = xbm_scan (&s, end, buffer, &value)
3097 #define expect(TOKEN) \
3098 if (LA1 != (TOKEN)) \
3103 #define expect_ident(IDENT) \
3104 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3109 *width
= *height
= -1;
3112 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
3114 /* Parse defines for width, height and hot-spots. */
3118 expect_ident ("define");
3119 expect (XBM_TK_IDENT
);
3121 if (LA1
== XBM_TK_NUMBER
);
3123 char *p
= strrchr (buffer
, '_');
3124 p
= p
? p
+ 1 : buffer
;
3125 if (strcmp (p
, "width") == 0)
3127 else if (strcmp (p
, "height") == 0)
3130 expect (XBM_TK_NUMBER
);
3133 if (!check_image_size (f
, *width
, *height
))
3135 else if (data
== NULL
)
3138 /* Parse bits. Must start with `static'. */
3139 expect_ident ("static");
3140 if (LA1
== XBM_TK_IDENT
)
3142 if (strcmp (buffer
, "unsigned") == 0)
3145 expect_ident ("char");
3147 else if (strcmp (buffer
, "short") == 0)
3151 if (*width
% 16 && *width
% 16 < 9)
3154 else if (strcmp (buffer
, "char") == 0)
3162 expect (XBM_TK_IDENT
);
3168 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3169 nbytes
= bytes_per_line
* *height
;
3170 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3174 for (i
= 0; i
< nbytes
; i
+= 2)
3177 expect (XBM_TK_NUMBER
);
3179 *p
++ = XBM_BIT_SHUFFLE (val
);
3180 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3181 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3183 if (LA1
== ',' || LA1
== '}')
3191 for (i
= 0; i
< nbytes
; ++i
)
3194 expect (XBM_TK_NUMBER
);
3196 *p
++ = XBM_BIT_SHUFFLE (val
);
3198 if (LA1
== ',' || LA1
== '}')
3223 /* Load XBM image IMG which will be displayed on frame F from buffer
3224 CONTENTS. END is the end of the buffer. Value is non-zero if
3228 xbm_load_image (f
, img
, contents
, end
)
3231 unsigned char *contents
, *end
;
3234 unsigned char *data
;
3237 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3240 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3241 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3242 int non_default_colors
= 0;
3245 xassert (img
->width
> 0 && img
->height
> 0);
3247 /* Get foreground and background colors, maybe allocate colors. */
3248 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3251 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3252 non_default_colors
= 1;
3254 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3257 background
= x_alloc_image_color (f
, img
, value
, background
);
3258 img
->background
= background
;
3259 img
->background_valid
= 1;
3260 non_default_colors
= 1;
3263 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3264 foreground
, background
,
3265 non_default_colors
);
3268 if (img
->pixmap
== NO_PIXMAP
)
3270 x_clear_image (f
, img
);
3271 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3277 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3283 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3290 return (STRINGP (data
)
3291 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3298 /* Fill image IMG which is used on frame F with pixmap data. Value is
3299 non-zero if successful. */
3307 Lisp_Object file_name
;
3309 xassert (xbm_image_p (img
->spec
));
3311 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3312 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3313 if (STRINGP (file_name
))
3316 unsigned char *contents
;
3318 struct gcpro gcpro1
;
3320 file
= x_find_image_file (file_name
);
3322 if (!STRINGP (file
))
3324 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3329 contents
= slurp_file (SDATA (file
), &size
);
3330 if (contents
== NULL
)
3332 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3337 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3342 struct image_keyword fmt
[XBM_LAST
];
3344 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3345 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3346 int non_default_colors
= 0;
3349 int in_memory_file_p
= 0;
3351 /* See if data looks like an in-memory XBM file. */
3352 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3353 in_memory_file_p
= xbm_file_p (data
);
3355 /* Parse the image specification. */
3356 bcopy (xbm_format
, fmt
, sizeof fmt
);
3357 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3360 /* Get specified width, and height. */
3361 if (!in_memory_file_p
)
3363 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3364 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3365 xassert (img
->width
> 0 && img
->height
> 0);
3368 /* Get foreground and background colors, maybe allocate colors. */
3369 if (fmt
[XBM_FOREGROUND
].count
3370 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3372 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3374 non_default_colors
= 1;
3377 if (fmt
[XBM_BACKGROUND
].count
3378 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3380 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3382 non_default_colors
= 1;
3385 if (in_memory_file_p
)
3386 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3395 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3397 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3398 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3400 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3402 bcopy (SDATA (line
), p
, nbytes
);
3404 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3407 else if (STRINGP (data
))
3408 bits
= SDATA (data
);
3410 bits
= XBOOL_VECTOR (data
)->data
;
3412 /* Create the pixmap. */
3414 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3415 foreground
, background
,
3416 non_default_colors
);
3421 image_error ("Unable to create pixmap for XBM image `%s'",
3423 x_clear_image (f
, img
);
3433 /***********************************************************************
3435 ***********************************************************************/
3437 #if defined (HAVE_XPM) || defined (MAC_OS)
3439 static int xpm_image_p
P_ ((Lisp_Object object
));
3440 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3441 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3443 #endif /* HAVE_XPM || MAC_OS */
3447 /* Indicate to xpm.h that we don't have Xlib. */
3449 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3450 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3451 #define XColor xpm_XColor
3452 #define XImage xpm_XImage
3453 #define Display xpm_Display
3454 #define PIXEL_ALREADY_TYPEDEFED
3455 #include "X11/xpm.h"
3460 #undef PIXEL_ALREADY_TYPEDEFED
3462 #include "X11/xpm.h"
3463 #endif /* HAVE_NTGUI */
3464 #endif /* HAVE_XPM */
3466 #if defined (HAVE_XPM) || defined (MAC_OS)
3467 /* The symbol `xpm' identifying XPM-format images. */
3471 /* Indices of image specification fields in xpm_format, below. */
3473 enum xpm_keyword_index
3489 /* Vector of image_keyword structures describing the format
3490 of valid XPM image specifications. */
3492 static struct image_keyword xpm_format
[XPM_LAST
] =
3494 {":type", IMAGE_SYMBOL_VALUE
, 1},
3495 {":file", IMAGE_STRING_VALUE
, 0},
3496 {":data", IMAGE_STRING_VALUE
, 0},
3497 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3498 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3499 {":relief", IMAGE_INTEGER_VALUE
, 0},
3500 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3501 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3502 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3503 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3504 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3507 /* Structure describing the image type XPM. */
3509 static struct image_type xpm_type
=
3518 #ifdef HAVE_X_WINDOWS
3520 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3521 functions for allocating image colors. Our own functions handle
3522 color allocation failures more gracefully than the ones on the XPM
3525 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3526 #define ALLOC_XPM_COLORS
3528 #endif /* HAVE_X_WINDOWS */
3530 #ifdef ALLOC_XPM_COLORS
3532 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3533 static void xpm_free_color_cache
P_ ((void));
3534 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3535 static int xpm_color_bucket
P_ ((char *));
3536 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3539 /* An entry in a hash table used to cache color definitions of named
3540 colors. This cache is necessary to speed up XPM image loading in
3541 case we do color allocations ourselves. Without it, we would need
3542 a call to XParseColor per pixel in the image. */
3544 struct xpm_cached_color
3546 /* Next in collision chain. */
3547 struct xpm_cached_color
*next
;
3549 /* Color definition (RGB and pixel color). */
3556 /* The hash table used for the color cache, and its bucket vector
3559 #define XPM_COLOR_CACHE_BUCKETS 1001
3560 struct xpm_cached_color
**xpm_color_cache
;
3562 /* Initialize the color cache. */
3565 xpm_init_color_cache (f
, attrs
)
3567 XpmAttributes
*attrs
;
3569 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3570 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3571 memset (xpm_color_cache
, 0, nbytes
);
3572 init_color_table ();
3574 if (attrs
->valuemask
& XpmColorSymbols
)
3579 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3580 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3581 attrs
->colorsymbols
[i
].value
, &color
))
3583 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3585 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3590 /* Free the color cache. */
3593 xpm_free_color_cache ()
3595 struct xpm_cached_color
*p
, *next
;
3598 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3599 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3605 xfree (xpm_color_cache
);
3606 xpm_color_cache
= NULL
;
3607 free_color_table ();
3610 /* Return the bucket index for color named COLOR_NAME in the color
3614 xpm_color_bucket (color_name
)
3620 for (s
= color_name
; *s
; ++s
)
3622 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3626 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3627 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3630 static struct xpm_cached_color
*
3631 xpm_cache_color (f
, color_name
, color
, bucket
)
3638 struct xpm_cached_color
*p
;
3641 bucket
= xpm_color_bucket (color_name
);
3643 nbytes
= sizeof *p
+ strlen (color_name
);
3644 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3645 strcpy (p
->name
, color_name
);
3647 p
->next
= xpm_color_cache
[bucket
];
3648 xpm_color_cache
[bucket
] = p
;
3652 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3653 return the cached definition in *COLOR. Otherwise, make a new
3654 entry in the cache and allocate the color. Value is zero if color
3655 allocation failed. */
3658 xpm_lookup_color (f
, color_name
, color
)
3663 struct xpm_cached_color
*p
;
3664 int h
= xpm_color_bucket (color_name
);
3666 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3667 if (strcmp (p
->name
, color_name
) == 0)
3672 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3675 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3677 p
= xpm_cache_color (f
, color_name
, color
, h
);
3679 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3680 with transparency, and it's useful. */
3681 else if (strcmp ("opaque", color_name
) == 0)
3683 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3684 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3685 p
= xpm_cache_color (f
, color_name
, color
, h
);
3692 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3693 CLOSURE is a pointer to the frame on which we allocate the
3694 color. Return in *COLOR the allocated color. Value is non-zero
3698 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3705 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3709 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3710 is a pointer to the frame on which we allocate the color. Value is
3711 non-zero if successful. */
3714 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3724 #endif /* ALLOC_XPM_COLORS */
3729 /* XPM library details. */
3731 DEF_IMGLIB_FN (XpmFreeAttributes
);
3732 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3733 DEF_IMGLIB_FN (XpmReadFileToImage
);
3734 DEF_IMGLIB_FN (XImageFree
);
3737 init_xpm_functions (Lisp_Object libraries
)
3741 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3744 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3745 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3746 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3747 LOAD_IMGLIB_FN (library
, XImageFree
);
3751 #endif /* HAVE_NTGUI */
3754 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3755 for XPM images. Such a list must consist of conses whose car and
3759 xpm_valid_color_symbols_p (color_symbols
)
3760 Lisp_Object color_symbols
;
3762 while (CONSP (color_symbols
))
3764 Lisp_Object sym
= XCAR (color_symbols
);
3766 || !STRINGP (XCAR (sym
))
3767 || !STRINGP (XCDR (sym
)))
3769 color_symbols
= XCDR (color_symbols
);
3772 return NILP (color_symbols
);
3776 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3779 xpm_image_p (object
)
3782 struct image_keyword fmt
[XPM_LAST
];
3783 bcopy (xpm_format
, fmt
, sizeof fmt
);
3784 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3785 /* Either `:file' or `:data' must be present. */
3786 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3787 /* Either no `:color-symbols' or it's a list of conses
3788 whose car and cdr are strings. */
3789 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3790 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3793 #endif /* HAVE_XPM || MAC_OS */
3795 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3797 x_create_bitmap_from_xpm_data (f
, bits
)
3801 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3803 XpmAttributes attrs
;
3804 Pixmap bitmap
, mask
;
3806 bzero (&attrs
, sizeof attrs
);
3808 attrs
.visual
= FRAME_X_VISUAL (f
);
3809 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3810 attrs
.valuemask
|= XpmVisual
;
3811 attrs
.valuemask
|= XpmColormap
;
3813 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3814 bits
, &bitmap
, &mask
, &attrs
);
3815 if (rc
!= XpmSuccess
)
3817 XpmFreeAttributes (&attrs
);
3821 id
= x_allocate_bitmap_record (f
);
3822 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3823 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3824 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3825 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3826 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3827 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3828 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3829 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3831 XpmFreeAttributes (&attrs
);
3834 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3836 /* Load image IMG which will be displayed on frame F. Value is
3837 non-zero if successful. */
3847 XpmAttributes attrs
;
3848 Lisp_Object specified_file
, color_symbols
;
3851 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3852 #endif /* HAVE_NTGUI */
3854 /* Configure the XPM lib. Use the visual of frame F. Allocate
3855 close colors. Return colors allocated. */
3856 bzero (&attrs
, sizeof attrs
);
3859 attrs
.visual
= FRAME_X_VISUAL (f
);
3860 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3861 attrs
.valuemask
|= XpmVisual
;
3862 attrs
.valuemask
|= XpmColormap
;
3863 #endif /* HAVE_NTGUI */
3865 #ifdef ALLOC_XPM_COLORS
3866 /* Allocate colors with our own functions which handle
3867 failing color allocation more gracefully. */
3868 attrs
.color_closure
= f
;
3869 attrs
.alloc_color
= xpm_alloc_color
;
3870 attrs
.free_colors
= xpm_free_colors
;
3871 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3872 #else /* not ALLOC_XPM_COLORS */
3873 /* Let the XPM lib allocate colors. */
3874 attrs
.valuemask
|= XpmReturnAllocPixels
;
3875 #ifdef XpmAllocCloseColors
3876 attrs
.alloc_close_colors
= 1;
3877 attrs
.valuemask
|= XpmAllocCloseColors
;
3878 #else /* not XpmAllocCloseColors */
3879 attrs
.closeness
= 600;
3880 attrs
.valuemask
|= XpmCloseness
;
3881 #endif /* not XpmAllocCloseColors */
3882 #endif /* ALLOC_XPM_COLORS */
3883 #ifdef ALLOC_XPM_COLORS
3884 xpm_init_color_cache (f
, &attrs
);
3887 /* If image specification contains symbolic color definitions, add
3888 these to `attrs'. */
3889 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3890 if (CONSP (color_symbols
))
3893 XpmColorSymbol
*xpm_syms
;
3896 attrs
.valuemask
|= XpmColorSymbols
;
3898 /* Count number of symbols. */
3899 attrs
.numsymbols
= 0;
3900 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3903 /* Allocate an XpmColorSymbol array. */
3904 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3905 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3906 bzero (xpm_syms
, size
);
3907 attrs
.colorsymbols
= xpm_syms
;
3909 /* Fill the color symbol array. */
3910 for (tail
= color_symbols
, i
= 0;
3912 ++i
, tail
= XCDR (tail
))
3914 Lisp_Object name
= XCAR (XCAR (tail
));
3915 Lisp_Object color
= XCDR (XCAR (tail
));
3916 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3917 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3918 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3919 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3923 /* Create a pixmap for the image, either from a file, or from a
3924 string buffer containing data in the same format as an XPM file. */
3925 #ifdef ALLOC_XPM_COLORS
3926 xpm_init_color_cache (f
, &attrs
);
3929 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3933 HDC frame_dc
= get_frame_dc (f
);
3934 hdc
= CreateCompatibleDC (frame_dc
);
3935 release_frame_dc (f
, frame_dc
);
3937 #endif /* HAVE_NTGUI */
3939 if (STRINGP (specified_file
))
3941 Lisp_Object file
= x_find_image_file (specified_file
);
3942 if (!STRINGP (file
))
3944 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3949 /* XpmReadFileToPixmap is not available in the Windows port of
3950 libxpm. But XpmReadFileToImage almost does what we want. */
3951 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3952 &xpm_image
, &xpm_mask
,
3955 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3956 SDATA (file
), &img
->pixmap
, &img
->mask
,
3958 #endif /* HAVE_NTGUI */
3962 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3964 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3965 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3966 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3967 &xpm_image
, &xpm_mask
,
3970 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3972 &img
->pixmap
, &img
->mask
,
3974 #endif /* HAVE_NTGUI */
3977 if (rc
== XpmSuccess
)
3979 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3980 img
->colors
= colors_in_color_table (&img
->ncolors
);
3981 #else /* not ALLOC_XPM_COLORS */
3985 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3986 plus some duplicate attributes. */
3987 if (xpm_image
&& xpm_image
->bitmap
)
3989 img
->pixmap
= xpm_image
->bitmap
;
3990 /* XImageFree in libXpm frees XImage struct without destroying
3991 the bitmap, which is what we want. */
3992 fn_XImageFree (xpm_image
);
3994 if (xpm_mask
&& xpm_mask
->bitmap
)
3996 /* The mask appears to be inverted compared with what we expect.
3997 TODO: invert our expectations. See other places where we
3998 have to invert bits because our idea of masks is backwards. */
4000 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
4002 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
4003 SelectObject (hdc
, old_obj
);
4005 img
->mask
= xpm_mask
->bitmap
;
4006 fn_XImageFree (xpm_mask
);
4011 #endif /* HAVE_NTGUI */
4013 /* Remember allocated colors. */
4014 img
->ncolors
= attrs
.nalloc_pixels
;
4015 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
4016 * sizeof *img
->colors
);
4017 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
4019 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
4020 #ifdef DEBUG_X_COLORS
4021 register_color (img
->colors
[i
]);
4024 #endif /* not ALLOC_XPM_COLORS */
4026 img
->width
= attrs
.width
;
4027 img
->height
= attrs
.height
;
4028 xassert (img
->width
> 0 && img
->height
> 0);
4030 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4032 fn_XpmFreeAttributes (&attrs
);
4034 XpmFreeAttributes (&attrs
);
4035 #endif /* HAVE_NTGUI */
4041 #endif /* HAVE_NTGUI */
4046 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
4049 case XpmFileInvalid
:
4050 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4054 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4057 case XpmColorFailed
:
4058 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
4062 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
4067 #ifdef ALLOC_XPM_COLORS
4068 xpm_free_color_cache ();
4070 return rc
== XpmSuccess
;
4073 #endif /* HAVE_XPM */
4077 /* XPM support functions for Mac OS where libxpm is not available.
4078 Only XPM version 3 (without any extensions) is supported. */
4080 static int xpm_scan
P_ ((unsigned char **, unsigned char *,
4081 unsigned char **, int *));
4082 static Lisp_Object xpm_make_color_table_v
4083 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
4084 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
4085 static void xpm_put_color_table_v
P_ ((Lisp_Object
, unsigned char *,
4087 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
4088 unsigned char *, int));
4089 static Lisp_Object xpm_make_color_table_h
4090 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
4091 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
4092 static void xpm_put_color_table_h
P_ ((Lisp_Object
, unsigned char *,
4094 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
4095 unsigned char *, int));
4096 static int xpm_str_to_color_key
P_ ((char *));
4097 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
4098 unsigned char *, unsigned char *));
4100 /* Tokens returned from xpm_scan. */
4109 /* Scan an XPM data and return a character (< 256) or a token defined
4110 by enum xpm_token above. *S and END are the start (inclusive) and
4111 the end (exclusive) addresses of the data, respectively. Advance
4112 *S while scanning. If token is either XPM_TK_IDENT or
4113 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4114 length of the corresponding token, respectively. */
4117 xpm_scan (s
, end
, beg
, len
)
4118 unsigned char **s
, *end
, **beg
;
4125 /* Skip white-space. */
4126 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4129 /* gnus-pointer.xpm uses '-' in its identifier.
4130 sb-dir-plus.xpm uses '+' in its identifier. */
4131 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4135 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4138 return XPM_TK_IDENT
;
4143 while (*s
< end
&& **s
!= '"')
4148 return XPM_TK_STRING
;
4152 if (*s
< end
&& **s
== '*')
4154 /* C-style comment. */
4158 while (*s
< end
&& *(*s
)++ != '*')
4161 while (*s
< end
&& **s
!= '/');
4175 /* Functions for color table lookup in XPM data. A Key is a string
4176 specifying the color of each pixel in XPM data. A value is either
4177 an integer that specifies a pixel color, Qt that specifies
4178 transparency, or Qnil for the unspecified color. If the length of
4179 the key string is one, a vector is used as a table. Otherwise, a
4180 hash table is used. */
4183 xpm_make_color_table_v (put_func
, get_func
)
4184 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4185 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
4187 *put_func
= xpm_put_color_table_v
;
4188 *get_func
= xpm_get_color_table_v
;
4189 return Fmake_vector (make_number (256), Qnil
);
4193 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4194 Lisp_Object color_table
;
4195 unsigned char *chars_start
;
4199 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4203 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4204 Lisp_Object color_table
;
4205 unsigned char *chars_start
;
4208 return XVECTOR (color_table
)->contents
[*chars_start
];
4212 xpm_make_color_table_h (put_func
, get_func
)
4213 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4214 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
4216 *put_func
= xpm_put_color_table_h
;
4217 *get_func
= xpm_get_color_table_h
;
4218 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4219 make_float (DEFAULT_REHASH_SIZE
),
4220 make_float (DEFAULT_REHASH_THRESHOLD
),
4225 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4226 Lisp_Object color_table
;
4227 unsigned char *chars_start
;
4231 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4233 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4235 hash_lookup (table
, chars
, &hash_code
);
4236 hash_put (table
, chars
, color
, hash_code
);
4240 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4241 Lisp_Object color_table
;
4242 unsigned char *chars_start
;
4245 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4246 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4249 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4252 enum xpm_color_key
{
4260 static char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4263 xpm_str_to_color_key (s
)
4269 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4271 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4277 xpm_load_image (f
, img
, contents
, end
)
4280 unsigned char *contents
, *end
;
4282 unsigned char *s
= contents
, *beg
, *str
;
4283 unsigned char buffer
[BUFSIZ
];
4284 int width
, height
, x
, y
;
4285 int num_colors
, chars_per_pixel
;
4287 void (*put_color_table
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4288 Lisp_Object (*get_color_table
) (Lisp_Object
, unsigned char *, int);
4289 Lisp_Object frame
, color_symbols
, color_table
;
4290 int best_key
, have_mask
= 0;
4291 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4294 LA1 = xpm_scan (&s, end, &beg, &len)
4296 #define expect(TOKEN) \
4297 if (LA1 != (TOKEN)) \
4302 #define expect_ident(IDENT) \
4303 if (LA1 == XPM_TK_IDENT \
4304 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4309 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4313 expect_ident ("static");
4314 expect_ident ("char");
4316 expect (XPM_TK_IDENT
);
4321 expect (XPM_TK_STRING
);
4324 memcpy (buffer
, beg
, len
);
4326 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4327 &num_colors
, &chars_per_pixel
) != 4
4328 || width
<= 0 || height
<= 0
4329 || num_colors
<= 0 || chars_per_pixel
<= 0)
4332 if (!check_image_size (f
, width
, height
))
4334 image_error ("Invalid image size", Qnil
, Qnil
);
4340 XSETFRAME (frame
, f
);
4341 if (!NILP (Fxw_display_color_p (frame
)))
4342 best_key
= XPM_COLOR_KEY_C
;
4343 else if (!NILP (Fx_display_grayscale_p (frame
)))
4344 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4345 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4347 best_key
= XPM_COLOR_KEY_M
;
4349 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4350 if (chars_per_pixel
== 1)
4351 color_table
= xpm_make_color_table_v (&put_color_table
,
4354 color_table
= xpm_make_color_table_h (&put_color_table
,
4357 while (num_colors
-- > 0)
4359 unsigned char *color
, *max_color
;
4360 int key
, next_key
, max_key
= 0;
4361 Lisp_Object symbol_color
= Qnil
, color_val
;
4364 expect (XPM_TK_STRING
);
4365 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4367 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4368 buffer
[len
- chars_per_pixel
] = '\0';
4370 str
= strtok (buffer
, " \t");
4373 key
= xpm_str_to_color_key (str
);
4378 color
= strtok (NULL
, " \t");
4382 while ((str
= strtok (NULL
, " \t")) != NULL
)
4384 next_key
= xpm_str_to_color_key (str
);
4387 color
[strlen (color
)] = ' ';
4390 if (key
== XPM_COLOR_KEY_S
)
4392 if (NILP (symbol_color
))
4393 symbol_color
= build_string (color
);
4395 else if (max_key
< key
&& key
<= best_key
)
4405 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4407 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4409 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4411 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4413 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4415 color_val
= make_number (cdef
.pixel
);
4418 if (NILP (color_val
) && max_key
> 0)
4420 if (xstricmp (max_color
, "None") == 0)
4422 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4423 color_val
= make_number (cdef
.pixel
);
4425 if (!NILP (color_val
))
4426 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4431 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4432 &ximg
, &img
->pixmap
)
4433 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4434 &mask_img
, &img
->mask
))
4436 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4440 for (y
= 0; y
< height
; y
++)
4442 expect (XPM_TK_STRING
);
4444 if (len
< width
* chars_per_pixel
)
4446 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4448 Lisp_Object color_val
=
4449 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4451 XPutPixel (ximg
, x
, y
,
4452 (INTEGERP (color_val
) ? XINT (color_val
)
4453 : FRAME_FOREGROUND_PIXEL (f
)));
4454 XPutPixel (mask_img
, x
, y
,
4455 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4456 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4463 img
->height
= height
;
4465 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4466 x_destroy_x_image (ximg
);
4469 /* Fill in the background_transparent field while we have the
4471 image_background_transparent (img
, f
, mask_img
);
4473 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4474 x_destroy_x_image (mask_img
);
4478 x_destroy_x_image (mask_img
);
4479 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4480 img
->mask
= NO_PIXMAP
;
4486 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4488 x_destroy_x_image (ximg
);
4489 x_destroy_x_image (mask_img
);
4490 x_clear_image (f
, img
);
4504 Lisp_Object file_name
;
4506 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4507 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4508 if (STRINGP (file_name
))
4511 unsigned char *contents
;
4513 struct gcpro gcpro1
;
4515 file
= x_find_image_file (file_name
);
4517 if (!STRINGP (file
))
4519 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4524 contents
= slurp_file (SDATA (file
), &size
);
4525 if (contents
== NULL
)
4527 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4532 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4540 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4541 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4542 SDATA (data
) + SBYTES (data
));
4552 /***********************************************************************
4554 ***********************************************************************/
4556 #ifdef COLOR_TABLE_SUPPORT
4558 /* An entry in the color table mapping an RGB color to a pixel color. */
4563 unsigned long pixel
;
4565 /* Next in color table collision list. */
4566 struct ct_color
*next
;
4569 /* The bucket vector size to use. Must be prime. */
4573 /* Value is a hash of the RGB color given by R, G, and B. */
4575 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4577 /* The color hash table. */
4579 struct ct_color
**ct_table
;
4581 /* Number of entries in the color table. */
4583 int ct_colors_allocated
;
4585 /* Initialize the color table. */
4590 int size
= CT_SIZE
* sizeof (*ct_table
);
4591 ct_table
= (struct ct_color
**) xmalloc (size
);
4592 bzero (ct_table
, size
);
4593 ct_colors_allocated
= 0;
4597 /* Free memory associated with the color table. */
4603 struct ct_color
*p
, *next
;
4605 for (i
= 0; i
< CT_SIZE
; ++i
)
4606 for (p
= ct_table
[i
]; p
; p
= next
)
4617 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4618 entry for that color already is in the color table, return the
4619 pixel color of that entry. Otherwise, allocate a new color for R,
4620 G, B, and make an entry in the color table. */
4622 static unsigned long
4623 lookup_rgb_color (f
, r
, g
, b
)
4627 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4628 int i
= hash
% CT_SIZE
;
4630 Display_Info
*dpyinfo
;
4632 /* Handle TrueColor visuals specially, which improves performance by
4633 two orders of magnitude. Freeing colors on TrueColor visuals is
4634 a nop, and pixel colors specify RGB values directly. See also
4635 the Xlib spec, chapter 3.1. */
4636 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4637 if (dpyinfo
->red_bits
> 0)
4639 unsigned long pr
, pg
, pb
;
4641 /* Apply gamma-correction like normal color allocation does. */
4645 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4646 gamma_correct (f
, &color
);
4647 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4650 /* Scale down RGB values to the visual's bits per RGB, and shift
4651 them to the right position in the pixel color. Note that the
4652 original RGB values are 16-bit values, as usual in X. */
4653 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4654 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4655 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4657 /* Assemble the pixel color. */
4658 return pr
| pg
| pb
;
4661 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4662 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4668 #ifdef HAVE_X_WINDOWS
4677 cmap
= FRAME_X_COLORMAP (f
);
4678 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4681 ++ct_colors_allocated
;
4682 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4686 p
->pixel
= color
.pixel
;
4687 p
->next
= ct_table
[i
];
4691 return FRAME_FOREGROUND_PIXEL (f
);
4696 color
= PALETTERGB (r
, g
, b
);
4698 color
= RGB_TO_ULONG (r
, g
, b
);
4699 #endif /* HAVE_NTGUI */
4700 ++ct_colors_allocated
;
4701 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4706 p
->next
= ct_table
[i
];
4708 #endif /* HAVE_X_WINDOWS */
4716 /* Look up pixel color PIXEL which is used on frame F in the color
4717 table. If not already present, allocate it. Value is PIXEL. */
4719 static unsigned long
4720 lookup_pixel_color (f
, pixel
)
4722 unsigned long pixel
;
4724 int i
= pixel
% CT_SIZE
;
4727 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4728 if (p
->pixel
== pixel
)
4737 #ifdef HAVE_X_WINDOWS
4738 cmap
= FRAME_X_COLORMAP (f
);
4739 color
.pixel
= pixel
;
4740 x_query_color (f
, &color
);
4741 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4744 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4745 color
.pixel
= pixel
;
4746 XQueryColor (NULL
, cmap
, &color
);
4747 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4749 #endif /* HAVE_X_WINDOWS */
4753 ++ct_colors_allocated
;
4755 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4760 p
->next
= ct_table
[i
];
4764 return FRAME_FOREGROUND_PIXEL (f
);
4770 /* Value is a vector of all pixel colors contained in the color table,
4771 allocated via xmalloc. Set *N to the number of colors. */
4773 static unsigned long *
4774 colors_in_color_table (n
)
4779 unsigned long *colors
;
4781 if (ct_colors_allocated
== 0)
4788 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4790 *n
= ct_colors_allocated
;
4792 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4793 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4794 colors
[j
++] = p
->pixel
;
4800 #else /* COLOR_TABLE_SUPPORT */
4802 static unsigned long
4803 lookup_rgb_color (f
, r
, g
, b
)
4807 unsigned long pixel
;
4810 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4811 gamma_correct (f
, &pixel
);
4815 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4816 #endif /* HAVE_NTGUI */
4825 #endif /* COLOR_TABLE_SUPPORT */
4828 /***********************************************************************
4830 ***********************************************************************/
4832 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4833 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4834 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4837 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4838 #endif /* HAVE_NTGUI */
4840 /* Non-zero means draw a cross on images having `:conversion
4843 int cross_disabled_images
;
4845 /* Edge detection matrices for different edge-detection
4848 static int emboss_matrix
[9] = {
4850 2, -1, 0, /* y - 1 */
4852 0, 1, -2 /* y + 1 */
4855 static int laplace_matrix
[9] = {
4857 1, 0, 0, /* y - 1 */
4859 0, 0, -1 /* y + 1 */
4862 /* Value is the intensity of the color whose red/green/blue values
4865 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4868 /* On frame F, return an array of XColor structures describing image
4869 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4870 non-zero means also fill the red/green/blue members of the XColor
4871 structures. Value is a pointer to the array of XColors structures,
4872 allocated with xmalloc; it must be freed by the caller. */
4875 x_to_xcolors (f
, img
, rgb_p
)
4882 XImagePtr_or_DC ximg
;
4886 #endif /* HAVE_NTGUI */
4888 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4891 /* Get the X image IMG->pixmap. */
4892 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4893 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4895 /* Load the image into a memory device context. */
4896 hdc
= get_frame_dc (f
);
4897 ximg
= CreateCompatibleDC (hdc
);
4898 release_frame_dc (f
, hdc
);
4899 prev
= SelectObject (ximg
, img
->pixmap
);
4900 #endif /* HAVE_NTGUI */
4902 /* Fill the `pixel' members of the XColor array. I wished there
4903 were an easy and portable way to circumvent XGetPixel. */
4905 for (y
= 0; y
< img
->height
; ++y
)
4909 #ifdef HAVE_X_WINDOWS
4910 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4911 p
->pixel
= XGetPixel (ximg
, x
, y
);
4913 x_query_colors (f
, row
, img
->width
);
4917 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4919 /* W32_TODO: palette support needed here? */
4920 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4924 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4925 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4926 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4929 p
->red
= 256 * GetRValue (p
->pixel
);
4930 p
->green
= 256 * GetGValue (p
->pixel
);
4931 p
->blue
= 256 * GetBValue (p
->pixel
);
4932 #endif /* HAVE_NTGUI */
4935 #endif /* HAVE_X_WINDOWS */
4938 Destroy_Image (ximg
, prev
);
4945 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4946 created with CreateDIBSection, with the pointer to the bit values
4947 stored in ximg->data. */
4949 static void XPutPixel (ximg
, x
, y
, color
)
4954 int width
= ximg
->info
.bmiHeader
.biWidth
;
4955 int height
= ximg
->info
.bmiHeader
.biHeight
;
4956 unsigned char * pixel
;
4958 /* True color images. */
4959 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4961 int rowbytes
= width
* 3;
4962 /* Ensure scanlines are aligned on 4 byte boundaries. */
4964 rowbytes
+= 4 - (rowbytes
% 4);
4966 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4967 /* Windows bitmaps are in BGR order. */
4968 *pixel
= GetBValue (color
);
4969 *(pixel
+ 1) = GetGValue (color
);
4970 *(pixel
+ 2) = GetRValue (color
);
4972 /* Monochrome images. */
4973 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4975 int rowbytes
= width
/ 8;
4976 /* Ensure scanlines are aligned on 4 byte boundaries. */
4978 rowbytes
+= 4 - (rowbytes
% 4);
4979 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4980 /* Filter out palette info. */
4981 if (color
& 0x00ffffff)
4982 *pixel
= *pixel
| (1 << x
% 8);
4984 *pixel
= *pixel
& ~(1 << x
% 8);
4987 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4990 #endif /* HAVE_NTGUI */
4992 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4993 RGB members are set. F is the frame on which this all happens.
4994 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4997 x_from_xcolors (f
, img
, colors
)
5007 init_color_table ();
5009 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
5012 for (y
= 0; y
< img
->height
; ++y
)
5013 for (x
= 0; x
< img
->width
; ++x
, ++p
)
5015 unsigned long pixel
;
5016 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
5017 XPutPixel (oimg
, x
, y
, pixel
);
5021 x_clear_image_1 (f
, img
, 1, 0, 1);
5023 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
5024 x_destroy_x_image (oimg
);
5025 img
->pixmap
= pixmap
;
5026 #ifdef COLOR_TABLE_SUPPORT
5027 img
->colors
= colors_in_color_table (&img
->ncolors
);
5028 free_color_table ();
5029 #endif /* COLOR_TABLE_SUPPORT */
5033 /* On frame F, perform edge-detection on image IMG.
5035 MATRIX is a nine-element array specifying the transformation
5036 matrix. See emboss_matrix for an example.
5038 COLOR_ADJUST is a color adjustment added to each pixel of the
5042 x_detect_edges (f
, img
, matrix
, color_adjust
)
5045 int matrix
[9], color_adjust
;
5047 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5051 for (i
= sum
= 0; i
< 9; ++i
)
5052 sum
+= abs (matrix
[i
]);
5054 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5056 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
5058 for (y
= 0; y
< img
->height
; ++y
)
5060 p
= COLOR (new, 0, y
);
5061 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5062 p
= COLOR (new, img
->width
- 1, y
);
5063 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5066 for (x
= 1; x
< img
->width
- 1; ++x
)
5068 p
= COLOR (new, x
, 0);
5069 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5070 p
= COLOR (new, x
, img
->height
- 1);
5071 p
->red
= p
->green
= p
->blue
= 0xffff/2;
5074 for (y
= 1; y
< img
->height
- 1; ++y
)
5076 p
= COLOR (new, 1, y
);
5078 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
5080 int r
, g
, b
, y1
, x1
;
5083 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
5084 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
5087 XColor
*t
= COLOR (colors
, x1
, y1
);
5088 r
+= matrix
[i
] * t
->red
;
5089 g
+= matrix
[i
] * t
->green
;
5090 b
+= matrix
[i
] * t
->blue
;
5093 r
= (r
/ sum
+ color_adjust
) & 0xffff;
5094 g
= (g
/ sum
+ color_adjust
) & 0xffff;
5095 b
= (b
/ sum
+ color_adjust
) & 0xffff;
5096 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
5101 x_from_xcolors (f
, img
, new);
5107 /* Perform the pre-defined `emboss' edge-detection on image IMG
5115 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5119 /* Transform image IMG which is used on frame F with a Laplace
5120 edge-detection algorithm. The result is an image that can be used
5121 to draw disabled buttons, for example. */
5128 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5132 /* Perform edge-detection on image IMG on frame F, with specified
5133 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5135 MATRIX must be either
5137 - a list of at least 9 numbers in row-major form
5138 - a vector of at least 9 numbers
5140 COLOR_ADJUST nil means use a default; otherwise it must be a
5144 x_edge_detection (f
, img
, matrix
, color_adjust
)
5147 Lisp_Object matrix
, color_adjust
;
5155 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5156 ++i
, matrix
= XCDR (matrix
))
5157 trans
[i
] = XFLOATINT (XCAR (matrix
));
5159 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5161 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5162 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5165 if (NILP (color_adjust
))
5166 color_adjust
= make_number (0xffff / 2);
5168 if (i
== 9 && NUMBERP (color_adjust
))
5169 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5173 /* Transform image IMG on frame F so that it looks disabled. */
5176 x_disable_image (f
, img
)
5180 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5182 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5184 int n_planes
= dpyinfo
->n_planes
;
5185 #endif /* HAVE_NTGUI */
5189 /* Color (or grayscale). Convert to gray, and equalize. Just
5190 drawing such images with a stipple can look very odd, so
5191 we're using this method instead. */
5192 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5194 const int h
= 15000;
5195 const int l
= 30000;
5197 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5201 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5202 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5203 p
->red
= p
->green
= p
->blue
= i2
;
5206 x_from_xcolors (f
, img
, colors
);
5209 /* Draw a cross over the disabled image, if we must or if we
5211 if (n_planes
< 2 || cross_disabled_images
)
5214 Display
*dpy
= FRAME_X_DISPLAY (f
);
5218 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
5219 #define MaskForeground(f) PIX_MASK_DRAW
5221 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
5222 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5225 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
5226 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5227 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5228 img
->width
- 1, img
->height
- 1);
5229 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5235 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
5236 XSetForeground (dpy
, gc
, MaskForeground (f
));
5237 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5238 img
->width
- 1, img
->height
- 1);
5239 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5247 hdc
= get_frame_dc (f
);
5248 bmpdc
= CreateCompatibleDC (hdc
);
5249 release_frame_dc (f
, hdc
);
5251 prev
= SelectObject (bmpdc
, img
->pixmap
);
5253 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5254 MoveToEx (bmpdc
, 0, 0, NULL
);
5255 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5256 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5257 LineTo (bmpdc
, img
->width
- 1, 0);
5261 SelectObject (bmpdc
, img
->mask
);
5262 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5263 MoveToEx (bmpdc
, 0, 0, NULL
);
5264 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5265 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5266 LineTo (bmpdc
, img
->width
- 1, 0);
5268 SelectObject (bmpdc
, prev
);
5270 #endif /* HAVE_NTGUI */
5275 /* Build a mask for image IMG which is used on frame F. FILE is the
5276 name of an image file, for error messages. HOW determines how to
5277 determine the background color of IMG. If it is a list '(R G B)',
5278 with R, G, and B being integers >= 0, take that as the color of the
5279 background. Otherwise, determine the background color of IMG
5280 heuristically. Value is non-zero if successful. */
5283 x_build_heuristic_mask (f
, img
, how
)
5288 XImagePtr_or_DC ximg
;
5296 #endif /* HAVE_NTGUI */
5297 int x
, y
, rc
, use_img_background
;
5298 unsigned long bg
= 0;
5302 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5303 img
->mask
= NO_PIXMAP
;
5304 img
->background_transparent_valid
= 0;
5308 /* Create an image and pixmap serving as mask. */
5309 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5310 &mask_img
, &img
->mask
);
5314 /* Get the X image of IMG->pixmap. */
5315 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5316 img
->width
, img
->height
,
5319 /* Create the bit array serving as mask. */
5320 row_width
= (img
->width
+ 7) / 8;
5321 mask_img
= xmalloc (row_width
* img
->height
);
5322 bzero (mask_img
, row_width
* img
->height
);
5324 /* Create a memory device context for IMG->pixmap. */
5325 frame_dc
= get_frame_dc (f
);
5326 ximg
= CreateCompatibleDC (frame_dc
);
5327 release_frame_dc (f
, frame_dc
);
5328 prev
= SelectObject (ximg
, img
->pixmap
);
5329 #endif /* HAVE_NTGUI */
5331 /* Determine the background color of ximg. If HOW is `(R G B)'
5332 take that as color. Otherwise, use the image's background color. */
5333 use_img_background
= 1;
5339 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5341 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5345 if (i
== 3 && NILP (how
))
5347 char color_name
[30];
5348 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5351 0x00ffffff & /* Filter out palette info. */
5352 #endif /* HAVE_NTGUI */
5353 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5354 use_img_background
= 0;
5358 if (use_img_background
)
5359 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
5361 /* Set all bits in mask_img to 1 whose color in ximg is different
5362 from the background color bg. */
5364 for (y
= 0; y
< img
->height
; ++y
)
5365 for (x
= 0; x
< img
->width
; ++x
)
5366 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5367 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5369 /* Fill in the background_transparent field while we have the mask handy. */
5370 image_background_transparent (img
, f
, mask_img
);
5372 /* Put mask_img into img->mask. */
5373 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5374 x_destroy_x_image (mask_img
);
5377 for (y
= 0; y
< img
->height
; ++y
)
5378 for (x
= 0; x
< img
->width
; ++x
)
5380 COLORREF p
= GetPixel (ximg
, x
, y
);
5382 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5385 /* Create the mask image. */
5386 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5388 /* Fill in the background_transparent field while we have the mask handy. */
5389 SelectObject (ximg
, img
->mask
);
5390 image_background_transparent (img
, f
, ximg
);
5392 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5394 #endif /* HAVE_NTGUI */
5396 Destroy_Image (ximg
, prev
);
5402 /***********************************************************************
5403 PBM (mono, gray, color)
5404 ***********************************************************************/
5406 static int pbm_image_p
P_ ((Lisp_Object object
));
5407 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5408 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5410 /* The symbol `pbm' identifying images of this type. */
5414 /* Indices of image specification fields in gs_format, below. */
5416 enum pbm_keyword_index
5432 /* Vector of image_keyword structures describing the format
5433 of valid user-defined image specifications. */
5435 static struct image_keyword pbm_format
[PBM_LAST
] =
5437 {":type", IMAGE_SYMBOL_VALUE
, 1},
5438 {":file", IMAGE_STRING_VALUE
, 0},
5439 {":data", IMAGE_STRING_VALUE
, 0},
5440 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5441 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5442 {":relief", IMAGE_INTEGER_VALUE
, 0},
5443 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5444 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5445 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5446 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5447 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5450 /* Structure describing the image type `pbm'. */
5452 static struct image_type pbm_type
=
5462 /* Return non-zero if OBJECT is a valid PBM image specification. */
5465 pbm_image_p (object
)
5468 struct image_keyword fmt
[PBM_LAST
];
5470 bcopy (pbm_format
, fmt
, sizeof fmt
);
5472 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5475 /* Must specify either :data or :file. */
5476 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5480 /* Scan a decimal number from *S and return it. Advance *S while
5481 reading the number. END is the end of the string. Value is -1 at
5485 pbm_scan_number (s
, end
)
5486 unsigned char **s
, *end
;
5488 int c
= 0, val
= -1;
5492 /* Skip white-space. */
5493 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5498 /* Skip comment to end of line. */
5499 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5502 else if (isdigit (c
))
5504 /* Read decimal number. */
5506 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5507 val
= 10 * val
+ c
- '0';
5519 #if 0 /* Unused. ++kfs */
5521 /* Read FILE into memory. Value is a pointer to a buffer allocated
5522 with xmalloc holding FILE's contents. Value is null if an error
5523 occurred. *SIZE is set to the size of the file. */
5526 pbm_read_file (file
, size
)
5534 if (stat (SDATA (file
), &st
) == 0
5535 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5536 && (buf
= (char *) xmalloc (st
.st_size
),
5537 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5556 #endif /* HAVE_NTGUI */
5558 /* Load PBM image IMG for use on frame F. */
5566 int width
, height
, max_color_idx
= 0;
5568 Lisp_Object file
, specified_file
;
5569 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5570 struct gcpro gcpro1
;
5571 unsigned char *contents
= NULL
;
5572 unsigned char *end
, *p
;
5575 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5579 if (STRINGP (specified_file
))
5581 file
= x_find_image_file (specified_file
);
5582 if (!STRINGP (file
))
5584 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5589 contents
= slurp_file (SDATA (file
), &size
);
5590 if (contents
== NULL
)
5592 image_error ("Error reading `%s'", file
, Qnil
);
5598 end
= contents
+ size
;
5603 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5605 end
= p
+ SBYTES (data
);
5608 /* Check magic number. */
5609 if (end
- p
< 2 || *p
++ != 'P')
5611 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5621 raw_p
= 0, type
= PBM_MONO
;
5625 raw_p
= 0, type
= PBM_GRAY
;
5629 raw_p
= 0, type
= PBM_COLOR
;
5633 raw_p
= 1, type
= PBM_MONO
;
5637 raw_p
= 1, type
= PBM_GRAY
;
5641 raw_p
= 1, type
= PBM_COLOR
;
5645 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5649 /* Read width, height, maximum color-component. Characters
5650 starting with `#' up to the end of a line are ignored. */
5651 width
= pbm_scan_number (&p
, end
);
5652 height
= pbm_scan_number (&p
, end
);
5654 if (type
!= PBM_MONO
)
5656 max_color_idx
= pbm_scan_number (&p
, end
);
5657 if (raw_p
&& max_color_idx
> 255)
5658 max_color_idx
= 255;
5661 if (!check_image_size (f
, width
, height
)
5662 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5665 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5666 &ximg
, &img
->pixmap
))
5669 /* Initialize the color hash table. */
5670 init_color_table ();
5672 if (type
== PBM_MONO
)
5675 struct image_keyword fmt
[PBM_LAST
];
5676 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5677 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5679 /* Parse the image specification. */
5680 bcopy (pbm_format
, fmt
, sizeof fmt
);
5681 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5683 /* Get foreground and background colors, maybe allocate colors. */
5684 if (fmt
[PBM_FOREGROUND
].count
5685 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5686 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5687 if (fmt
[PBM_BACKGROUND
].count
5688 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5690 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5691 img
->background
= bg
;
5692 img
->background_valid
= 1;
5695 for (y
= 0; y
< height
; ++y
)
5696 for (x
= 0; x
< width
; ++x
)
5706 g
= pbm_scan_number (&p
, end
);
5708 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5713 for (y
= 0; y
< height
; ++y
)
5714 for (x
= 0; x
< width
; ++x
)
5718 if (type
== PBM_GRAY
)
5719 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5728 r
= pbm_scan_number (&p
, end
);
5729 g
= pbm_scan_number (&p
, end
);
5730 b
= pbm_scan_number (&p
, end
);
5733 if (r
< 0 || g
< 0 || b
< 0)
5735 x_destroy_x_image (ximg
);
5736 image_error ("Invalid pixel value in image `%s'",
5741 /* RGB values are now in the range 0..max_color_idx.
5742 Scale this to the range 0..0xffff supported by X. */
5743 r
= (double) r
* 65535 / max_color_idx
;
5744 g
= (double) g
* 65535 / max_color_idx
;
5745 b
= (double) b
* 65535 / max_color_idx
;
5746 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5750 #ifdef COLOR_TABLE_SUPPORT
5751 /* Store in IMG->colors the colors allocated for the image, and
5752 free the color table. */
5753 img
->colors
= colors_in_color_table (&img
->ncolors
);
5754 free_color_table ();
5755 #endif /* COLOR_TABLE_SUPPORT */
5758 img
->height
= height
;
5760 /* Maybe fill in the background field while we have ximg handy. */
5762 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5763 /* Casting avoids a GCC warning. */
5764 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5766 /* Put the image into a pixmap. */
5767 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5768 x_destroy_x_image (ximg
);
5770 /* X and W32 versions did it here, MAC version above. ++kfs
5772 img->height = height; */
5780 /***********************************************************************
5782 ***********************************************************************/
5784 #if defined (HAVE_PNG) || defined (MAC_OS)
5786 /* Function prototypes. */
5788 static int png_image_p
P_ ((Lisp_Object object
));
5789 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5791 /* The symbol `png' identifying images of this type. */
5795 /* Indices of image specification fields in png_format, below. */
5797 enum png_keyword_index
5812 /* Vector of image_keyword structures describing the format
5813 of valid user-defined image specifications. */
5815 static struct image_keyword png_format
[PNG_LAST
] =
5817 {":type", IMAGE_SYMBOL_VALUE
, 1},
5818 {":data", IMAGE_STRING_VALUE
, 0},
5819 {":file", IMAGE_STRING_VALUE
, 0},
5820 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5821 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5822 {":relief", IMAGE_INTEGER_VALUE
, 0},
5823 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5824 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5825 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5826 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5829 /* Structure describing the image type `png'. */
5831 static struct image_type png_type
=
5840 /* Return non-zero if OBJECT is a valid PNG image specification. */
5843 png_image_p (object
)
5846 struct image_keyword fmt
[PNG_LAST
];
5847 bcopy (png_format
, fmt
, sizeof fmt
);
5849 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5852 /* Must specify either the :data or :file keyword. */
5853 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5856 #endif /* HAVE_PNG || MAC_OS */
5861 #if defined HAVE_LIBPNG_PNG_H
5862 # include <libpng/png.h>
5868 /* PNG library details. */
5870 DEF_IMGLIB_FN (png_get_io_ptr
);
5871 DEF_IMGLIB_FN (png_check_sig
);
5872 DEF_IMGLIB_FN (png_create_read_struct
);
5873 DEF_IMGLIB_FN (png_create_info_struct
);
5874 DEF_IMGLIB_FN (png_destroy_read_struct
);
5875 DEF_IMGLIB_FN (png_set_read_fn
);
5876 DEF_IMGLIB_FN (png_set_sig_bytes
);
5877 DEF_IMGLIB_FN (png_read_info
);
5878 DEF_IMGLIB_FN (png_get_IHDR
);
5879 DEF_IMGLIB_FN (png_get_valid
);
5880 DEF_IMGLIB_FN (png_set_strip_16
);
5881 DEF_IMGLIB_FN (png_set_expand
);
5882 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5883 DEF_IMGLIB_FN (png_set_background
);
5884 DEF_IMGLIB_FN (png_get_bKGD
);
5885 DEF_IMGLIB_FN (png_read_update_info
);
5886 DEF_IMGLIB_FN (png_get_channels
);
5887 DEF_IMGLIB_FN (png_get_rowbytes
);
5888 DEF_IMGLIB_FN (png_read_image
);
5889 DEF_IMGLIB_FN (png_read_end
);
5890 DEF_IMGLIB_FN (png_error
);
5893 init_png_functions (Lisp_Object libraries
)
5897 /* Try loading libpng under probable names. */
5898 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5901 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5902 LOAD_IMGLIB_FN (library
, png_check_sig
);
5903 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5904 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5905 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5906 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5907 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5908 LOAD_IMGLIB_FN (library
, png_read_info
);
5909 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5910 LOAD_IMGLIB_FN (library
, png_get_valid
);
5911 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5912 LOAD_IMGLIB_FN (library
, png_set_expand
);
5913 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5914 LOAD_IMGLIB_FN (library
, png_set_background
);
5915 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5916 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5917 LOAD_IMGLIB_FN (library
, png_get_channels
);
5918 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5919 LOAD_IMGLIB_FN (library
, png_read_image
);
5920 LOAD_IMGLIB_FN (library
, png_read_end
);
5921 LOAD_IMGLIB_FN (library
, png_error
);
5926 #define fn_png_get_io_ptr png_get_io_ptr
5927 #define fn_png_check_sig png_check_sig
5928 #define fn_png_create_read_struct png_create_read_struct
5929 #define fn_png_create_info_struct png_create_info_struct
5930 #define fn_png_destroy_read_struct png_destroy_read_struct
5931 #define fn_png_set_read_fn png_set_read_fn
5932 #define fn_png_set_sig_bytes png_set_sig_bytes
5933 #define fn_png_read_info png_read_info
5934 #define fn_png_get_IHDR png_get_IHDR
5935 #define fn_png_get_valid png_get_valid
5936 #define fn_png_set_strip_16 png_set_strip_16
5937 #define fn_png_set_expand png_set_expand
5938 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5939 #define fn_png_set_background png_set_background
5940 #define fn_png_get_bKGD png_get_bKGD
5941 #define fn_png_read_update_info png_read_update_info
5942 #define fn_png_get_channels png_get_channels
5943 #define fn_png_get_rowbytes png_get_rowbytes
5944 #define fn_png_read_image png_read_image
5945 #define fn_png_read_end png_read_end
5946 #define fn_png_error png_error
5948 #endif /* HAVE_NTGUI */
5950 /* Error and warning handlers installed when the PNG library
5954 my_png_error (png_ptr
, msg
)
5955 png_struct
*png_ptr
;
5958 xassert (png_ptr
!= NULL
);
5959 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5960 longjmp (png_ptr
->jmpbuf
, 1);
5965 my_png_warning (png_ptr
, msg
)
5966 png_struct
*png_ptr
;
5969 xassert (png_ptr
!= NULL
);
5970 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5973 /* Memory source for PNG decoding. */
5975 struct png_memory_storage
5977 unsigned char *bytes
; /* The data */
5978 size_t len
; /* How big is it? */
5979 int index
; /* Where are we? */
5983 /* Function set as reader function when reading PNG image from memory.
5984 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5985 bytes from the input to DATA. */
5988 png_read_from_memory (png_ptr
, data
, length
)
5989 png_structp png_ptr
;
5993 struct png_memory_storage
*tbr
5994 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5996 if (length
> tbr
->len
- tbr
->index
)
5997 fn_png_error (png_ptr
, "Read error");
5999 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
6000 tbr
->index
= tbr
->index
+ length
;
6004 /* Function set as reader function when reading PNG image from a file.
6005 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6006 bytes from the input to DATA. */
6009 png_read_from_file (png_ptr
, data
, length
)
6010 png_structp png_ptr
;
6014 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
6016 if (fread (data
, 1, length
, fp
) < length
)
6017 fn_png_error (png_ptr
, "Read error");
6021 /* Load PNG image IMG for use on frame F. Value is non-zero if
6029 Lisp_Object file
, specified_file
;
6030 Lisp_Object specified_data
;
6032 XImagePtr ximg
, mask_img
= NULL
;
6033 struct gcpro gcpro1
;
6034 png_struct
*png_ptr
= NULL
;
6035 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
6036 FILE *volatile fp
= NULL
;
6038 png_byte
* volatile pixels
= NULL
;
6039 png_byte
** volatile rows
= NULL
;
6040 png_uint_32 width
, height
;
6041 int bit_depth
, color_type
, interlace_type
;
6043 png_uint_32 row_bytes
;
6045 double screen_gamma
;
6046 struct png_memory_storage tbr
; /* Data to be read */
6048 /* Find out what file to load. */
6049 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6050 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6054 if (NILP (specified_data
))
6056 file
= x_find_image_file (specified_file
);
6057 if (!STRINGP (file
))
6059 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6064 /* Open the image file. */
6065 fp
= fopen (SDATA (file
), "rb");
6068 image_error ("Cannot open image file `%s'", file
, Qnil
);
6074 /* Check PNG signature. */
6075 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6076 || !fn_png_check_sig (sig
, sizeof sig
))
6078 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6086 /* Read from memory. */
6087 tbr
.bytes
= SDATA (specified_data
);
6088 tbr
.len
= SBYTES (specified_data
);
6091 /* Check PNG signature. */
6092 if (tbr
.len
< sizeof sig
6093 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6095 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6100 /* Need to skip past the signature. */
6101 tbr
.bytes
+= sizeof (sig
);
6104 /* Initialize read and info structs for PNG lib. Casting return
6105 value avoids a GCC warning on W32. */
6106 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6111 if (fp
) fclose (fp
);
6116 /* Casting return value avoids a GCC warning on W32. */
6117 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6120 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6121 if (fp
) fclose (fp
);
6126 /* Casting return value avoids a GCC warning on W32. */
6127 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6130 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6131 if (fp
) fclose (fp
);
6136 /* Set error jump-back. We come back here when the PNG library
6137 detects an error. */
6138 if (setjmp (png_ptr
->jmpbuf
))
6142 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6145 if (fp
) fclose (fp
);
6150 /* Read image info. */
6151 if (!NILP (specified_data
))
6152 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6154 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6156 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6157 fn_png_read_info (png_ptr
, info_ptr
);
6158 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6159 &interlace_type
, NULL
, NULL
);
6161 if (!check_image_size (f
, width
, height
))
6164 /* If image contains simply transparency data, we prefer to
6165 construct a clipping mask. */
6166 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6171 /* This function is easier to write if we only have to handle
6172 one data format: RGB or RGBA with 8 bits per channel. Let's
6173 transform other formats into that format. */
6175 /* Strip more than 8 bits per channel. */
6176 if (bit_depth
== 16)
6177 fn_png_set_strip_16 (png_ptr
);
6179 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6181 fn_png_set_expand (png_ptr
);
6183 /* Convert grayscale images to RGB. */
6184 if (color_type
== PNG_COLOR_TYPE_GRAY
6185 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6186 fn_png_set_gray_to_rgb (png_ptr
);
6188 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
6190 #if 0 /* Avoid double gamma correction for PNG images. */
6191 { /* Tell the PNG lib to handle gamma correction for us. */
6194 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6195 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
6196 /* The libpng documentation says this is right in this case. */
6197 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6200 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
6201 /* Image contains gamma information. */
6202 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
6204 /* Use the standard default for the image gamma. */
6205 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
6209 /* Handle alpha channel by combining the image with a background
6210 color. Do this only if a real alpha channel is supplied. For
6211 simple transparency, we prefer a clipping mask. */
6214 png_color_16
*image_bg
;
6215 Lisp_Object specified_bg
6216 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6218 if (STRINGP (specified_bg
))
6219 /* The user specified `:background', use that. */
6221 /* W32 version incorrectly used COLORREF here!! ++kfs */
6223 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6225 png_color_16 user_bg
;
6227 bzero (&user_bg
, sizeof user_bg
);
6228 user_bg
.red
= color
.red
>> 8;
6229 user_bg
.green
= color
.green
>> 8;
6230 user_bg
.blue
= color
.blue
>> 8;
6232 fn_png_set_background (png_ptr
, &user_bg
,
6233 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6236 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
6237 /* Image contains a background color with which to
6238 combine the image. */
6239 fn_png_set_background (png_ptr
, image_bg
,
6240 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
6243 /* Image does not contain a background color with which
6244 to combine the image data via an alpha channel. Use
6245 the frame's background instead. */
6246 #ifdef HAVE_X_WINDOWS
6248 png_color_16 frame_background
;
6250 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6251 x_query_color (f
, &color
);
6253 bzero (&frame_background
, sizeof frame_background
);
6254 frame_background
.red
= color
.red
>> 8;
6255 frame_background
.green
= color
.green
>> 8;
6256 frame_background
.blue
= color
.blue
>> 8;
6257 #endif /* HAVE_X_WINDOWS */
6261 png_color_16 frame_background
;
6262 color
= FRAME_BACKGROUND_PIXEL (f
);
6263 #if 0 /* W32 TODO : Colormap support. */
6264 x_query_color (f
, &color
);
6266 bzero (&frame_background
, sizeof frame_background
);
6267 frame_background
.red
= GetRValue (color
);
6268 frame_background
.green
= GetGValue (color
);
6269 frame_background
.blue
= GetBValue (color
);
6270 #endif /* HAVE_NTGUI */
6273 unsigned long color
;
6274 png_color_16 frame_background
;
6275 color
= FRAME_BACKGROUND_PIXEL (f
);
6276 #if 0 /* MAC/W32 TODO : Colormap support. */
6277 x_query_color (f
, &color
);
6279 bzero (&frame_background
, sizeof frame_background
);
6280 frame_background
.red
= RED_FROM_ULONG (color
);
6281 frame_background
.green
= GREEN_FROM_ULONG (color
);
6282 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6285 fn_png_set_background (png_ptr
, &frame_background
,
6286 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6290 /* Update info structure. */
6291 fn_png_read_update_info (png_ptr
, info_ptr
);
6293 /* Get number of channels. Valid values are 1 for grayscale images
6294 and images with a palette, 2 for grayscale images with transparency
6295 information (alpha channel), 3 for RGB images, and 4 for RGB
6296 images with alpha channel, i.e. RGBA. If conversions above were
6297 sufficient we should only have 3 or 4 channels here. */
6298 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6299 xassert (channels
== 3 || channels
== 4);
6301 /* Number of bytes needed for one row of the image. */
6302 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6304 /* Allocate memory for the image. */
6305 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6306 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6307 for (i
= 0; i
< height
; ++i
)
6308 rows
[i
] = pixels
+ i
* row_bytes
;
6310 /* Read the entire image. */
6311 fn_png_read_image (png_ptr
, rows
);
6312 fn_png_read_end (png_ptr
, info_ptr
);
6319 /* Create the X image and pixmap. */
6320 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6324 /* Create an image and pixmap serving as mask if the PNG image
6325 contains an alpha channel. */
6328 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6329 &mask_img
, &img
->mask
))
6331 x_destroy_x_image (ximg
);
6332 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6333 img
->pixmap
= NO_PIXMAP
;
6337 /* Fill the X image and mask from PNG data. */
6338 init_color_table ();
6340 for (y
= 0; y
< height
; ++y
)
6342 png_byte
*p
= rows
[y
];
6344 for (x
= 0; x
< width
; ++x
)
6351 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6352 /* An alpha channel, aka mask channel, associates variable
6353 transparency with an image. Where other image formats
6354 support binary transparency---fully transparent or fully
6355 opaque---PNG allows up to 254 levels of partial transparency.
6356 The PNG library implements partial transparency by combining
6357 the image with a specified background color.
6359 I'm not sure how to handle this here nicely: because the
6360 background on which the image is displayed may change, for
6361 real alpha channel support, it would be necessary to create
6362 a new image for each possible background.
6364 What I'm doing now is that a mask is created if we have
6365 boolean transparency information. Otherwise I'm using
6366 the frame's background color to combine the image with. */
6371 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6377 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6378 /* Set IMG's background color from the PNG image, unless the user
6382 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6384 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6385 img
->background_valid
= 1;
6389 #ifdef COLOR_TABLE_SUPPORT
6390 /* Remember colors allocated for this image. */
6391 img
->colors
= colors_in_color_table (&img
->ncolors
);
6392 free_color_table ();
6393 #endif /* COLOR_TABLE_SUPPORT */
6396 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6401 img
->height
= height
;
6403 /* Maybe fill in the background field while we have ximg handy.
6404 Casting avoids a GCC warning. */
6405 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6407 /* Put the image into the pixmap, then free the X image and its buffer. */
6408 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6409 x_destroy_x_image (ximg
);
6411 /* Same for the mask. */
6414 /* Fill in the background_transparent field while we have the
6415 mask handy. Casting avoids a GCC warning. */
6416 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6418 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6419 x_destroy_x_image (mask_img
);
6426 #else /* HAVE_PNG */
6435 if (MyCGImageCreateWithPNGDataProvider
)
6436 return image_load_quartz2d (f
, img
, 1);
6439 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6443 #endif /* !HAVE_PNG */
6447 /***********************************************************************
6449 ***********************************************************************/
6451 #if defined (HAVE_JPEG) || defined (MAC_OS)
6453 static int jpeg_image_p
P_ ((Lisp_Object object
));
6454 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6456 /* The symbol `jpeg' identifying images of this type. */
6460 /* Indices of image specification fields in gs_format, below. */
6462 enum jpeg_keyword_index
6471 JPEG_HEURISTIC_MASK
,
6477 /* Vector of image_keyword structures describing the format
6478 of valid user-defined image specifications. */
6480 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6482 {":type", IMAGE_SYMBOL_VALUE
, 1},
6483 {":data", IMAGE_STRING_VALUE
, 0},
6484 {":file", IMAGE_STRING_VALUE
, 0},
6485 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6486 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6487 {":relief", IMAGE_INTEGER_VALUE
, 0},
6488 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6489 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6490 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6491 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6494 /* Structure describing the image type `jpeg'. */
6496 static struct image_type jpeg_type
=
6505 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6508 jpeg_image_p (object
)
6511 struct image_keyword fmt
[JPEG_LAST
];
6513 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6515 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6518 /* Must specify either the :data or :file keyword. */
6519 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6522 #endif /* HAVE_JPEG || MAC_OS */
6526 /* Work around a warning about HAVE_STDLIB_H being redefined in
6528 #ifdef HAVE_STDLIB_H
6529 #define HAVE_STDLIB_H_1
6530 #undef HAVE_STDLIB_H
6531 #endif /* HAVE_STLIB_H */
6533 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6534 /* In older releases of the jpeg library, jpeglib.h will define boolean
6535 differently depending on __WIN32__, so make sure it is defined. */
6539 #include <jpeglib.h>
6543 #ifdef HAVE_STLIB_H_1
6544 #define HAVE_STDLIB_H 1
6549 /* JPEG library details. */
6550 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6551 DEF_IMGLIB_FN (jpeg_start_decompress
);
6552 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6553 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6554 DEF_IMGLIB_FN (jpeg_read_header
);
6555 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6556 DEF_IMGLIB_FN (jpeg_std_error
);
6557 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6560 init_jpeg_functions (Lisp_Object libraries
)
6564 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6567 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6568 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6569 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6570 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6571 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6572 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6573 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6574 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6578 /* Wrapper since we can't directly assign the function pointer
6579 to another function pointer that was declared more completely easily. */
6581 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6582 j_decompress_ptr cinfo
;
6585 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6590 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6591 #define fn_jpeg_start_decompress jpeg_start_decompress
6592 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6593 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6594 #define fn_jpeg_read_header jpeg_read_header
6595 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6596 #define fn_jpeg_std_error jpeg_std_error
6597 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6599 #endif /* HAVE_NTGUI */
6601 struct my_jpeg_error_mgr
6603 struct jpeg_error_mgr pub
;
6604 jmp_buf setjmp_buffer
;
6609 my_error_exit (cinfo
)
6612 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6613 longjmp (mgr
->setjmp_buffer
, 1);
6617 /* Init source method for JPEG data source manager. Called by
6618 jpeg_read_header() before any data is actually read. See
6619 libjpeg.doc from the JPEG lib distribution. */
6622 our_common_init_source (cinfo
)
6623 j_decompress_ptr cinfo
;
6628 /* Method to terminate data source. Called by
6629 jpeg_finish_decompress() after all data has been processed. */
6632 our_common_term_source (cinfo
)
6633 j_decompress_ptr cinfo
;
6638 /* Fill input buffer method for JPEG data source manager. Called
6639 whenever more data is needed. We read the whole image in one step,
6640 so this only adds a fake end of input marker at the end. */
6643 our_memory_fill_input_buffer (cinfo
)
6644 j_decompress_ptr cinfo
;
6646 /* Insert a fake EOI marker. */
6647 struct jpeg_source_mgr
*src
= cinfo
->src
;
6648 static JOCTET buffer
[2];
6650 buffer
[0] = (JOCTET
) 0xFF;
6651 buffer
[1] = (JOCTET
) JPEG_EOI
;
6653 src
->next_input_byte
= buffer
;
6654 src
->bytes_in_buffer
= 2;
6659 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6660 is the JPEG data source manager. */
6663 our_memory_skip_input_data (cinfo
, num_bytes
)
6664 j_decompress_ptr cinfo
;
6667 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6671 if (num_bytes
> src
->bytes_in_buffer
)
6672 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6674 src
->bytes_in_buffer
-= num_bytes
;
6675 src
->next_input_byte
+= num_bytes
;
6680 /* Set up the JPEG lib for reading an image from DATA which contains
6681 LEN bytes. CINFO is the decompression info structure created for
6682 reading the image. */
6685 jpeg_memory_src (cinfo
, data
, len
)
6686 j_decompress_ptr cinfo
;
6690 struct jpeg_source_mgr
*src
;
6692 if (cinfo
->src
== NULL
)
6694 /* First time for this JPEG object? */
6695 cinfo
->src
= (struct jpeg_source_mgr
*)
6696 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6697 sizeof (struct jpeg_source_mgr
));
6698 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6699 src
->next_input_byte
= data
;
6702 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6703 src
->init_source
= our_common_init_source
;
6704 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6705 src
->skip_input_data
= our_memory_skip_input_data
;
6706 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6707 src
->term_source
= our_common_term_source
;
6708 src
->bytes_in_buffer
= len
;
6709 src
->next_input_byte
= data
;
6713 struct jpeg_stdio_mgr
6715 struct jpeg_source_mgr mgr
;
6722 /* Size of buffer to read JPEG from file.
6723 Not too big, as we want to use alloc_small. */
6724 #define JPEG_STDIO_BUFFER_SIZE 8192
6727 /* Fill input buffer method for JPEG data source manager. Called
6728 whenever more data is needed. The data is read from a FILE *. */
6731 our_stdio_fill_input_buffer (cinfo
)
6732 j_decompress_ptr cinfo
;
6734 struct jpeg_stdio_mgr
*src
;
6736 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6741 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6743 src
->mgr
.bytes_in_buffer
= bytes
;
6746 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6748 src
->buffer
[0] = (JOCTET
) 0xFF;
6749 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6750 src
->mgr
.bytes_in_buffer
= 2;
6752 src
->mgr
.next_input_byte
= src
->buffer
;
6759 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6760 is the JPEG data source manager. */
6763 our_stdio_skip_input_data (cinfo
, num_bytes
)
6764 j_decompress_ptr cinfo
;
6767 struct jpeg_stdio_mgr
*src
;
6768 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6770 while (num_bytes
> 0 && !src
->finished
)
6772 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6774 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6775 src
->mgr
.next_input_byte
+= num_bytes
;
6780 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6781 src
->mgr
.bytes_in_buffer
= 0;
6782 src
->mgr
.next_input_byte
= NULL
;
6784 our_stdio_fill_input_buffer (cinfo
);
6790 /* Set up the JPEG lib for reading an image from a FILE *.
6791 CINFO is the decompression info structure created for
6792 reading the image. */
6795 jpeg_file_src (cinfo
, fp
)
6796 j_decompress_ptr cinfo
;
6799 struct jpeg_stdio_mgr
*src
;
6801 if (cinfo
->src
!= NULL
)
6802 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6805 /* First time for this JPEG object? */
6806 cinfo
->src
= (struct jpeg_source_mgr
*)
6807 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6808 sizeof (struct jpeg_stdio_mgr
));
6809 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6810 src
->buffer
= (JOCTET
*)
6811 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6812 JPEG_STDIO_BUFFER_SIZE
);
6817 src
->mgr
.init_source
= our_common_init_source
;
6818 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6819 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6820 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6821 src
->mgr
.term_source
= our_common_term_source
;
6822 src
->mgr
.bytes_in_buffer
= 0;
6823 src
->mgr
.next_input_byte
= NULL
;
6827 /* Load image IMG for use on frame F. Patterned after example.c
6828 from the JPEG lib. */
6835 struct jpeg_decompress_struct cinfo
;
6836 struct my_jpeg_error_mgr mgr
;
6837 Lisp_Object file
, specified_file
;
6838 Lisp_Object specified_data
;
6839 FILE * volatile fp
= NULL
;
6841 int row_stride
, x
, y
;
6842 XImagePtr ximg
= NULL
;
6844 unsigned long *colors
;
6846 struct gcpro gcpro1
;
6848 /* Open the JPEG file. */
6849 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6850 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6854 if (NILP (specified_data
))
6856 file
= x_find_image_file (specified_file
);
6857 if (!STRINGP (file
))
6859 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6864 fp
= fopen (SDATA (file
), "rb");
6867 image_error ("Cannot open `%s'", file
, Qnil
);
6873 /* Customize libjpeg's error handling to call my_error_exit when an
6874 error is detected. This function will perform a longjmp.
6875 Casting return value avoids a GCC warning on W32. */
6876 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
6877 mgr
.pub
.error_exit
= my_error_exit
;
6879 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6883 /* Called from my_error_exit. Display a JPEG error. */
6884 char buffer
[JMSG_LENGTH_MAX
];
6885 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6886 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6887 build_string (buffer
));
6890 /* Close the input file and destroy the JPEG object. */
6892 fclose ((FILE *) fp
);
6893 fn_jpeg_destroy_decompress (&cinfo
);
6895 /* If we already have an XImage, free that. */
6896 x_destroy_x_image (ximg
);
6898 /* Free pixmap and colors. */
6899 x_clear_image (f
, img
);
6905 /* Create the JPEG decompression object. Let it read from fp.
6906 Read the JPEG image header. */
6907 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6909 if (NILP (specified_data
))
6910 jpeg_file_src (&cinfo
, (FILE *) fp
);
6912 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6913 SBYTES (specified_data
));
6915 fn_jpeg_read_header (&cinfo
, 1);
6917 /* Customize decompression so that color quantization will be used.
6918 Start decompression. */
6919 cinfo
.quantize_colors
= 1;
6920 fn_jpeg_start_decompress (&cinfo
);
6921 width
= img
->width
= cinfo
.output_width
;
6922 height
= img
->height
= cinfo
.output_height
;
6924 if (!check_image_size (f
, width
, height
))
6926 image_error ("Invalid image size", Qnil
, Qnil
);
6927 longjmp (mgr
.setjmp_buffer
, 2);
6930 /* Create X image and pixmap. */
6931 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6932 longjmp (mgr
.setjmp_buffer
, 2);
6934 /* Allocate colors. When color quantization is used,
6935 cinfo.actual_number_of_colors has been set with the number of
6936 colors generated, and cinfo.colormap is a two-dimensional array
6937 of color indices in the range 0..cinfo.actual_number_of_colors.
6938 No more than 255 colors will be generated. */
6942 if (cinfo
.out_color_components
> 2)
6943 ir
= 0, ig
= 1, ib
= 2;
6944 else if (cinfo
.out_color_components
> 1)
6945 ir
= 0, ig
= 1, ib
= 0;
6947 ir
= 0, ig
= 0, ib
= 0;
6949 /* Use the color table mechanism because it handles colors that
6950 cannot be allocated nicely. Such colors will be replaced with
6951 a default color, and we don't have to care about which colors
6952 can be freed safely, and which can't. */
6953 init_color_table ();
6954 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6957 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6959 /* Multiply RGB values with 255 because X expects RGB values
6960 in the range 0..0xffff. */
6961 int r
= cinfo
.colormap
[ir
][i
] << 8;
6962 int g
= cinfo
.colormap
[ig
][i
] << 8;
6963 int b
= cinfo
.colormap
[ib
][i
] << 8;
6964 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6967 #ifdef COLOR_TABLE_SUPPORT
6968 /* Remember those colors actually allocated. */
6969 img
->colors
= colors_in_color_table (&img
->ncolors
);
6970 free_color_table ();
6971 #endif /* COLOR_TABLE_SUPPORT */
6975 row_stride
= width
* cinfo
.output_components
;
6976 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6978 for (y
= 0; y
< height
; ++y
)
6980 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6981 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6982 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6986 fn_jpeg_finish_decompress (&cinfo
);
6987 fn_jpeg_destroy_decompress (&cinfo
);
6989 fclose ((FILE *) fp
);
6991 /* Maybe fill in the background field while we have ximg handy. */
6992 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6993 /* Casting avoids a GCC warning. */
6994 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6996 /* Put the image into the pixmap. */
6997 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6998 x_destroy_x_image (ximg
);
7003 #else /* HAVE_JPEG */
7012 return image_load_quartz2d (f
, img
, 0);
7014 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
7019 #endif /* !HAVE_JPEG */
7023 /***********************************************************************
7025 ***********************************************************************/
7027 #if defined (HAVE_TIFF) || defined (MAC_OS)
7029 static int tiff_image_p
P_ ((Lisp_Object object
));
7030 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
7032 /* The symbol `tiff' identifying images of this type. */
7036 /* Indices of image specification fields in tiff_format, below. */
7038 enum tiff_keyword_index
7047 TIFF_HEURISTIC_MASK
,
7053 /* Vector of image_keyword structures describing the format
7054 of valid user-defined image specifications. */
7056 static struct image_keyword tiff_format
[TIFF_LAST
] =
7058 {":type", IMAGE_SYMBOL_VALUE
, 1},
7059 {":data", IMAGE_STRING_VALUE
, 0},
7060 {":file", IMAGE_STRING_VALUE
, 0},
7061 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7062 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7063 {":relief", IMAGE_INTEGER_VALUE
, 0},
7064 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7065 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7066 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7067 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7070 /* Structure describing the image type `tiff'. */
7072 static struct image_type tiff_type
=
7081 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7084 tiff_image_p (object
)
7087 struct image_keyword fmt
[TIFF_LAST
];
7088 bcopy (tiff_format
, fmt
, sizeof fmt
);
7090 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
7093 /* Must specify either the :data or :file keyword. */
7094 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
7097 #endif /* HAVE_TIFF || MAC_OS */
7105 /* TIFF library details. */
7106 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
7107 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
7108 DEF_IMGLIB_FN (TIFFOpen
);
7109 DEF_IMGLIB_FN (TIFFClientOpen
);
7110 DEF_IMGLIB_FN (TIFFGetField
);
7111 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
7112 DEF_IMGLIB_FN (TIFFClose
);
7115 init_tiff_functions (Lisp_Object libraries
)
7119 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7122 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7123 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7124 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7125 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7126 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7127 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7128 LOAD_IMGLIB_FN (library
, TIFFClose
);
7134 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7135 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7136 #define fn_TIFFOpen TIFFOpen
7137 #define fn_TIFFClientOpen TIFFClientOpen
7138 #define fn_TIFFGetField TIFFGetField
7139 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7140 #define fn_TIFFClose TIFFClose
7142 #endif /* HAVE_NTGUI */
7145 /* Reading from a memory buffer for TIFF images Based on the PNG
7146 memory source, but we have to provide a lot of extra functions.
7149 We really only need to implement read and seek, but I am not
7150 convinced that the TIFF library is smart enough not to destroy
7151 itself if we only hand it the function pointers we need to
7156 unsigned char *bytes
;
7163 tiff_read_from_memory (data
, buf
, size
)
7168 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7170 if (size
> src
->len
- src
->index
)
7172 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7178 tiff_write_from_memory (data
, buf
, size
)
7187 tiff_seek_in_memory (data
, off
, whence
)
7192 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7197 case SEEK_SET
: /* Go from beginning of source. */
7201 case SEEK_END
: /* Go from end of source. */
7202 idx
= src
->len
+ off
;
7205 case SEEK_CUR
: /* Go from current position. */
7206 idx
= src
->index
+ off
;
7209 default: /* Invalid `whence'. */
7213 if (idx
> src
->len
|| idx
< 0)
7221 tiff_close_memory (data
)
7229 tiff_mmap_memory (data
, pbase
, psize
)
7234 /* It is already _IN_ memory. */
7239 tiff_unmap_memory (data
, base
, size
)
7244 /* We don't need to do this. */
7248 tiff_size_of_memory (data
)
7251 return ((tiff_memory_source
*) data
)->len
;
7256 tiff_error_handler (title
, format
, ap
)
7257 const char *title
, *format
;
7263 len
= sprintf (buf
, "TIFF error: %s ", title
);
7264 vsprintf (buf
+ len
, format
, ap
);
7265 add_to_log (buf
, Qnil
, Qnil
);
7270 tiff_warning_handler (title
, format
, ap
)
7271 const char *title
, *format
;
7277 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7278 vsprintf (buf
+ len
, format
, ap
);
7279 add_to_log (buf
, Qnil
, Qnil
);
7283 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7291 Lisp_Object file
, specified_file
;
7292 Lisp_Object specified_data
;
7294 int width
, height
, x
, y
;
7298 struct gcpro gcpro1
;
7299 tiff_memory_source memsrc
;
7301 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7302 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7306 fn_TIFFSetErrorHandler (tiff_error_handler
);
7307 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7309 if (NILP (specified_data
))
7311 /* Read from a file */
7312 file
= x_find_image_file (specified_file
);
7313 if (!STRINGP (file
))
7315 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7320 /* Try to open the image file. Casting return value avoids a
7321 GCC warning on W32. */
7322 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7325 image_error ("Cannot open `%s'", file
, Qnil
);
7332 /* Memory source! */
7333 memsrc
.bytes
= SDATA (specified_data
);
7334 memsrc
.len
= SBYTES (specified_data
);
7337 /* Casting return value avoids a GCC warning on W32. */
7338 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7339 (TIFFReadWriteProc
) tiff_read_from_memory
,
7340 (TIFFReadWriteProc
) tiff_write_from_memory
,
7341 tiff_seek_in_memory
,
7343 tiff_size_of_memory
,
7349 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7355 /* Get width and height of the image, and allocate a raster buffer
7356 of width x height 32-bit values. */
7357 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7358 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7360 if (!check_image_size (f
, width
, height
))
7362 image_error ("Invalid image size", Qnil
, Qnil
);
7367 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7369 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7370 fn_TIFFClose (tiff
);
7373 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7379 /* Create the X image and pixmap. */
7380 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7387 /* Initialize the color table. */
7388 init_color_table ();
7390 /* Process the pixel raster. Origin is in the lower-left corner. */
7391 for (y
= 0; y
< height
; ++y
)
7393 uint32
*row
= buf
+ y
* width
;
7395 for (x
= 0; x
< width
; ++x
)
7397 uint32 abgr
= row
[x
];
7398 int r
= TIFFGetR (abgr
) << 8;
7399 int g
= TIFFGetG (abgr
) << 8;
7400 int b
= TIFFGetB (abgr
) << 8;
7401 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7405 #ifdef COLOR_TABLE_SUPPORT
7406 /* Remember the colors allocated for the image. Free the color table. */
7407 img
->colors
= colors_in_color_table (&img
->ncolors
);
7408 free_color_table ();
7409 #endif /* COLOR_TABLE_SUPPORT */
7412 img
->height
= height
;
7414 /* Maybe fill in the background field while we have ximg handy. */
7415 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7416 /* Casting avoids a GCC warning on W32. */
7417 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7419 /* Put the image into the pixmap, then free the X image and its buffer. */
7420 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7421 x_destroy_x_image (ximg
);
7428 #else /* HAVE_TIFF */
7436 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7440 #endif /* !HAVE_TIFF */
7444 /***********************************************************************
7446 ***********************************************************************/
7448 #if defined (HAVE_GIF) || defined (MAC_OS)
7450 static int gif_image_p
P_ ((Lisp_Object object
));
7451 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7453 /* The symbol `gif' identifying images of this type. */
7457 /* Indices of image specification fields in gif_format, below. */
7459 enum gif_keyword_index
7475 /* Vector of image_keyword structures describing the format
7476 of valid user-defined image specifications. */
7478 static struct image_keyword gif_format
[GIF_LAST
] =
7480 {":type", IMAGE_SYMBOL_VALUE
, 1},
7481 {":data", IMAGE_STRING_VALUE
, 0},
7482 {":file", IMAGE_STRING_VALUE
, 0},
7483 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7484 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7485 {":relief", IMAGE_INTEGER_VALUE
, 0},
7486 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7487 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7488 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7489 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7490 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7493 /* Structure describing the image type `gif'. */
7495 static struct image_type gif_type
=
7504 /* Return non-zero if OBJECT is a valid GIF image specification. */
7507 gif_image_p (object
)
7510 struct image_keyword fmt
[GIF_LAST
];
7511 bcopy (gif_format
, fmt
, sizeof fmt
);
7513 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7516 /* Must specify either the :data or :file keyword. */
7517 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7520 #endif /* HAVE_GIF || MAC_OS */
7524 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7525 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7526 Undefine before redefining to avoid a preprocessor warning. */
7530 /* avoid conflict with QuickdrawText.h */
7531 #define DrawText gif_DrawText
7532 #include <gif_lib.h>
7535 #else /* HAVE_NTGUI || MAC_OS */
7537 #include <gif_lib.h>
7539 #endif /* HAVE_NTGUI || MAC_OS */
7544 /* GIF library details. */
7545 DEF_IMGLIB_FN (DGifCloseFile
);
7546 DEF_IMGLIB_FN (DGifSlurp
);
7547 DEF_IMGLIB_FN (DGifOpen
);
7548 DEF_IMGLIB_FN (DGifOpenFileName
);
7551 init_gif_functions (Lisp_Object libraries
)
7555 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7558 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7559 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7560 LOAD_IMGLIB_FN (library
, DGifOpen
);
7561 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7567 #define fn_DGifCloseFile DGifCloseFile
7568 #define fn_DGifSlurp DGifSlurp
7569 #define fn_DGifOpen DGifOpen
7570 #define fn_DGifOpenFileName DGifOpenFileName
7572 #endif /* HAVE_NTGUI */
7574 /* Reading a GIF image from memory
7575 Based on the PNG memory stuff to a certain extent. */
7579 unsigned char *bytes
;
7585 /* Make the current memory source available to gif_read_from_memory.
7586 It's done this way because not all versions of libungif support
7587 a UserData field in the GifFileType structure. */
7588 static gif_memory_source
*current_gif_memory_src
;
7591 gif_read_from_memory (file
, buf
, len
)
7596 gif_memory_source
*src
= current_gif_memory_src
;
7598 if (len
> src
->len
- src
->index
)
7601 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7607 /* Load GIF image IMG for use on frame F. Value is non-zero if
7615 Lisp_Object file
, specified_file
;
7616 Lisp_Object specified_data
;
7617 int rc
, width
, height
, x
, y
, i
;
7619 ColorMapObject
*gif_color_map
;
7620 unsigned long pixel_colors
[256];
7622 struct gcpro gcpro1
;
7624 int ino
, image_left
, image_top
, image_width
, image_height
;
7625 gif_memory_source memsrc
;
7626 unsigned char *raster
;
7628 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7629 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7633 if (NILP (specified_data
))
7635 file
= x_find_image_file (specified_file
);
7636 if (!STRINGP (file
))
7638 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7643 /* Open the GIF file. Casting return value avoids a GCC warning
7645 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7648 image_error ("Cannot open `%s'", file
, Qnil
);
7655 /* Read from memory! */
7656 current_gif_memory_src
= &memsrc
;
7657 memsrc
.bytes
= SDATA (specified_data
);
7658 memsrc
.len
= SBYTES (specified_data
);
7661 /* Casting return value avoids a GCC warning on W32. */
7662 gif
= (GifFileType
*)fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7665 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7671 /* Before reading entire contents, check the declared image size. */
7672 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7674 image_error ("Invalid image size", Qnil
, Qnil
);
7675 fn_DGifCloseFile (gif
);
7680 /* Read entire contents. */
7681 rc
= fn_DGifSlurp (gif
);
7682 if (rc
== GIF_ERROR
)
7684 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7685 fn_DGifCloseFile (gif
);
7690 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7691 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7692 if (ino
>= gif
->ImageCount
)
7694 image_error ("Invalid image number `%s' in image `%s'",
7696 fn_DGifCloseFile (gif
);
7701 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
7702 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
7703 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7704 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7706 width
= img
->width
= max (gif
->SWidth
,
7707 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7708 image_left
+ image_width
));
7709 height
= img
->height
= max (gif
->SHeight
,
7710 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7711 image_top
+ image_height
));
7713 if (!check_image_size (f
, width
, height
))
7715 image_error ("Invalid image size", Qnil
, Qnil
);
7716 fn_DGifCloseFile (gif
);
7721 /* Create the X image and pixmap. */
7722 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7724 fn_DGifCloseFile (gif
);
7729 /* Allocate colors. */
7730 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7732 gif_color_map
= gif
->SColorMap
;
7733 init_color_table ();
7734 bzero (pixel_colors
, sizeof pixel_colors
);
7736 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7738 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7739 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7740 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7741 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7744 #ifdef COLOR_TABLE_SUPPORT
7745 img
->colors
= colors_in_color_table (&img
->ncolors
);
7746 free_color_table ();
7747 #endif /* COLOR_TABLE_SUPPORT */
7749 /* Clear the part of the screen image that are not covered by
7750 the image from the GIF file. Full animated GIF support
7751 requires more than can be done here (see the gif89 spec,
7752 disposal methods). Let's simply assume that the part
7753 not covered by a sub-image is in the frame's background color. */
7754 for (y
= 0; y
< image_top
; ++y
)
7755 for (x
= 0; x
< width
; ++x
)
7756 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7758 for (y
= image_top
+ image_height
; y
< height
; ++y
)
7759 for (x
= 0; x
< width
; ++x
)
7760 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7762 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
7764 for (x
= 0; x
< image_left
; ++x
)
7765 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7766 for (x
= image_left
+ image_width
; x
< width
; ++x
)
7767 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7770 /* Read the GIF image into the X image. We use a local variable
7771 `raster' here because RasterBits below is a char *, and invites
7772 problems with bytes >= 0x80. */
7773 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7775 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7777 static int interlace_start
[] = {0, 4, 2, 1};
7778 static int interlace_increment
[] = {8, 8, 4, 2};
7780 int row
= interlace_start
[0];
7784 for (y
= 0; y
< image_height
; y
++)
7786 if (row
>= image_height
)
7788 row
= interlace_start
[++pass
];
7789 while (row
>= image_height
)
7790 row
= interlace_start
[++pass
];
7793 for (x
= 0; x
< image_width
; x
++)
7795 int i
= raster
[(y
* image_width
) + x
];
7796 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
7800 row
+= interlace_increment
[pass
];
7805 for (y
= 0; y
< image_height
; ++y
)
7806 for (x
= 0; x
< image_width
; ++x
)
7808 int i
= raster
[y
* image_width
+ x
];
7809 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
7813 fn_DGifCloseFile (gif
);
7815 /* Maybe fill in the background field while we have ximg handy. */
7816 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7817 /* Casting avoids a GCC warning. */
7818 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7820 /* Put the image into the pixmap, then free the X image and its buffer. */
7821 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7822 x_destroy_x_image (ximg
);
7828 #else /* !HAVE_GIF */
7836 Lisp_Object specified_file
, file
;
7837 Lisp_Object specified_data
;
7839 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
7847 Lisp_Object specified_bg
;
7857 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7858 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7860 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7863 if (NILP (specified_data
))
7865 /* Read from a file */
7869 err
= find_image_fsspec (specified_file
, &file
, &fss
);
7873 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7878 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
7879 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
7883 if (!graphic_p
&& !movie_p
)
7885 if (prefer_graphic_p
)
7886 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
7887 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
7890 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
7891 CloseMovieFile (refnum
);
7894 image_error ("Error reading `%s'", file
, Qnil
);
7900 /* Memory source! */
7902 long file_type_atom
[3];
7904 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
7907 image_error ("Cannot allocate data handle for `%s'",
7912 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
7913 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
7914 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
7915 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
7918 err
= PtrAndHand ("\p", dref
, 1);
7920 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
7923 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
7926 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
7927 &movie_p
, &prefer_graphic_p
, 0);
7931 if (!graphic_p
&& !movie_p
)
7933 if (prefer_graphic_p
)
7937 DisposeHandle (dref
);
7938 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
7942 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
7943 HandleDataHandlerSubType
);
7944 DisposeHandle (dref
);
7949 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7950 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7951 track
= GetMovieIndTrack (movie
, 1);
7952 media
= GetTrackMedia (track
);
7953 nsamples
= GetMediaSampleCount (media
);
7954 if (ino
>= nsamples
)
7956 image_error ("Invalid image number `%s' in image `%s'",
7961 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7962 if (!STRINGP (specified_bg
) ||
7963 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
7965 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7966 color
.red
= RED16_FROM_ULONG (color
.pixel
);
7967 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
7968 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
7970 GetMovieBox (movie
, &rect
);
7971 width
= img
->width
= rect
.right
- rect
.left
;
7972 height
= img
->height
= rect
.bottom
- rect
.top
;
7973 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7976 GetGWorld (&old_port
, &old_gdh
);
7977 SetGWorld (ximg
, NULL
);
7978 bg_color
.red
= color
.red
;
7979 bg_color
.green
= color
.green
;
7980 bg_color
.blue
= color
.blue
;
7981 RGBBackColor (&bg_color
);
7982 SetGWorld (old_port
, old_gdh
);
7983 SetMovieActive (movie
, 1);
7984 SetMovieGWorld (movie
, ximg
, NULL
);
7985 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7986 SetMovieTimeValue (movie
, time
);
7987 MoviesTask (movie
, 0L);
7988 DisposeTrackMedia (media
);
7989 DisposeMovieTrack (track
);
7990 DisposeMovie (movie
);
7993 /* Maybe fill in the background field while we have ximg handy. */
7994 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7995 IMAGE_BACKGROUND (img
, f
, ximg
);
7997 /* Put the image into the pixmap. */
7998 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7999 x_destroy_x_image (ximg
);
8003 image_error ("Cannot open `%s'", file
, Qnil
);
8006 DisposeTrackMedia (media
);
8008 DisposeMovieTrack (track
);
8010 DisposeMovie (movie
);
8017 #endif /* HAVE_GIF */
8021 /***********************************************************************
8023 ***********************************************************************/
8025 #ifdef HAVE_X_WINDOWS
8026 #define HAVE_GHOSTSCRIPT 1
8027 #endif /* HAVE_X_WINDOWS */
8029 /* The symbol `postscript' identifying images of this type. */
8031 Lisp_Object Qpostscript
;
8033 #ifdef HAVE_GHOSTSCRIPT
8035 static int gs_image_p
P_ ((Lisp_Object object
));
8036 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8037 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8039 /* Keyword symbols. */
8041 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8043 /* Indices of image specification fields in gs_format, below. */
8045 enum gs_keyword_index
8063 /* Vector of image_keyword structures describing the format
8064 of valid user-defined image specifications. */
8066 static struct image_keyword gs_format
[GS_LAST
] =
8068 {":type", IMAGE_SYMBOL_VALUE
, 1},
8069 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8070 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8071 {":file", IMAGE_STRING_VALUE
, 1},
8072 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8073 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8074 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8075 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8076 {":relief", IMAGE_INTEGER_VALUE
, 0},
8077 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8078 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8079 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8080 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8083 /* Structure describing the image type `ghostscript'. */
8085 static struct image_type gs_type
=
8095 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8098 gs_clear_image (f
, img
)
8102 /* IMG->data.ptr_val may contain a recorded colormap. */
8103 xfree (img
->data
.ptr_val
);
8104 x_clear_image (f
, img
);
8108 /* Return non-zero if OBJECT is a valid Ghostscript image
8115 struct image_keyword fmt
[GS_LAST
];
8119 bcopy (gs_format
, fmt
, sizeof fmt
);
8121 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8124 /* Bounding box must be a list or vector containing 4 integers. */
8125 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8128 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8129 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8134 else if (VECTORP (tem
))
8136 if (XVECTOR (tem
)->size
!= 4)
8138 for (i
= 0; i
< 4; ++i
)
8139 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8149 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8158 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8159 struct gcpro gcpro1
, gcpro2
;
8161 double in_width
, in_height
;
8162 Lisp_Object pixel_colors
= Qnil
;
8164 /* Compute pixel size of pixmap needed from the given size in the
8165 image specification. Sizes in the specification are in pt. 1 pt
8166 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8168 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8169 in_width
= XFASTINT (pt_width
) / 72.0;
8170 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8171 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8172 in_height
= XFASTINT (pt_height
) / 72.0;
8173 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8175 if (!check_image_size (f
, img
->width
, img
->height
))
8177 image_error ("Invalid image size", Qnil
, Qnil
);
8181 /* Create the pixmap. */
8182 xassert (img
->pixmap
== NO_PIXMAP
);
8184 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8186 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8187 img
->width
, img
->height
,
8188 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8193 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8197 /* Call the loader to fill the pixmap. It returns a process object
8198 if successful. We do not record_unwind_protect here because
8199 other places in redisplay like calling window scroll functions
8200 don't either. Let the Lisp loader use `unwind-protect' instead. */
8201 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8203 sprintf (buffer
, "%lu %lu",
8204 (unsigned long) FRAME_X_WINDOW (f
),
8205 (unsigned long) img
->pixmap
);
8206 window_and_pixmap_id
= build_string (buffer
);
8208 sprintf (buffer
, "%lu %lu",
8209 FRAME_FOREGROUND_PIXEL (f
),
8210 FRAME_BACKGROUND_PIXEL (f
));
8211 pixel_colors
= build_string (buffer
);
8213 XSETFRAME (frame
, f
);
8214 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8216 loader
= intern ("gs-load-image");
8218 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8219 make_number (img
->width
),
8220 make_number (img
->height
),
8221 window_and_pixmap_id
,
8224 return PROCESSP (img
->data
.lisp_val
);
8228 /* Kill the Ghostscript process that was started to fill PIXMAP on
8229 frame F. Called from XTread_socket when receiving an event
8230 telling Emacs that Ghostscript has finished drawing. */
8233 x_kill_gs_process (pixmap
, f
)
8237 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
8241 /* Find the image containing PIXMAP. */
8242 for (i
= 0; i
< c
->used
; ++i
)
8243 if (c
->images
[i
]->pixmap
== pixmap
)
8246 /* Should someone in between have cleared the image cache, for
8247 instance, give up. */
8251 /* Kill the GS process. We should have found PIXMAP in the image
8252 cache and its image should contain a process object. */
8254 xassert (PROCESSP (img
->data
.lisp_val
));
8255 Fkill_process (img
->data
.lisp_val
, Qnil
);
8256 img
->data
.lisp_val
= Qnil
;
8258 #if defined (HAVE_X_WINDOWS)
8260 /* On displays with a mutable colormap, figure out the colors
8261 allocated for the image by looking at the pixels of an XImage for
8263 class = FRAME_X_VISUAL (f
)->class;
8264 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8270 /* Try to get an XImage for img->pixmep. */
8271 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8272 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8277 /* Initialize the color table. */
8278 init_color_table ();
8280 /* For each pixel of the image, look its color up in the
8281 color table. After having done so, the color table will
8282 contain an entry for each color used by the image. */
8283 for (y
= 0; y
< img
->height
; ++y
)
8284 for (x
= 0; x
< img
->width
; ++x
)
8286 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8287 lookup_pixel_color (f
, pixel
);
8290 /* Record colors in the image. Free color table and XImage. */
8291 #ifdef COLOR_TABLE_SUPPORT
8292 img
->colors
= colors_in_color_table (&img
->ncolors
);
8293 free_color_table ();
8295 XDestroyImage (ximg
);
8297 #if 0 /* This doesn't seem to be the case. If we free the colors
8298 here, we get a BadAccess later in x_clear_image when
8299 freeing the colors. */
8300 /* We have allocated colors once, but Ghostscript has also
8301 allocated colors on behalf of us. So, to get the
8302 reference counts right, free them once. */
8304 x_free_colors (f
, img
->colors
, img
->ncolors
);
8308 image_error ("Cannot get X image of `%s'; colors will not be freed",
8313 #endif /* HAVE_X_WINDOWS */
8315 /* Now that we have the pixmap, compute mask and transform the
8316 image if requested. */
8318 postprocess_image (f
, img
);
8322 #endif /* HAVE_GHOSTSCRIPT */
8325 /***********************************************************************
8327 ***********************************************************************/
8331 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8332 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8336 return valid_image_p (spec
) ? Qt
: Qnil
;
8340 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8346 if (valid_image_p (spec
))
8347 id
= lookup_image (SELECTED_FRAME (), spec
);
8350 return make_number (id
);
8353 #endif /* GLYPH_DEBUG != 0 */
8356 /***********************************************************************
8358 ***********************************************************************/
8361 /* Image types that rely on external libraries are loaded dynamically
8362 if the library is available. */
8363 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8364 define_image_type (image_type, init_lib_fn (libraries))
8366 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8367 define_image_type (image_type, 1)
8368 #endif /* HAVE_NTGUI */
8370 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8371 doc
: /* Initialize image library implementing image type TYPE.
8372 Return non-nil if TYPE is a supported image type.
8374 Image types pbm and xbm are prebuilt; other types are loaded here.
8375 Libraries to load are specified in alist LIBRARIES (usually, the value
8376 of `image-library-alist', which see). */)
8378 Lisp_Object type
, libraries
;
8382 /* Don't try to reload the library. */
8383 tested
= Fassq (type
, Vimage_type_cache
);
8385 return XCDR (tested
);
8387 #if defined (HAVE_XPM) || defined (MAC_OS)
8388 if (EQ (type
, Qxpm
))
8389 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8392 #if defined (HAVE_JPEG) || defined (MAC_OS)
8393 if (EQ (type
, Qjpeg
))
8394 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8397 #if defined (HAVE_TIFF) || defined (MAC_OS)
8398 if (EQ (type
, Qtiff
))
8399 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8402 #if defined (HAVE_GIF) || defined (MAC_OS)
8403 if (EQ (type
, Qgif
))
8404 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8407 #if defined (HAVE_PNG) || defined (MAC_OS)
8408 if (EQ (type
, Qpng
))
8409 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8412 #ifdef HAVE_GHOSTSCRIPT
8413 if (EQ (type
, Qpostscript
))
8414 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8417 /* If the type is not recognized, avoid testing it ever again. */
8418 CACHE_IMAGE_TYPE (type
, Qnil
);
8425 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8427 /* Initialize this only once, since that's what we do with Vimage_types
8428 and they are supposed to be in sync. Initializing here gives correct
8429 operation on GNU/Linux of calling dump-emacs after loading some images. */
8432 /* Must be defined now becase we're going to update it below, while
8433 defining the supported image types. */
8434 DEFVAR_LISP ("image-types", &Vimage_types
,
8435 doc
: /* List of potentially supported image types.
8436 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
8437 To check whether it is really supported, use `image-type-available-p'. */);
8438 Vimage_types
= Qnil
;
8440 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8441 doc
: /* Alist of image types vs external libraries needed to display them.
8443 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8444 representing a supported image type, and the rest are strings giving
8445 alternate filenames for the corresponding external libraries.
8447 Emacs tries to load the libraries in the order they appear on the
8448 list; if none is loaded, the running session of Emacs won't
8449 support the image type. Types 'pbm and 'xbm don't need to be
8450 listed; they're always supported. */);
8451 Vimage_library_alist
= Qnil
;
8452 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8454 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8455 doc
: /* Maximum size of images.
8456 Emacs will not load an image into memory if its pixel width or
8457 pixel height exceeds this limit.
8459 If the value is an integer, it directly specifies the maximum
8460 image height and width, measured in pixels. If it is a floating
8461 point number, it specifies the maximum image height and width
8462 as a ratio to the frame height and width. If the value is
8463 non-numeric, there is no explicit limit on the size of images. */);
8464 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8466 Vimage_type_cache
= Qnil
;
8467 staticpro (&Vimage_type_cache
);
8469 Qpbm
= intern ("pbm");
8471 ADD_IMAGE_TYPE(Qpbm
);
8473 Qxbm
= intern ("xbm");
8475 ADD_IMAGE_TYPE(Qxbm
);
8477 define_image_type (&xbm_type
, 1);
8478 define_image_type (&pbm_type
, 1);
8480 QCascent
= intern (":ascent");
8481 staticpro (&QCascent
);
8482 QCmargin
= intern (":margin");
8483 staticpro (&QCmargin
);
8484 QCrelief
= intern (":relief");
8485 staticpro (&QCrelief
);
8486 QCconversion
= intern (":conversion");
8487 staticpro (&QCconversion
);
8488 QCcolor_symbols
= intern (":color-symbols");
8489 staticpro (&QCcolor_symbols
);
8490 QCheuristic_mask
= intern (":heuristic-mask");
8491 staticpro (&QCheuristic_mask
);
8492 QCindex
= intern (":index");
8493 staticpro (&QCindex
);
8494 QCmatrix
= intern (":matrix");
8495 staticpro (&QCmatrix
);
8496 QCcolor_adjustment
= intern (":color-adjustment");
8497 staticpro (&QCcolor_adjustment
);
8498 QCmask
= intern (":mask");
8499 staticpro (&QCmask
);
8501 Qlaplace
= intern ("laplace");
8502 staticpro (&Qlaplace
);
8503 Qemboss
= intern ("emboss");
8504 staticpro (&Qemboss
);
8505 Qedge_detection
= intern ("edge-detection");
8506 staticpro (&Qedge_detection
);
8507 Qheuristic
= intern ("heuristic");
8508 staticpro (&Qheuristic
);
8510 Qpostscript
= intern ("postscript");
8511 staticpro (&Qpostscript
);
8512 #ifdef HAVE_GHOSTSCRIPT
8513 ADD_IMAGE_TYPE(Qpostscript
);
8514 QCloader
= intern (":loader");
8515 staticpro (&QCloader
);
8516 QCbounding_box
= intern (":bounding-box");
8517 staticpro (&QCbounding_box
);
8518 QCpt_width
= intern (":pt-width");
8519 staticpro (&QCpt_width
);
8520 QCpt_height
= intern (":pt-height");
8521 staticpro (&QCpt_height
);
8522 #endif /* HAVE_GHOSTSCRIPT */
8524 #if defined (HAVE_XPM) || defined (MAC_OS)
8525 Qxpm
= intern ("xpm");
8527 ADD_IMAGE_TYPE(Qxpm
);
8530 #if defined (HAVE_JPEG) || defined (MAC_OS)
8531 Qjpeg
= intern ("jpeg");
8533 ADD_IMAGE_TYPE(Qjpeg
);
8536 #if defined (HAVE_TIFF) || defined (MAC_OS)
8537 Qtiff
= intern ("tiff");
8539 ADD_IMAGE_TYPE(Qtiff
);
8542 #if defined (HAVE_GIF) || defined (MAC_OS)
8543 Qgif
= intern ("gif");
8545 ADD_IMAGE_TYPE(Qgif
);
8548 #if defined (HAVE_PNG) || defined (MAC_OS)
8549 Qpng
= intern ("png");
8551 ADD_IMAGE_TYPE(Qpng
);
8554 defsubr (&Sinit_image_library
);
8555 defsubr (&Sclear_image_cache
);
8556 defsubr (&Simage_size
);
8557 defsubr (&Simage_mask_p
);
8561 defsubr (&Slookup_image
);
8564 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8565 doc
: /* Non-nil means always draw a cross over disabled images.
8566 Disabled images are those having an `:conversion disabled' property.
8567 A cross is always drawn on black & white displays. */);
8568 cross_disabled_images
= 0;
8570 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8571 doc
: /* List of directories to search for window system bitmap files. */);
8572 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8574 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8575 doc
: /* Time after which cached images are removed from the cache.
8576 When an image has not been displayed this many seconds, remove it
8577 from the image cache. Value must be an integer or nil with nil
8578 meaning don't clear the cache. */);
8579 Vimage_cache_eviction_delay
= make_number (30 * 60);
8585 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
8586 init_image_func_pointer ();
8590 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8591 (do not change this comment) */