1 /* Functions for image support on window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
3 Free Software Foundation.
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, 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"
46 #include <sys/types.h>
49 #define COLOR_TABLE_SUPPORT 1
51 typedef struct x_bitmap_record Bitmap_Record
;
52 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
53 #define NO_PIXMAP None
55 #define RGB_PIXEL_COLOR unsigned long
57 #define PIX_MASK_RETAIN(f) 0
58 #define PIX_MASK_DRAW(f) 1
59 #endif /* HAVE_X_WINDOWS */
65 /* W32_TODO : Color tables on W32. */
66 #undef COLOR_TABLE_SUPPORT
68 typedef struct w32_bitmap_record Bitmap_Record
;
69 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
72 #define RGB_PIXEL_COLOR COLORREF
74 #define PIX_MASK_RETAIN(f) 0
75 #define PIX_MASK_DRAW(f) 1
77 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
78 #define x_defined_color w32_defined_color
79 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
80 #endif /* HAVE_NTGUI */
90 #include <QuickTime/QuickTime.h>
91 #else /* not MAC_OSX */
94 #include <TextUtils.h>
95 #endif /* not MAC_OSX */
97 /* MAC_TODO : Color tables on Mac. */
98 #undef COLOR_TABLE_SUPPORT
100 #define ZPixmap 0 /* arbitrary */
101 typedef struct mac_bitmap_record Bitmap_Record
;
103 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
106 #define RGB_PIXEL_COLOR unsigned long
108 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
109 #define x_defined_color mac_defined_color
110 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
111 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
112 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
117 /* Search path for bitmap files. */
119 Lisp_Object Vx_bitmap_file_path
;
122 static void x_disable_image
P_ ((struct frame
*, struct image
*));
123 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
126 static void init_color_table
P_ ((void));
127 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
128 #ifdef COLOR_TABLE_SUPPORT
129 static void free_color_table
P_ ((void));
130 static unsigned long *colors_in_color_table
P_ ((int *n
));
131 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
134 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
135 id, which is just an int that this section returns. Bitmaps are
136 reference counted so they can be shared among frames.
138 Bitmap indices are guaranteed to be > 0, so a negative number can
139 be used to indicate no bitmap.
141 If you use x_create_bitmap_from_data, then you must keep track of
142 the bitmaps yourself. That is, creating a bitmap from the same
143 data more than once will not be caught. */
148 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
149 Display
*display
; /* not used */
151 int x
, y
; /* not used */
152 unsigned int width
, height
; /* not used */
153 unsigned long plane_mask
; /* not used */
154 int format
; /* not used */
157 xassert (x
== 0 && y
== 0);
160 SetRect (&ri
, 0, 0, width
, height
);
161 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
163 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
166 LockPixels (GetGWorldPixMap (pixmap
));
172 XPutPixel (ximage
, x
, y
, pixel
)
181 GetGWorld (&old_port
, &old_gdh
);
182 SetGWorld (ximage
, NULL
);
184 color
.red
= RED16_FROM_ULONG (pixel
);
185 color
.green
= GREEN16_FROM_ULONG (pixel
);
186 color
.blue
= BLUE16_FROM_ULONG (pixel
);
187 SetCPixel (x
, y
, &color
);
189 SetGWorld (old_port
, old_gdh
);
193 XGetPixel (ximage
, x
, y
)
201 GetGWorld (&old_port
, &old_gdh
);
202 SetGWorld (ximage
, NULL
);
204 GetCPixel (x
, y
, &color
);
206 SetGWorld (old_port
, old_gdh
);
207 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
214 UnlockPixels (GetGWorldPixMap (ximg
));
219 /* Functions to access the contents of a bitmap, given an id. */
222 x_bitmap_height (f
, id
)
226 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
230 x_bitmap_width (f
, id
)
234 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
237 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
239 x_bitmap_pixmap (f
, id
)
243 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
247 #ifdef HAVE_X_WINDOWS
249 x_bitmap_mask (f
, id
)
253 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
257 /* Allocate a new bitmap record. Returns index of new record. */
260 x_allocate_bitmap_record (f
)
263 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
266 if (dpyinfo
->bitmaps
== NULL
)
268 dpyinfo
->bitmaps_size
= 10;
270 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
271 dpyinfo
->bitmaps_last
= 1;
275 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
276 return ++dpyinfo
->bitmaps_last
;
278 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
279 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
282 dpyinfo
->bitmaps_size
*= 2;
284 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
285 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
286 return ++dpyinfo
->bitmaps_last
;
289 /* Add one reference to the reference count of the bitmap with id ID. */
292 x_reference_bitmap (f
, id
)
296 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
299 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
302 x_create_bitmap_from_data (f
, bits
, width
, height
)
305 unsigned int width
, height
;
307 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
310 #ifdef HAVE_X_WINDOWS
312 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
313 bits
, width
, height
);
316 #endif /* HAVE_X_WINDOWS */
320 bitmap
= CreateBitmap (width
, height
,
321 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
322 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
326 #endif /* HAVE_NTGUI */
329 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
334 id
= x_allocate_bitmap_record (f
);
336 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
337 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
339 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
342 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
343 dpyinfo
->bitmaps
[id
- 1].height
= height
;
344 dpyinfo
->bitmaps
[id
- 1].width
= width
;
345 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
347 #ifdef HAVE_X_WINDOWS
348 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
349 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
350 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
351 #endif /* HAVE_X_WINDOWS */
354 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
355 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
356 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
357 #endif /* HAVE_NTGUI */
362 /* Create bitmap from file FILE for frame F. */
365 x_create_bitmap_from_file (f
, file
)
370 return -1; /* MAC_TODO : bitmap support */
374 return -1; /* W32_TODO : bitmap support */
375 #endif /* HAVE_NTGUI */
377 #ifdef HAVE_X_WINDOWS
378 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
379 unsigned int width
, height
;
381 int xhot
, yhot
, result
, id
;
386 /* Look for an existing bitmap with the same name. */
387 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
389 if (dpyinfo
->bitmaps
[id
].refcount
390 && dpyinfo
->bitmaps
[id
].file
391 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
393 ++dpyinfo
->bitmaps
[id
].refcount
;
398 /* Search bitmap-file-path for the file, if appropriate. */
399 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
404 filename
= (char *) SDATA (found
);
406 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
407 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
408 if (result
!= BitmapSuccess
)
411 id
= x_allocate_bitmap_record (f
);
412 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
413 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
414 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
415 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
416 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
417 dpyinfo
->bitmaps
[id
- 1].height
= height
;
418 dpyinfo
->bitmaps
[id
- 1].width
= width
;
419 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
422 #endif /* HAVE_X_WINDOWS */
428 Free_Bitmap_Record (dpyinfo
, bm
)
429 Display_Info
*dpyinfo
;
432 #ifdef HAVE_X_WINDOWS
433 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
435 XFreePixmap (dpyinfo
->display
, bm
->mask
);
436 #endif /* HAVE_X_WINDOWS */
439 DeleteObject (bm
->pixmap
);
440 #endif /* HAVE_NTGUI */
443 xfree (bm
->bitmap_data
); /* Added ++kfs */
444 bm
->bitmap_data
= NULL
;
454 /* Remove reference to bitmap with id number ID. */
457 x_destroy_bitmap (f
, id
)
461 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
465 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
467 if (--bm
->refcount
== 0)
470 Free_Bitmap_Record (dpyinfo
, bm
);
476 /* Free all the bitmaps for the display specified by DPYINFO. */
479 x_destroy_all_bitmaps (dpyinfo
)
480 Display_Info
*dpyinfo
;
483 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
485 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
486 if (bm
->refcount
> 0)
487 Free_Bitmap_Record (dpyinfo
, bm
);
489 dpyinfo
->bitmaps_last
= 0;
493 #ifdef HAVE_X_WINDOWS
495 /* Useful functions defined in the section
496 `Image type independent image structures' below. */
498 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
499 unsigned long height
));
501 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
502 int depth
, XImagePtr
*ximg
,
505 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
508 /* Create a mask of a bitmap. Note is this not a perfect mask.
509 It's nicer with some borders in this context */
512 x_create_bitmap_mask (f
, id
)
517 XImagePtr ximg
, mask_img
;
518 unsigned long width
, height
;
521 unsigned long x
, y
, xp
, xm
, yp
, ym
;
524 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
529 pixmap
= x_bitmap_pixmap (f
, id
);
530 width
= x_bitmap_width (f
, id
);
531 height
= x_bitmap_height (f
, id
);
534 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
543 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
548 XDestroyImage (ximg
);
552 bg
= four_corners_best (ximg
, width
, height
);
554 for (y
= 0; y
< ximg
->height
; ++y
)
556 for (x
= 0; x
< ximg
->width
; ++x
)
558 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
559 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
560 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
561 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
562 if (XGetPixel (ximg
, x
, y
) == bg
563 && XGetPixel (ximg
, x
, yp
) == bg
564 && XGetPixel (ximg
, x
, ym
) == bg
565 && XGetPixel (ximg
, xp
, y
) == bg
566 && XGetPixel (ximg
, xp
, yp
) == bg
567 && XGetPixel (ximg
, xp
, ym
) == bg
568 && XGetPixel (ximg
, xm
, y
) == bg
569 && XGetPixel (ximg
, xm
, yp
) == bg
570 && XGetPixel (ximg
, xm
, ym
) == bg
)
571 XPutPixel (mask_img
, x
, y
, 0);
573 XPutPixel (mask_img
, x
, y
, 1);
577 xassert (interrupt_input_blocked
);
578 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
579 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
581 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
583 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
584 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
586 XDestroyImage (ximg
);
587 x_destroy_x_image (mask_img
);
592 #endif /* HAVE_X_WINDOWS */
595 /***********************************************************************
597 ***********************************************************************/
599 /* Value is the number of elements of vector VECTOR. */
601 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
603 /* List of supported image types. Use define_image_type to add new
604 types. Use lookup_image_type to find a type for a given symbol. */
606 static struct image_type
*image_types
;
608 /* The symbol `xbm' which is used as the type symbol for XBM images. */
614 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
615 extern Lisp_Object QCdata
, QCtype
;
616 extern Lisp_Object Qcenter
;
617 Lisp_Object QCascent
, QCmargin
, QCrelief
;
618 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
619 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
623 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
625 /* Time in seconds after which images should be removed from the cache
628 Lisp_Object Vimage_cache_eviction_delay
;
630 /* Function prototypes. */
632 static void define_image_type
P_ ((struct image_type
*type
));
633 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
634 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
635 static void x_laplace
P_ ((struct frame
*, struct image
*));
636 static void x_emboss
P_ ((struct frame
*, struct image
*));
637 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
641 /* Define a new image type from TYPE. This adds a copy of TYPE to
642 image_types and adds the symbol *TYPE->type to Vimage_types. */
645 define_image_type (type
)
646 struct image_type
*type
;
648 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
649 The initialized data segment is read-only. */
650 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
651 bcopy (type
, p
, sizeof *p
);
652 p
->next
= image_types
;
654 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
658 /* Look up image type SYMBOL, and return a pointer to its image_type
659 structure. Value is null if SYMBOL is not a known image type. */
661 static INLINE
struct image_type
*
662 lookup_image_type (symbol
)
665 struct image_type
*type
;
667 for (type
= image_types
; type
; type
= type
->next
)
668 if (EQ (symbol
, *type
->type
))
675 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
676 valid image specification is a list whose car is the symbol
677 `image', and whose rest is a property list. The property list must
678 contain a value for key `:type'. That value must be the name of a
679 supported image type. The rest of the property list depends on the
683 valid_image_p (object
)
692 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
693 if (EQ (XCAR (tem
), QCtype
))
696 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
698 struct image_type
*type
;
699 type
= lookup_image_type (XCAR (tem
));
701 valid_p
= type
->valid_p (object
);
712 /* Log error message with format string FORMAT and argument ARG.
713 Signaling an error, e.g. when an image cannot be loaded, is not a
714 good idea because this would interrupt redisplay, and the error
715 message display would lead to another redisplay. This function
716 therefore simply displays a message. */
719 image_error (format
, arg1
, arg2
)
721 Lisp_Object arg1
, arg2
;
723 add_to_log (format
, arg1
, arg2
);
728 /***********************************************************************
730 ***********************************************************************/
732 enum image_value_type
734 IMAGE_DONT_CHECK_VALUE_TYPE
,
736 IMAGE_STRING_OR_NIL_VALUE
,
738 IMAGE_POSITIVE_INTEGER_VALUE
,
739 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
740 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
743 IMAGE_FUNCTION_VALUE
,
748 /* Structure used when parsing image specifications. */
752 /* Name of keyword. */
755 /* The type of value allowed. */
756 enum image_value_type type
;
758 /* Non-zero means key must be present. */
761 /* Used to recognize duplicate keywords in a property list. */
764 /* The value that was found. */
769 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
771 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
774 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
775 has the format (image KEYWORD VALUE ...). One of the keyword/
776 value pairs must be `:type TYPE'. KEYWORDS is a vector of
777 image_keywords structures of size NKEYWORDS describing other
778 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
781 parse_image_spec (spec
, keywords
, nkeywords
, type
)
783 struct image_keyword
*keywords
;
794 while (CONSP (plist
))
796 Lisp_Object key
, value
;
798 /* First element of a pair must be a symbol. */
800 plist
= XCDR (plist
);
804 /* There must follow a value. */
807 value
= XCAR (plist
);
808 plist
= XCDR (plist
);
810 /* Find key in KEYWORDS. Error if not found. */
811 for (i
= 0; i
< nkeywords
; ++i
)
812 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
818 /* Record that we recognized the keyword. If a keywords
819 was found more than once, it's an error. */
820 keywords
[i
].value
= value
;
823 if (keywords
[i
].count
> 1)
826 /* Check type of value against allowed type. */
827 switch (keywords
[i
].type
)
829 case IMAGE_STRING_VALUE
:
830 if (!STRINGP (value
))
834 case IMAGE_STRING_OR_NIL_VALUE
:
835 if (!STRINGP (value
) && !NILP (value
))
839 case IMAGE_SYMBOL_VALUE
:
840 if (!SYMBOLP (value
))
844 case IMAGE_POSITIVE_INTEGER_VALUE
:
845 if (!INTEGERP (value
) || XINT (value
) <= 0)
849 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
850 if (INTEGERP (value
) && XINT (value
) >= 0)
853 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
854 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
858 case IMAGE_ASCENT_VALUE
:
859 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
861 else if (INTEGERP (value
)
863 && XINT (value
) <= 100)
867 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
868 if (!INTEGERP (value
) || XINT (value
) < 0)
872 case IMAGE_DONT_CHECK_VALUE_TYPE
:
875 case IMAGE_FUNCTION_VALUE
:
876 value
= indirect_function (value
);
879 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
883 case IMAGE_NUMBER_VALUE
:
884 if (!INTEGERP (value
) && !FLOATP (value
))
888 case IMAGE_INTEGER_VALUE
:
889 if (!INTEGERP (value
))
893 case IMAGE_BOOL_VALUE
:
894 if (!NILP (value
) && !EQ (value
, Qt
))
903 if (EQ (key
, QCtype
) && !EQ (type
, value
))
907 /* Check that all mandatory fields are present. */
908 for (i
= 0; i
< nkeywords
; ++i
)
909 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
916 /* Return the value of KEY in image specification SPEC. Value is nil
917 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
918 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
921 image_spec_value (spec
, key
, found
)
922 Lisp_Object spec
, key
;
927 xassert (valid_image_p (spec
));
929 for (tail
= XCDR (spec
);
930 CONSP (tail
) && CONSP (XCDR (tail
));
931 tail
= XCDR (XCDR (tail
)))
933 if (EQ (XCAR (tail
), key
))
937 return XCAR (XCDR (tail
));
947 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
948 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
949 PIXELS non-nil means return the size in pixels, otherwise return the
950 size in canonical character units.
951 FRAME is the frame on which the image will be displayed. FRAME nil
952 or omitted means use the selected frame. */)
953 (spec
, pixels
, frame
)
954 Lisp_Object spec
, pixels
, frame
;
959 if (valid_image_p (spec
))
961 struct frame
*f
= check_x_frame (frame
);
962 int id
= lookup_image (f
, spec
);
963 struct image
*img
= IMAGE_FROM_ID (f
, id
);
964 int width
= img
->width
+ 2 * img
->hmargin
;
965 int height
= img
->height
+ 2 * img
->vmargin
;
968 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
969 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
971 size
= Fcons (make_number (width
), make_number (height
));
974 error ("Invalid image specification");
980 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
981 doc
: /* Return t if image SPEC has a mask bitmap.
982 FRAME is the frame on which the image will be displayed. FRAME nil
983 or omitted means use the selected frame. */)
985 Lisp_Object spec
, frame
;
990 if (valid_image_p (spec
))
992 struct frame
*f
= check_x_frame (frame
);
993 int id
= lookup_image (f
, spec
);
994 struct image
*img
= IMAGE_FROM_ID (f
, id
);
999 error ("Invalid image specification");
1005 /***********************************************************************
1006 Image type independent image structures
1007 ***********************************************************************/
1009 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1010 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1013 /* Allocate and return a new image structure for image specification
1014 SPEC. SPEC has a hash value of HASH. */
1016 static struct image
*
1017 make_image (spec
, hash
)
1021 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1023 xassert (valid_image_p (spec
));
1024 bzero (img
, sizeof *img
);
1025 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1026 xassert (img
->type
!= NULL
);
1028 img
->data
.lisp_val
= Qnil
;
1029 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1035 /* Free image IMG which was used on frame F, including its resources. */
1044 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1046 /* Remove IMG from the hash table of its cache. */
1048 img
->prev
->next
= img
->next
;
1050 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1053 img
->next
->prev
= img
->prev
;
1055 c
->images
[img
->id
] = NULL
;
1057 /* Free resources, then free IMG. */
1058 img
->type
->free (f
, img
);
1064 /* Prepare image IMG for display on frame F. Must be called before
1065 drawing an image. */
1068 prepare_image_for_display (f
, img
)
1074 /* We're about to display IMG, so set its timestamp to `now'. */
1076 img
->timestamp
= EMACS_SECS (t
);
1078 /* If IMG doesn't have a pixmap yet, load it now, using the image
1079 type dependent loader function. */
1080 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1081 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1085 /* Value is the number of pixels for the ascent of image IMG when
1086 drawn in face FACE. */
1089 image_ascent (img
, face
, slice
)
1092 struct glyph_slice
*slice
;
1097 if (slice
->height
== img
->height
)
1098 height
= img
->height
+ img
->vmargin
;
1099 else if (slice
->y
== 0)
1100 height
= slice
->height
+ img
->vmargin
;
1102 height
= slice
->height
;
1104 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1109 /* W32 specific version. Why?. ++kfs */
1110 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1111 - FONT_BASE(face
->font
)) / 2;
1113 /* This expression is arranged so that if the image can't be
1114 exactly centered, it will be moved slightly up. This is
1115 because a typical font is `top-heavy' (due to the presence
1116 uppercase letters), so the image placement should err towards
1117 being top-heavy too. It also just generally looks better. */
1118 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1119 #endif /* HAVE_NTGUI */
1122 ascent
= height
/ 2;
1125 ascent
= (int) (height
* img
->ascent
/ 100.0);
1131 /* Image background colors. */
1133 /* Find the "best" corner color of a bitmap.
1134 On W32, XIMG is assumed to a device context with the bitmap selected. */
1136 static RGB_PIXEL_COLOR
1137 four_corners_best (ximg
, width
, height
)
1138 XImagePtr_or_DC ximg
;
1139 unsigned long width
, height
;
1141 RGB_PIXEL_COLOR corners
[4], best
;
1144 /* Get the colors at the corners of ximg. */
1145 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1146 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1147 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1148 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1150 /* Choose the most frequently found color as background. */
1151 for (i
= best_count
= 0; i
< 4; ++i
)
1155 for (j
= n
= 0; j
< 4; ++j
)
1156 if (corners
[i
] == corners
[j
])
1160 best
= corners
[i
], best_count
= n
;
1166 /* Portability macros */
1170 #define Destroy_Image(img_dc, prev) \
1171 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1173 #define Free_Pixmap(display, pixmap) \
1174 DeleteObject (pixmap)
1178 #define Destroy_Image(ximg, dummy) \
1179 XDestroyImage (ximg)
1181 #define Free_Pixmap(display, pixmap) \
1182 XFreePixmap (display, pixmap)
1184 #endif /* HAVE_NTGUI */
1187 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1188 it is guessed heuristically. If non-zero, XIMG is an existing
1189 XImage object (or device context with the image selected on W32) to
1190 use for the heuristic. */
1193 image_background (img
, f
, ximg
)
1196 XImagePtr_or_DC ximg
;
1198 if (! img
->background_valid
)
1199 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1201 int free_ximg
= !ximg
;
1204 #endif /* HAVE_NTGUI */
1209 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1210 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1212 HDC frame_dc
= get_frame_dc (f
);
1213 ximg
= CreateCompatibleDC (frame_dc
);
1214 release_frame_dc (f
, frame_dc
);
1215 prev
= SelectObject (ximg
, img
->pixmap
);
1216 #endif /* !HAVE_NTGUI */
1219 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1222 Destroy_Image (ximg
, prev
);
1224 img
->background_valid
= 1;
1227 return img
->background
;
1230 /* Return the `background_transparent' field of IMG. If IMG doesn't
1231 have one yet, it is guessed heuristically. If non-zero, MASK is an
1232 existing XImage object to use for the heuristic. */
1235 image_background_transparent (img
, f
, mask
)
1238 XImagePtr_or_DC mask
;
1240 if (! img
->background_transparent_valid
)
1241 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1245 int free_mask
= !mask
;
1248 #endif /* HAVE_NTGUI */
1253 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1254 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1256 HDC frame_dc
= get_frame_dc (f
);
1257 mask
= CreateCompatibleDC (frame_dc
);
1258 release_frame_dc (f
, frame_dc
);
1259 prev
= SelectObject (mask
, img
->mask
);
1260 #endif /* HAVE_NTGUI */
1263 img
->background_transparent
1264 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1267 Destroy_Image (mask
, prev
);
1270 img
->background_transparent
= 0;
1272 img
->background_transparent_valid
= 1;
1275 return img
->background_transparent
;
1279 /***********************************************************************
1280 Helper functions for X image types
1281 ***********************************************************************/
1283 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1285 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1286 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1288 Lisp_Object color_name
,
1289 unsigned long dflt
));
1292 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1293 free the pixmap if any. MASK_P non-zero means clear the mask
1294 pixmap if any. COLORS_P non-zero means free colors allocated for
1295 the image, if any. */
1298 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1301 int pixmap_p
, mask_p
, colors_p
;
1303 if (pixmap_p
&& img
->pixmap
)
1305 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1306 img
->pixmap
= NO_PIXMAP
;
1307 img
->background_valid
= 0;
1310 if (mask_p
&& img
->mask
)
1312 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1313 img
->mask
= NO_PIXMAP
;
1314 img
->background_transparent_valid
= 0;
1317 if (colors_p
&& img
->ncolors
)
1319 /* MAC_TODO: color table support. */
1320 /* W32_TODO: color table support. */
1321 #ifdef HAVE_X_WINDOWS
1322 x_free_colors (f
, img
->colors
, img
->ncolors
);
1323 #endif /* HAVE_X_WINDOWS */
1324 xfree (img
->colors
);
1330 /* Free X resources of image IMG which is used on frame F. */
1333 x_clear_image (f
, img
)
1338 x_clear_image_1 (f
, img
, 1, 1, 1);
1343 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1344 cannot be allocated, use DFLT. Add a newly allocated color to
1345 IMG->colors, so that it can be freed again. Value is the pixel
1348 static unsigned long
1349 x_alloc_image_color (f
, img
, color_name
, dflt
)
1352 Lisp_Object color_name
;
1356 unsigned long result
;
1358 xassert (STRINGP (color_name
));
1360 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1362 /* This isn't called frequently so we get away with simply
1363 reallocating the color vector to the needed size, here. */
1366 (unsigned long *) xrealloc (img
->colors
,
1367 img
->ncolors
* sizeof *img
->colors
);
1368 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1369 result
= color
.pixel
;
1379 /***********************************************************************
1381 ***********************************************************************/
1383 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1384 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1386 /* Return a new, initialized image cache that is allocated from the
1387 heap. Call free_image_cache to free an image cache. */
1389 struct image_cache
*
1392 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1395 bzero (c
, sizeof *c
);
1397 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1398 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1399 c
->buckets
= (struct image
**) xmalloc (size
);
1400 bzero (c
->buckets
, size
);
1405 /* Free image cache of frame F. Be aware that X frames share images
1409 free_image_cache (f
)
1412 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1417 /* Cache should not be referenced by any frame when freed. */
1418 xassert (c
->refcount
== 0);
1420 for (i
= 0; i
< c
->used
; ++i
)
1421 free_image (f
, c
->images
[i
]);
1425 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1430 /* Clear image cache of frame F. FORCE_P non-zero means free all
1431 images. FORCE_P zero means clear only images that haven't been
1432 displayed for some time. Should be called from time to time to
1433 reduce the number of loaded images. If image-eviction-seconds is
1434 non-nil, this frees images in the cache which weren't displayed for
1435 at least that many seconds. */
1438 clear_image_cache (f
, force_p
)
1442 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1444 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1451 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1453 /* Block input so that we won't be interrupted by a SIGIO
1454 while being in an inconsistent state. */
1457 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1459 struct image
*img
= c
->images
[i
];
1461 && (force_p
|| img
->timestamp
< old
))
1463 free_image (f
, img
);
1468 /* We may be clearing the image cache because, for example,
1469 Emacs was iconified for a longer period of time. In that
1470 case, current matrices may still contain references to
1471 images freed above. So, clear these matrices. */
1474 Lisp_Object tail
, frame
;
1476 FOR_EACH_FRAME (tail
, frame
)
1478 struct frame
*f
= XFRAME (frame
);
1479 if (FRAME_WINDOW_P (f
)
1480 && FRAME_X_IMAGE_CACHE (f
) == c
)
1481 clear_current_matrices (f
);
1484 ++windows_or_buffers_changed
;
1492 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1494 doc
: /* Clear the image cache of FRAME.
1495 FRAME nil or omitted means use the selected frame.
1496 FRAME t means clear the image caches of all frames. */)
1504 FOR_EACH_FRAME (tail
, frame
)
1505 if (FRAME_WINDOW_P (XFRAME (frame
)))
1506 clear_image_cache (XFRAME (frame
), 1);
1509 clear_image_cache (check_x_frame (frame
), 1);
1515 /* Compute masks and transform image IMG on frame F, as specified
1516 by the image's specification, */
1519 postprocess_image (f
, img
)
1523 /* Manipulation of the image's mask. */
1526 Lisp_Object conversion
, spec
;
1531 /* `:heuristic-mask t'
1533 means build a mask heuristically.
1534 `:heuristic-mask (R G B)'
1535 `:mask (heuristic (R G B))'
1536 means build a mask from color (R G B) in the
1539 means remove a mask, if any. */
1541 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1543 x_build_heuristic_mask (f
, img
, mask
);
1548 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1550 if (EQ (mask
, Qheuristic
))
1551 x_build_heuristic_mask (f
, img
, Qt
);
1552 else if (CONSP (mask
)
1553 && EQ (XCAR (mask
), Qheuristic
))
1555 if (CONSP (XCDR (mask
)))
1556 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1558 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1560 else if (NILP (mask
) && found_p
&& img
->mask
)
1562 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1563 img
->mask
= NO_PIXMAP
;
1568 /* Should we apply an image transformation algorithm? */
1569 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1570 if (EQ (conversion
, Qdisabled
))
1571 x_disable_image (f
, img
);
1572 else if (EQ (conversion
, Qlaplace
))
1574 else if (EQ (conversion
, Qemboss
))
1576 else if (CONSP (conversion
)
1577 && EQ (XCAR (conversion
), Qedge_detection
))
1580 tem
= XCDR (conversion
);
1582 x_edge_detection (f
, img
,
1583 Fplist_get (tem
, QCmatrix
),
1584 Fplist_get (tem
, QCcolor_adjustment
));
1590 /* Return the id of image with Lisp specification SPEC on frame F.
1591 SPEC must be a valid Lisp image specification (see valid_image_p). */
1594 lookup_image (f
, spec
)
1598 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1602 struct gcpro gcpro1
;
1605 /* F must be a window-system frame, and SPEC must be a valid image
1607 xassert (FRAME_WINDOW_P (f
));
1608 xassert (valid_image_p (spec
));
1612 /* Look up SPEC in the hash table of the image cache. */
1613 hash
= sxhash (spec
, 0);
1614 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1616 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1617 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1620 /* If not found, create a new image and cache it. */
1623 extern Lisp_Object Qpostscript
;
1626 img
= make_image (spec
, hash
);
1627 cache_image (f
, img
);
1628 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1630 /* If we can't load the image, and we don't have a width and
1631 height, use some arbitrary width and height so that we can
1632 draw a rectangle for it. */
1633 if (img
->load_failed_p
)
1637 value
= image_spec_value (spec
, QCwidth
, NULL
);
1638 img
->width
= (INTEGERP (value
)
1639 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1640 value
= image_spec_value (spec
, QCheight
, NULL
);
1641 img
->height
= (INTEGERP (value
)
1642 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1646 /* Handle image type independent image attributes
1647 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1648 `:background COLOR'. */
1649 Lisp_Object ascent
, margin
, relief
, bg
;
1651 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1652 if (INTEGERP (ascent
))
1653 img
->ascent
= XFASTINT (ascent
);
1654 else if (EQ (ascent
, Qcenter
))
1655 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1657 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1658 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1659 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1660 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1661 && INTEGERP (XCDR (margin
)))
1663 if (XINT (XCAR (margin
)) > 0)
1664 img
->hmargin
= XFASTINT (XCAR (margin
));
1665 if (XINT (XCDR (margin
)) > 0)
1666 img
->vmargin
= XFASTINT (XCDR (margin
));
1669 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1670 if (INTEGERP (relief
))
1672 img
->relief
= XINT (relief
);
1673 img
->hmargin
+= abs (img
->relief
);
1674 img
->vmargin
+= abs (img
->relief
);
1677 if (! img
->background_valid
)
1679 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1683 = x_alloc_image_color (f
, img
, bg
,
1684 FRAME_BACKGROUND_PIXEL (f
));
1685 img
->background_valid
= 1;
1689 /* Do image transformations and compute masks, unless we
1690 don't have the image yet. */
1691 if (!EQ (*img
->type
->type
, Qpostscript
))
1692 postprocess_image (f
, img
);
1698 /* We're using IMG, so set its timestamp to `now'. */
1699 EMACS_GET_TIME (now
);
1700 img
->timestamp
= EMACS_SECS (now
);
1704 /* Value is the image id. */
1709 /* Cache image IMG in the image cache of frame F. */
1712 cache_image (f
, img
)
1716 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1719 /* Find a free slot in c->images. */
1720 for (i
= 0; i
< c
->used
; ++i
)
1721 if (c
->images
[i
] == NULL
)
1724 /* If no free slot found, maybe enlarge c->images. */
1725 if (i
== c
->used
&& c
->used
== c
->size
)
1728 c
->images
= (struct image
**) xrealloc (c
->images
,
1729 c
->size
* sizeof *c
->images
);
1732 /* Add IMG to c->images, and assign IMG an id. */
1738 /* Add IMG to the cache's hash table. */
1739 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1740 img
->next
= c
->buckets
[i
];
1742 img
->next
->prev
= img
;
1744 c
->buckets
[i
] = img
;
1748 /* Call FN on every image in the image cache of frame F. Used to mark
1749 Lisp Objects in the image cache. */
1752 forall_images_in_image_cache (f
, fn
)
1754 void (*fn
) P_ ((struct image
*img
));
1756 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1758 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1762 for (i
= 0; i
< c
->used
; ++i
)
1771 /***********************************************************************
1772 X / MAC / W32 support code
1773 ***********************************************************************/
1777 /* Macro for defining functions that will be loaded from image DLLs. */
1778 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1780 /* Macro for loading those image functions from the library. */
1781 #define LOAD_IMGLIB_FN(lib,func) { \
1782 fn_##func = (void *) GetProcAddress (lib, #func); \
1783 if (!fn_##func) return 0; \
1786 #endif /* HAVE_NTGUI */
1788 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1789 XImagePtr
*, Pixmap
*));
1790 static void x_destroy_x_image
P_ ((XImagePtr
));
1791 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1794 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1795 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1796 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1797 via xmalloc. Print error messages via image_error if an error
1798 occurs. Value is non-zero if successful.
1800 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1801 should indicate the bit depth of the image. */
1804 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1806 int width
, height
, depth
;
1810 #ifdef HAVE_X_WINDOWS
1811 Display
*display
= FRAME_X_DISPLAY (f
);
1812 Window window
= FRAME_X_WINDOW (f
);
1813 Screen
*screen
= FRAME_X_SCREEN (f
);
1815 xassert (interrupt_input_blocked
);
1818 depth
= DefaultDepthOfScreen (screen
);
1819 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1820 depth
, ZPixmap
, 0, NULL
, width
, height
,
1821 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1824 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1828 /* Allocate image raster. */
1829 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1831 /* Allocate a pixmap of the same size. */
1832 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1833 if (*pixmap
== NO_PIXMAP
)
1835 x_destroy_x_image (*ximg
);
1837 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1842 #endif /* HAVE_X_WINDOWS */
1846 BITMAPINFOHEADER
*header
;
1848 int scanline_width_bits
;
1850 int palette_colors
= 0;
1855 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1856 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1858 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1862 scanline_width_bits
= width
* depth
;
1863 remainder
= scanline_width_bits
% 32;
1866 scanline_width_bits
+= 32 - remainder
;
1868 /* Bitmaps with a depth less than 16 need a palette. */
1869 /* BITMAPINFO structure already contains the first RGBQUAD. */
1871 palette_colors
= 1 << depth
- 1;
1873 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1876 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1880 header
= &((*ximg
)->info
.bmiHeader
);
1881 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1882 header
->biSize
= sizeof (*header
);
1883 header
->biWidth
= width
;
1884 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1885 header
->biPlanes
= 1;
1886 header
->biBitCount
= depth
;
1887 header
->biCompression
= BI_RGB
;
1888 header
->biClrUsed
= palette_colors
;
1890 /* TODO: fill in palette. */
1893 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1894 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1895 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1896 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1897 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1898 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1899 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1900 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1903 hdc
= get_frame_dc (f
);
1905 /* Create a DIBSection and raster array for the bitmap,
1906 and store its handle in *pixmap. */
1907 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1908 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1909 &((*ximg
)->data
), NULL
, 0);
1911 /* Realize display palette and garbage all frames. */
1912 release_frame_dc (f
, hdc
);
1914 if (*pixmap
== NULL
)
1916 DWORD err
= GetLastError();
1917 Lisp_Object errcode
;
1918 /* All system errors are < 10000, so the following is safe. */
1919 XSETINT (errcode
, (int) err
);
1920 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1921 x_destroy_x_image (*ximg
);
1927 #endif /* HAVE_NTGUI */
1930 Display
*display
= FRAME_X_DISPLAY (f
);
1931 Window window
= FRAME_X_WINDOW (f
);
1933 xassert (interrupt_input_blocked
);
1935 /* Allocate a pixmap of the same size. */
1936 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1937 if (*pixmap
== NO_PIXMAP
)
1939 x_destroy_x_image (*ximg
);
1941 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1945 LockPixels (GetGWorldPixMap (*pixmap
));
1953 /* Destroy XImage XIMG. Free XIMG->data. */
1956 x_destroy_x_image (ximg
)
1959 xassert (interrupt_input_blocked
);
1962 #ifdef HAVE_X_WINDOWS
1965 XDestroyImage (ximg
);
1966 #endif /* HAVE_X_WINDOWS */
1968 /* Data will be freed by DestroyObject. */
1971 #endif /* HAVE_NTGUI */
1973 XDestroyImage (ximg
);
1979 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
1980 are width and height of both the image and pixmap. */
1983 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
1989 #ifdef HAVE_X_WINDOWS
1992 xassert (interrupt_input_blocked
);
1993 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
1994 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
1995 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1996 #endif /* HAVE_X_WINDOWS */
1999 #if 0 /* I don't think this is necessary looking at where it is used. */
2000 HDC hdc
= get_frame_dc (f
);
2001 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2002 release_frame_dc (f
, hdc
);
2004 #endif /* HAVE_NTGUI */
2007 xassert (ximg
== pixmap
);
2012 /***********************************************************************
2014 ***********************************************************************/
2016 static unsigned char *slurp_file
P_ ((char *, int *));
2019 /* Find image file FILE. Look in data-directory, then
2020 x-bitmap-file-path. Value is the full name of the file found, or
2021 nil if not found. */
2024 x_find_image_file (file
)
2027 Lisp_Object file_found
, search_path
;
2028 struct gcpro gcpro1
, gcpro2
;
2032 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2033 GCPRO2 (file_found
, search_path
);
2035 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2036 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2048 /* Read FILE into memory. Value is a pointer to a buffer allocated
2049 with xmalloc holding FILE's contents. Value is null if an error
2050 occurred. *SIZE is set to the size of the file. */
2052 static unsigned char *
2053 slurp_file (file
, size
)
2058 unsigned char *buf
= NULL
;
2061 if (stat (file
, &st
) == 0
2062 && (fp
= fopen (file
, "rb")) != NULL
2063 && (buf
= (char *) xmalloc (st
.st_size
),
2064 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2087 /***********************************************************************
2088 MAC Image Load Functions
2089 ***********************************************************************/
2091 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2094 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2098 find_image_fsspec (specified_file
, file
, fss
)
2099 Lisp_Object specified_file
, *file
;
2102 #if TARGET_API_MAC_CARBON
2105 Str255 mac_pathname
;
2109 *file
= x_find_image_file (specified_file
);
2110 if (!STRINGP (*file
))
2111 return fnfErr
; /* file or directory not found;
2112 incomplete pathname */
2113 /* Try to open the image file. */
2114 #if TARGET_API_MAC_CARBON
2115 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2117 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2119 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2121 c2pstr (mac_pathname
);
2122 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2128 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2136 GraphicsImportComponent gi
;
2139 short draw_all_pixels
;
2140 Lisp_Object specified_bg
;
2145 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2149 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2154 /* read from file system spec */
2155 err
= GraphicsImportSetDataFile (gi
, fss
);
2158 image_error ("Cannot set fsspec to graphics importer for '%s'",
2165 /* read from data handle */
2166 err
= GraphicsImportSetDataHandle (gi
, dh
);
2169 image_error ("Cannot set data handle to graphics importer for `%s'",
2174 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2177 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2180 width
= img
->width
= rect
.right
- rect
.left
;
2181 height
= img
->height
= rect
.bottom
- rect
.top
;
2182 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2184 /* Don't check the error code here. It may have an undocumented
2188 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2192 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2194 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2195 if (!STRINGP (specified_bg
) ||
2196 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2198 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2199 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2200 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2201 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2205 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2207 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2212 GetGWorld (&old_port
, &old_gdh
);
2213 SetGWorld (ximg
, NULL
);
2214 bg_color
.red
= color
.red
;
2215 bg_color
.green
= color
.green
;
2216 bg_color
.blue
= color
.blue
;
2217 RGBBackColor (&bg_color
);
2218 #if TARGET_API_MAC_CARBON
2219 GetPortBounds (ximg
, &rect
);
2222 EraseRect (&(ximg
->portRect
));
2224 SetGWorld (old_port
, old_gdh
);
2226 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2227 GraphicsImportDraw (gi
);
2228 CloseComponent (gi
);
2230 /* Maybe fill in the background field while we have ximg handy. */
2231 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2232 IMAGE_BACKGROUND (img
, f
, ximg
);
2234 /* Put the image into the pixmap. */
2235 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2236 x_destroy_x_image (ximg
);
2240 CloseComponent (gi
);
2245 /* Load an image using the QuickTime Graphics Importer.
2246 Note: The alpha channel does not work for PNG images. */
2248 image_load_quicktime (f
, img
, type
)
2253 Lisp_Object specified_file
;
2254 Lisp_Object specified_data
;
2257 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2258 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2260 if (NILP (specified_data
))
2262 /* Read from a file */
2266 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2270 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2272 image_error ("Cannot open `%s'", file
, Qnil
);
2275 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2279 /* Memory source! */
2283 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2286 image_error ("Cannot allocate data handle for `%s'",
2290 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2298 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2299 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2300 So don't use this function directly but determine at runtime
2301 whether it exists. */
2302 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2303 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2304 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2308 init_image_func_pointer ()
2310 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2312 MyCGImageCreateWithPNGDataProvider
2313 = (CGImageCreateWithPNGDataProviderProcType
)
2314 NSAddressOfSymbol (NSLookupAndBindSymbol
2315 ("_CGImageCreateWithPNGDataProvider"));
2318 MyCGImageCreateWithPNGDataProvider
= NULL
;
2323 image_load_quartz2d (f
, img
, png_p
)
2328 Lisp_Object file
, specified_file
;
2329 Lisp_Object specified_data
, specified_bg
;
2330 struct gcpro gcpro1
;
2331 CGDataProviderRef source
;
2335 XImagePtr ximg
= NULL
;
2336 CGContextRef context
;
2339 /* Open the file. */
2340 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2341 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2346 if (NILP (specified_data
))
2351 file
= x_find_image_file (specified_file
);
2352 if (!STRINGP (file
))
2354 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2358 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
2359 kCFStringEncodingUTF8
);
2360 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2361 kCFURLPOSIXPathStyle
, 0);
2363 source
= CGDataProviderCreateWithURL (url
);
2367 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2368 SBYTES (specified_data
), NULL
);
2371 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2372 kCGRenderingIntentDefault
);
2374 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2375 kCGRenderingIntentDefault
);
2377 CGDataProviderRelease (source
);
2381 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2387 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2388 if (!STRINGP (specified_bg
) ||
2389 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2391 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2392 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2393 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2394 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2397 width
= img
->width
= CGImageGetWidth (image
);
2398 height
= img
->height
= CGImageGetHeight (image
);
2399 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2401 CGImageRelease (image
);
2405 rectangle
= CGRectMake (0, 0, width
, height
);
2406 QDBeginCGContext (ximg
, &context
);
2409 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2410 color
.green
/ 65535.0,
2411 color
.blue
/ 65535.0, 1.0);
2412 CGContextFillRect (context
, rectangle
);
2414 CGContextDrawImage (context
, rectangle
, image
);
2415 QDEndCGContext (ximg
, &context
);
2416 CGImageRelease (image
);
2418 /* Maybe fill in the background field while we have ximg handy. */
2419 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2420 IMAGE_BACKGROUND (img
, f
, ximg
);
2422 /* Put the image into the pixmap. */
2423 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2424 x_destroy_x_image (ximg
);
2433 /***********************************************************************
2435 ***********************************************************************/
2437 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2438 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2439 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2440 unsigned char *, unsigned char *));
2441 static int xbm_image_p
P_ ((Lisp_Object object
));
2442 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2443 int *, int *, unsigned char **));
2444 static int xbm_file_p
P_ ((Lisp_Object
));
2447 /* Indices of image specification fields in xbm_format, below. */
2449 enum xbm_keyword_index
2467 /* Vector of image_keyword structures describing the format
2468 of valid XBM image specifications. */
2470 static struct image_keyword xbm_format
[XBM_LAST
] =
2472 {":type", IMAGE_SYMBOL_VALUE
, 1},
2473 {":file", IMAGE_STRING_VALUE
, 0},
2474 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2475 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2476 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2477 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2478 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2479 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2480 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2481 {":relief", IMAGE_INTEGER_VALUE
, 0},
2482 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2483 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2484 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2487 /* Structure describing the image type XBM. */
2489 static struct image_type xbm_type
=
2498 /* Tokens returned from xbm_scan. */
2507 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2508 A valid specification is a list starting with the symbol `image'
2509 The rest of the list is a property list which must contain an
2512 If the specification specifies a file to load, it must contain
2513 an entry `:file FILENAME' where FILENAME is a string.
2515 If the specification is for a bitmap loaded from memory it must
2516 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2517 WIDTH and HEIGHT are integers > 0. DATA may be:
2519 1. a string large enough to hold the bitmap data, i.e. it must
2520 have a size >= (WIDTH + 7) / 8 * HEIGHT
2522 2. a bool-vector of size >= WIDTH * HEIGHT
2524 3. a vector of strings or bool-vectors, one for each line of the
2527 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2528 may not be specified in this case because they are defined in the
2531 Both the file and data forms may contain the additional entries
2532 `:background COLOR' and `:foreground COLOR'. If not present,
2533 foreground and background of the frame on which the image is
2534 displayed is used. */
2537 xbm_image_p (object
)
2540 struct image_keyword kw
[XBM_LAST
];
2542 bcopy (xbm_format
, kw
, sizeof kw
);
2543 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2546 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2548 if (kw
[XBM_FILE
].count
)
2550 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2553 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2555 /* In-memory XBM file. */
2556 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2564 /* Entries for `:width', `:height' and `:data' must be present. */
2565 if (!kw
[XBM_WIDTH
].count
2566 || !kw
[XBM_HEIGHT
].count
2567 || !kw
[XBM_DATA
].count
)
2570 data
= kw
[XBM_DATA
].value
;
2571 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2572 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2574 /* Check type of data, and width and height against contents of
2580 /* Number of elements of the vector must be >= height. */
2581 if (XVECTOR (data
)->size
< height
)
2584 /* Each string or bool-vector in data must be large enough
2585 for one line of the image. */
2586 for (i
= 0; i
< height
; ++i
)
2588 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2593 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2596 else if (BOOL_VECTOR_P (elt
))
2598 if (XBOOL_VECTOR (elt
)->size
< width
)
2605 else if (STRINGP (data
))
2608 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2611 else if (BOOL_VECTOR_P (data
))
2613 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2624 /* Scan a bitmap file. FP is the stream to read from. Value is
2625 either an enumerator from enum xbm_token, or a character for a
2626 single-character token, or 0 at end of file. If scanning an
2627 identifier, store the lexeme of the identifier in SVAL. If
2628 scanning a number, store its value in *IVAL. */
2631 xbm_scan (s
, end
, sval
, ival
)
2632 unsigned char **s
, *end
;
2640 /* Skip white space. */
2641 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2646 else if (isdigit (c
))
2648 int value
= 0, digit
;
2650 if (c
== '0' && *s
< end
)
2653 if (c
== 'x' || c
== 'X')
2660 else if (c
>= 'a' && c
<= 'f')
2661 digit
= c
- 'a' + 10;
2662 else if (c
>= 'A' && c
<= 'F')
2663 digit
= c
- 'A' + 10;
2666 value
= 16 * value
+ digit
;
2669 else if (isdigit (c
))
2673 && (c
= *(*s
)++, isdigit (c
)))
2674 value
= 8 * value
+ c
- '0';
2681 && (c
= *(*s
)++, isdigit (c
)))
2682 value
= 10 * value
+ c
- '0';
2690 else if (isalpha (c
) || c
== '_')
2694 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2701 else if (c
== '/' && **s
== '*')
2703 /* C-style comment. */
2705 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2719 /* Create a Windows bitmap from X bitmap data. */
2721 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2723 static unsigned char swap_nibble
[16]
2724 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2725 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2726 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2727 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2729 unsigned char *bits
, *p
;
2732 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2733 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2734 bits
= (unsigned char *) alloca (height
* w2
);
2735 bzero (bits
, height
* w2
);
2736 for (i
= 0; i
< height
; i
++)
2739 for (j
= 0; j
< w1
; j
++)
2741 /* Bitswap XBM bytes to match how Windows does things. */
2742 unsigned char c
= *data
++;
2743 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2744 | (swap_nibble
[(c
>>4) & 0xf]));
2747 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2752 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2755 COLORREF foreground
, background
;
2757 HDC hdc
, old_img_dc
, new_img_dc
;
2758 HGDIOBJ old_prev
, new_prev
;
2761 hdc
= get_frame_dc (f
);
2762 old_img_dc
= CreateCompatibleDC (hdc
);
2763 new_img_dc
= CreateCompatibleDC (hdc
);
2764 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2765 release_frame_dc (f
, hdc
);
2766 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2767 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2768 SetTextColor (new_img_dc
, foreground
);
2769 SetBkColor (new_img_dc
, background
);
2771 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2774 SelectObject (old_img_dc
, old_prev
);
2775 SelectObject (new_img_dc
, new_prev
);
2776 DeleteDC (old_img_dc
);
2777 DeleteDC (new_img_dc
);
2778 DeleteObject (img
->pixmap
);
2779 if (new_pixmap
== 0)
2780 fprintf (stderr
, "Failed to convert image to color.\n");
2782 img
->pixmap
= new_pixmap
;
2785 #define XBM_BIT_SHUFFLE(b) (~(b))
2789 #define XBM_BIT_SHUFFLE(b) (b)
2791 #endif /* HAVE_NTGUI */
2795 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2799 RGB_PIXEL_COLOR fg
, bg
;
2800 int non_default_colors
;
2804 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2806 /* If colors were specified, transfer the bitmap to a color one. */
2807 if (non_default_colors
)
2808 convert_mono_to_color_image (f
, img
, fg
, bg
);
2811 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2814 img
->width
, img
->height
,
2816 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2817 #endif /* HAVE_NTGUI */
2822 /* Replacement for XReadBitmapFileData which isn't available under old
2823 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2824 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2825 the image. Return in *DATA the bitmap data allocated with xmalloc.
2826 Value is non-zero if successful. DATA null means just test if
2827 CONTENTS looks like an in-memory XBM file. */
2830 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2831 unsigned char *contents
, *end
;
2832 int *width
, *height
;
2833 unsigned char **data
;
2835 unsigned char *s
= contents
;
2836 char buffer
[BUFSIZ
];
2839 int bytes_per_line
, i
, nbytes
;
2845 LA1 = xbm_scan (&s, end, buffer, &value)
2847 #define expect(TOKEN) \
2848 if (LA1 != (TOKEN)) \
2853 #define expect_ident(IDENT) \
2854 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2859 *width
= *height
= -1;
2862 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2864 /* Parse defines for width, height and hot-spots. */
2868 expect_ident ("define");
2869 expect (XBM_TK_IDENT
);
2871 if (LA1
== XBM_TK_NUMBER
);
2873 char *p
= strrchr (buffer
, '_');
2874 p
= p
? p
+ 1 : buffer
;
2875 if (strcmp (p
, "width") == 0)
2877 else if (strcmp (p
, "height") == 0)
2880 expect (XBM_TK_NUMBER
);
2883 if (*width
< 0 || *height
< 0)
2885 else if (data
== NULL
)
2888 /* Parse bits. Must start with `static'. */
2889 expect_ident ("static");
2890 if (LA1
== XBM_TK_IDENT
)
2892 if (strcmp (buffer
, "unsigned") == 0)
2895 expect_ident ("char");
2897 else if (strcmp (buffer
, "short") == 0)
2901 if (*width
% 16 && *width
% 16 < 9)
2904 else if (strcmp (buffer
, "char") == 0)
2912 expect (XBM_TK_IDENT
);
2918 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2919 nbytes
= bytes_per_line
* *height
;
2920 p
= *data
= (char *) xmalloc (nbytes
);
2924 for (i
= 0; i
< nbytes
; i
+= 2)
2927 expect (XBM_TK_NUMBER
);
2929 *p
++ = XBM_BIT_SHUFFLE (val
);
2930 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2931 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2933 if (LA1
== ',' || LA1
== '}')
2941 for (i
= 0; i
< nbytes
; ++i
)
2944 expect (XBM_TK_NUMBER
);
2946 *p
++ = XBM_BIT_SHUFFLE (val
);
2948 if (LA1
== ',' || LA1
== '}')
2973 /* Load XBM image IMG which will be displayed on frame F from buffer
2974 CONTENTS. END is the end of the buffer. Value is non-zero if
2978 xbm_load_image (f
, img
, contents
, end
)
2981 unsigned char *contents
, *end
;
2984 unsigned char *data
;
2987 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
2990 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
2991 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
2992 int non_default_colors
= 0;
2995 xassert (img
->width
> 0 && img
->height
> 0);
2997 /* Get foreground and background colors, maybe allocate colors. */
2998 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3001 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3002 non_default_colors
= 1;
3004 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3007 background
= x_alloc_image_color (f
, img
, value
, background
);
3008 img
->background
= background
;
3009 img
->background_valid
= 1;
3010 non_default_colors
= 1;
3013 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3014 foreground
, background
,
3015 non_default_colors
);
3018 if (img
->pixmap
== NO_PIXMAP
)
3020 x_clear_image (f
, img
);
3021 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3027 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3033 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3040 return (STRINGP (data
)
3041 && xbm_read_bitmap_data (SDATA (data
),
3048 /* Fill image IMG which is used on frame F with pixmap data. Value is
3049 non-zero if successful. */
3057 Lisp_Object file_name
;
3059 xassert (xbm_image_p (img
->spec
));
3061 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3062 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3063 if (STRINGP (file_name
))
3066 unsigned char *contents
;
3068 struct gcpro gcpro1
;
3070 file
= x_find_image_file (file_name
);
3072 if (!STRINGP (file
))
3074 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3079 contents
= slurp_file (SDATA (file
), &size
);
3080 if (contents
== NULL
)
3082 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3087 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3092 struct image_keyword fmt
[XBM_LAST
];
3094 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3095 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3096 int non_default_colors
= 0;
3099 int in_memory_file_p
= 0;
3101 /* See if data looks like an in-memory XBM file. */
3102 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3103 in_memory_file_p
= xbm_file_p (data
);
3105 /* Parse the image specification. */
3106 bcopy (xbm_format
, fmt
, sizeof fmt
);
3107 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3110 /* Get specified width, and height. */
3111 if (!in_memory_file_p
)
3113 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3114 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3115 xassert (img
->width
> 0 && img
->height
> 0);
3118 /* Get foreground and background colors, maybe allocate colors. */
3119 if (fmt
[XBM_FOREGROUND
].count
3120 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3122 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3124 non_default_colors
= 1;
3127 if (fmt
[XBM_BACKGROUND
].count
3128 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3130 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3132 non_default_colors
= 1;
3135 if (in_memory_file_p
)
3136 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3145 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3147 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3148 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3150 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3152 bcopy (SDATA (line
), p
, nbytes
);
3154 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3157 else if (STRINGP (data
))
3158 bits
= SDATA (data
);
3160 bits
= XBOOL_VECTOR (data
)->data
;
3162 /* Create the pixmap. */
3164 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3165 foreground
, background
,
3166 non_default_colors
);
3171 image_error ("Unable to create pixmap for XBM image `%s'",
3173 x_clear_image (f
, img
);
3183 /***********************************************************************
3185 ***********************************************************************/
3187 #if defined (HAVE_XPM) || defined (MAC_OS)
3189 static int xpm_image_p
P_ ((Lisp_Object object
));
3190 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3191 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3193 #endif /* HAVE_XPM || MAC_OS */
3197 /* Indicate to xpm.h that we don't have Xlib. */
3199 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3200 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3201 #define XColor xpm_XColor
3202 #define XImage xpm_XImage
3203 #define Display xpm_Display
3204 #define PIXEL_ALREADY_TYPEDEFED
3205 #include "X11/xpm.h"
3210 #undef PIXEL_ALREADY_TYPEDEFED
3212 #include "X11/xpm.h"
3213 #endif /* HAVE_NTGUI */
3214 #endif /* HAVE_XPM */
3216 #if defined (HAVE_XPM) || defined (MAC_OS)
3217 /* The symbol `xpm' identifying XPM-format images. */
3221 /* Indices of image specification fields in xpm_format, below. */
3223 enum xpm_keyword_index
3239 /* Vector of image_keyword structures describing the format
3240 of valid XPM image specifications. */
3242 static struct image_keyword xpm_format
[XPM_LAST
] =
3244 {":type", IMAGE_SYMBOL_VALUE
, 1},
3245 {":file", IMAGE_STRING_VALUE
, 0},
3246 {":data", IMAGE_STRING_VALUE
, 0},
3247 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3248 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3249 {":relief", IMAGE_INTEGER_VALUE
, 0},
3250 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3251 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3252 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3253 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3254 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3257 /* Structure describing the image type XPM. */
3259 static struct image_type xpm_type
=
3268 #ifdef HAVE_X_WINDOWS
3270 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3271 functions for allocating image colors. Our own functions handle
3272 color allocation failures more gracefully than the ones on the XPM
3275 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3276 #define ALLOC_XPM_COLORS
3278 #endif /* HAVE_X_WINDOWS */
3280 #ifdef ALLOC_XPM_COLORS
3282 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3283 static void xpm_free_color_cache
P_ ((void));
3284 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3285 static int xpm_color_bucket
P_ ((char *));
3286 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3289 /* An entry in a hash table used to cache color definitions of named
3290 colors. This cache is necessary to speed up XPM image loading in
3291 case we do color allocations ourselves. Without it, we would need
3292 a call to XParseColor per pixel in the image. */
3294 struct xpm_cached_color
3296 /* Next in collision chain. */
3297 struct xpm_cached_color
*next
;
3299 /* Color definition (RGB and pixel color). */
3306 /* The hash table used for the color cache, and its bucket vector
3309 #define XPM_COLOR_CACHE_BUCKETS 1001
3310 struct xpm_cached_color
**xpm_color_cache
;
3312 /* Initialize the color cache. */
3315 xpm_init_color_cache (f
, attrs
)
3317 XpmAttributes
*attrs
;
3319 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3320 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3321 memset (xpm_color_cache
, 0, nbytes
);
3322 init_color_table ();
3324 if (attrs
->valuemask
& XpmColorSymbols
)
3329 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3330 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3331 attrs
->colorsymbols
[i
].value
, &color
))
3333 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3335 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3340 /* Free the color cache. */
3343 xpm_free_color_cache ()
3345 struct xpm_cached_color
*p
, *next
;
3348 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3349 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3355 xfree (xpm_color_cache
);
3356 xpm_color_cache
= NULL
;
3357 free_color_table ();
3360 /* Return the bucket index for color named COLOR_NAME in the color
3364 xpm_color_bucket (color_name
)
3370 for (s
= color_name
; *s
; ++s
)
3372 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3376 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3377 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3380 static struct xpm_cached_color
*
3381 xpm_cache_color (f
, color_name
, color
, bucket
)
3388 struct xpm_cached_color
*p
;
3391 bucket
= xpm_color_bucket (color_name
);
3393 nbytes
= sizeof *p
+ strlen (color_name
);
3394 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3395 strcpy (p
->name
, color_name
);
3397 p
->next
= xpm_color_cache
[bucket
];
3398 xpm_color_cache
[bucket
] = p
;
3402 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3403 return the cached definition in *COLOR. Otherwise, make a new
3404 entry in the cache and allocate the color. Value is zero if color
3405 allocation failed. */
3408 xpm_lookup_color (f
, color_name
, color
)
3413 struct xpm_cached_color
*p
;
3414 int h
= xpm_color_bucket (color_name
);
3416 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3417 if (strcmp (p
->name
, color_name
) == 0)
3422 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3425 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3427 p
= xpm_cache_color (f
, color_name
, color
, h
);
3429 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3430 with transparency, and it's useful. */
3431 else if (strcmp ("opaque", color_name
) == 0)
3433 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3434 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3435 p
= xpm_cache_color (f
, color_name
, color
, h
);
3442 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3443 CLOSURE is a pointer to the frame on which we allocate the
3444 color. Return in *COLOR the allocated color. Value is non-zero
3448 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3455 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3459 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3460 is a pointer to the frame on which we allocate the color. Value is
3461 non-zero if successful. */
3464 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3474 #endif /* ALLOC_XPM_COLORS */
3479 /* XPM library details. */
3481 DEF_IMGLIB_FN (XpmFreeAttributes
);
3482 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3483 DEF_IMGLIB_FN (XpmReadFileToImage
);
3484 DEF_IMGLIB_FN (XImageFree
);
3488 init_xpm_functions (void)
3492 if (!(library
= LoadLibrary ("libXpm.dll")))
3495 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3496 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3497 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3498 LOAD_IMGLIB_FN (library
, XImageFree
);
3502 #endif /* HAVE_NTGUI */
3505 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3506 for XPM images. Such a list must consist of conses whose car and
3510 xpm_valid_color_symbols_p (color_symbols
)
3511 Lisp_Object color_symbols
;
3513 while (CONSP (color_symbols
))
3515 Lisp_Object sym
= XCAR (color_symbols
);
3517 || !STRINGP (XCAR (sym
))
3518 || !STRINGP (XCDR (sym
)))
3520 color_symbols
= XCDR (color_symbols
);
3523 return NILP (color_symbols
);
3527 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3530 xpm_image_p (object
)
3533 struct image_keyword fmt
[XPM_LAST
];
3534 bcopy (xpm_format
, fmt
, sizeof fmt
);
3535 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3536 /* Either `:file' or `:data' must be present. */
3537 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3538 /* Either no `:color-symbols' or it's a list of conses
3539 whose car and cdr are strings. */
3540 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3541 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3544 #endif /* HAVE_XPM || MAC_OS */
3546 /* Load image IMG which will be displayed on frame F. Value is
3547 non-zero if successful. */
3557 XpmAttributes attrs
;
3558 Lisp_Object specified_file
, color_symbols
;
3561 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3562 #endif /* HAVE_NTGUI */
3564 /* Configure the XPM lib. Use the visual of frame F. Allocate
3565 close colors. Return colors allocated. */
3566 bzero (&attrs
, sizeof attrs
);
3569 attrs
.visual
= FRAME_X_VISUAL (f
);
3570 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3571 attrs
.valuemask
|= XpmVisual
;
3572 attrs
.valuemask
|= XpmColormap
;
3573 #endif /* HAVE_NTGUI */
3575 #ifdef ALLOC_XPM_COLORS
3576 /* Allocate colors with our own functions which handle
3577 failing color allocation more gracefully. */
3578 attrs
.color_closure
= f
;
3579 attrs
.alloc_color
= xpm_alloc_color
;
3580 attrs
.free_colors
= xpm_free_colors
;
3581 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3582 #else /* not ALLOC_XPM_COLORS */
3583 /* Let the XPM lib allocate colors. */
3584 attrs
.valuemask
|= XpmReturnAllocPixels
;
3585 #ifdef XpmAllocCloseColors
3586 attrs
.alloc_close_colors
= 1;
3587 attrs
.valuemask
|= XpmAllocCloseColors
;
3588 #else /* not XpmAllocCloseColors */
3589 attrs
.closeness
= 600;
3590 attrs
.valuemask
|= XpmCloseness
;
3591 #endif /* not XpmAllocCloseColors */
3592 #endif /* ALLOC_XPM_COLORS */
3594 /* If image specification contains symbolic color definitions, add
3595 these to `attrs'. */
3596 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3597 if (CONSP (color_symbols
))
3600 XpmColorSymbol
*xpm_syms
;
3603 attrs
.valuemask
|= XpmColorSymbols
;
3605 /* Count number of symbols. */
3606 attrs
.numsymbols
= 0;
3607 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3610 /* Allocate an XpmColorSymbol array. */
3611 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3612 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3613 bzero (xpm_syms
, size
);
3614 attrs
.colorsymbols
= xpm_syms
;
3616 /* Fill the color symbol array. */
3617 for (tail
= color_symbols
, i
= 0;
3619 ++i
, tail
= XCDR (tail
))
3621 Lisp_Object name
= XCAR (XCAR (tail
));
3622 Lisp_Object color
= XCDR (XCAR (tail
));
3623 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3624 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3625 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3626 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3630 /* Create a pixmap for the image, either from a file, or from a
3631 string buffer containing data in the same format as an XPM file. */
3632 #ifdef ALLOC_XPM_COLORS
3633 xpm_init_color_cache (f
, &attrs
);
3636 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3640 HDC frame_dc
= get_frame_dc (f
);
3641 hdc
= CreateCompatibleDC (frame_dc
);
3642 release_frame_dc (f
, frame_dc
);
3644 #endif /* HAVE_NTGUI */
3646 if (STRINGP (specified_file
))
3648 Lisp_Object file
= x_find_image_file (specified_file
);
3649 if (!STRINGP (file
))
3651 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3656 /* XpmReadFileToPixmap is not available in the Windows port of
3657 libxpm. But XpmReadFileToImage almost does what we want. */
3658 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3659 &xpm_image
, &xpm_mask
,
3662 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3663 SDATA (file
), &img
->pixmap
, &img
->mask
,
3665 #endif /* HAVE_NTGUI */
3669 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3671 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3672 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3673 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3674 &xpm_image
, &xpm_mask
,
3677 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3679 &img
->pixmap
, &img
->mask
,
3681 #endif /* HAVE_NTGUI */
3684 if (rc
== XpmSuccess
)
3686 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3687 img
->colors
= colors_in_color_table (&img
->ncolors
);
3688 #else /* not ALLOC_XPM_COLORS */
3692 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3693 plus some duplicate attributes. */
3694 if (xpm_image
&& xpm_image
->bitmap
)
3696 img
->pixmap
= xpm_image
->bitmap
;
3697 /* XImageFree in libXpm frees XImage struct without destroying
3698 the bitmap, which is what we want. */
3699 fn_XImageFree (xpm_image
);
3701 if (xpm_mask
&& xpm_mask
->bitmap
)
3703 /* The mask appears to be inverted compared with what we expect.
3704 TODO: invert our expectations. See other places where we
3705 have to invert bits because our idea of masks is backwards. */
3707 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3709 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3710 SelectObject (hdc
, old_obj
);
3712 img
->mask
= xpm_mask
->bitmap
;
3713 fn_XImageFree (xpm_mask
);
3718 #endif /* HAVE_NTGUI */
3720 /* Remember allocated colors. */
3721 img
->ncolors
= attrs
.nalloc_pixels
;
3722 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3723 * sizeof *img
->colors
);
3724 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3726 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3727 #ifdef DEBUG_X_COLORS
3728 register_color (img
->colors
[i
]);
3731 #endif /* not ALLOC_XPM_COLORS */
3733 img
->width
= attrs
.width
;
3734 img
->height
= attrs
.height
;
3735 xassert (img
->width
> 0 && img
->height
> 0);
3737 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3739 fn_XpmFreeAttributes (&attrs
);
3741 XpmFreeAttributes (&attrs
);
3742 #endif /* HAVE_NTGUI */
3748 #endif /* HAVE_NTGUI */
3753 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3756 case XpmFileInvalid
:
3757 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3761 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3764 case XpmColorFailed
:
3765 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3769 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3774 #ifdef ALLOC_XPM_COLORS
3775 xpm_free_color_cache ();
3777 return rc
== XpmSuccess
;
3780 #endif /* HAVE_XPM */
3784 /* XPM support functions for Mac OS where libxpm is not available.
3785 Only XPM version 3 (without any extensions) is supported. */
3787 static int xpm_scan
P_ ((unsigned char **, unsigned char *,
3788 unsigned char **, int *));
3789 static Lisp_Object xpm_make_color_table_v
3790 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3791 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3792 static void xpm_put_color_table_v
P_ ((Lisp_Object
, unsigned char *,
3794 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3795 unsigned char *, int));
3796 static Lisp_Object xpm_make_color_table_h
3797 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3798 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3799 static void xpm_put_color_table_h
P_ ((Lisp_Object
, unsigned char *,
3801 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3802 unsigned char *, int));
3803 static int xpm_str_to_color_key
P_ ((char *));
3804 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3805 unsigned char *, unsigned char *));
3807 /* Tokens returned from xpm_scan. */
3816 /* Scan an XPM data and return a character (< 256) or a token defined
3817 by enum xpm_token above. *S and END are the start (inclusive) and
3818 the end (exclusive) addresses of the data, respectively. Advance
3819 *S while scanning. If token is either XPM_TK_IDENT or
3820 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3821 length of the corresponding token, respectively. */
3824 xpm_scan (s
, end
, beg
, len
)
3825 unsigned char **s
, *end
, **beg
;
3832 /* Skip white-space. */
3833 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3836 /* gnus-pointer.xpm uses '-' in its identifier.
3837 sb-dir-plus.xpm uses '+' in its identifier. */
3838 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
3842 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
3845 return XPM_TK_IDENT
;
3850 while (*s
< end
&& **s
!= '"')
3855 return XPM_TK_STRING
;
3859 if (*s
< end
&& **s
== '*')
3861 /* C-style comment. */
3865 while (*s
< end
&& *(*s
)++ != '*')
3868 while (*s
< end
&& **s
!= '/');
3882 /* Functions for color table lookup in XPM data. A Key is a string
3883 specifying the color of each pixel in XPM data. A value is either
3884 an integer that specifies a pixel color, Qt that specifies
3885 transparency, or Qnil for the unspecified color. If the length of
3886 the key string is one, a vector is used as a table. Otherwise, a
3887 hash table is used. */
3890 xpm_make_color_table_v (put_func
, get_func
)
3891 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3892 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3894 *put_func
= xpm_put_color_table_v
;
3895 *get_func
= xpm_get_color_table_v
;
3896 return Fmake_vector (make_number (256), Qnil
);
3900 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
3901 Lisp_Object color_table
;
3902 unsigned char *chars_start
;
3906 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
3910 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
3911 Lisp_Object color_table
;
3912 unsigned char *chars_start
;
3915 return XVECTOR (color_table
)->contents
[*chars_start
];
3919 xpm_make_color_table_h (put_func
, get_func
)
3920 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3921 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3923 *put_func
= xpm_put_color_table_h
;
3924 *get_func
= xpm_get_color_table_h
;
3925 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
3926 make_float (DEFAULT_REHASH_SIZE
),
3927 make_float (DEFAULT_REHASH_THRESHOLD
),
3932 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
3933 Lisp_Object color_table
;
3934 unsigned char *chars_start
;
3938 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
3940 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
3942 hash_lookup (table
, chars
, &hash_code
);
3943 hash_put (table
, chars
, color
, hash_code
);
3947 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
3948 Lisp_Object color_table
;
3949 unsigned char *chars_start
;
3952 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
3953 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
3956 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
3959 enum xpm_color_key
{
3967 static char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
3970 xpm_str_to_color_key (s
)
3976 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
3978 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
3984 xpm_load_image (f
, img
, contents
, end
)
3987 unsigned char *contents
, *end
;
3989 unsigned char *s
= contents
, *beg
, *str
;
3990 unsigned char buffer
[BUFSIZ
];
3991 int width
, height
, x
, y
;
3992 int num_colors
, chars_per_pixel
;
3994 void (*put_color_table
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3995 Lisp_Object (*get_color_table
) (Lisp_Object
, unsigned char *, int);
3996 Lisp_Object frame
, color_symbols
, color_table
;
3997 int best_key
, have_mask
= 0;
3998 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4001 LA1 = xpm_scan (&s, end, &beg, &len)
4003 #define expect(TOKEN) \
4004 if (LA1 != (TOKEN)) \
4009 #define expect_ident(IDENT) \
4010 if (LA1 == XPM_TK_IDENT \
4011 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4016 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4020 expect_ident ("static");
4021 expect_ident ("char");
4023 expect (XPM_TK_IDENT
);
4028 expect (XPM_TK_STRING
);
4031 memcpy (buffer
, beg
, len
);
4033 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4034 &num_colors
, &chars_per_pixel
) != 4
4035 || width
<= 0 || height
<= 0
4036 || num_colors
<= 0 || chars_per_pixel
<= 0)
4040 XSETFRAME (frame
, f
);
4041 if (!NILP (Fxw_display_color_p (frame
)))
4042 best_key
= XPM_COLOR_KEY_C
;
4043 else if (!NILP (Fx_display_grayscale_p (frame
)))
4044 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4045 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4047 best_key
= XPM_COLOR_KEY_M
;
4049 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4050 if (chars_per_pixel
== 1)
4051 color_table
= xpm_make_color_table_v (&put_color_table
,
4054 color_table
= xpm_make_color_table_h (&put_color_table
,
4057 while (num_colors
-- > 0)
4059 unsigned char *color
, *max_color
;
4060 int key
, next_key
, max_key
= 0;
4061 Lisp_Object symbol_color
= Qnil
, color_val
;
4064 expect (XPM_TK_STRING
);
4065 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4067 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4068 buffer
[len
- chars_per_pixel
] = '\0';
4070 str
= strtok (buffer
, " \t");
4073 key
= xpm_str_to_color_key (str
);
4078 color
= strtok (NULL
, " \t");
4082 while (str
= strtok (NULL
, " \t"))
4084 next_key
= xpm_str_to_color_key (str
);
4087 color
[strlen (color
)] = ' ';
4090 if (key
== XPM_COLOR_KEY_S
)
4092 if (NILP (symbol_color
))
4093 symbol_color
= build_string (color
);
4095 else if (max_key
< key
&& key
<= best_key
)
4105 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4107 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4109 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4110 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4112 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4114 color_val
= make_number (cdef
.pixel
);
4116 if (NILP (color_val
) && max_key
> 0)
4117 if (xstricmp (max_color
, "None") == 0)
4119 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4120 color_val
= make_number (cdef
.pixel
);
4121 if (!NILP (color_val
))
4122 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4127 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4128 &ximg
, &img
->pixmap
)
4129 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4130 &mask_img
, &img
->mask
))
4132 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4136 for (y
= 0; y
< height
; y
++)
4138 expect (XPM_TK_STRING
);
4140 if (len
< width
* chars_per_pixel
)
4142 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4144 Lisp_Object color_val
=
4145 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4147 XPutPixel (ximg
, x
, y
,
4148 (INTEGERP (color_val
) ? XINT (color_val
)
4149 : FRAME_FOREGROUND_PIXEL (f
)));
4150 XPutPixel (mask_img
, x
, y
,
4151 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW (f
)
4152 : (have_mask
= 1, PIX_MASK_RETAIN (f
))));
4159 img
->height
= height
;
4161 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4162 x_destroy_x_image (ximg
);
4165 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4166 x_destroy_x_image (mask_img
);
4170 x_destroy_x_image (mask_img
);
4171 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4172 img
->mask
= NO_PIXMAP
;
4178 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4180 x_destroy_x_image (ximg
);
4181 x_destroy_x_image (mask_img
);
4182 x_clear_image (f
, img
);
4196 Lisp_Object file_name
;
4198 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4199 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4200 if (STRINGP (file_name
))
4203 unsigned char *contents
;
4205 struct gcpro gcpro1
;
4207 file
= x_find_image_file (file_name
);
4209 if (!STRINGP (file
))
4211 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4216 contents
= slurp_file (SDATA (file
), &size
);
4217 if (contents
== NULL
)
4219 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4224 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4232 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4233 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4234 SDATA (data
) + SBYTES (data
));
4244 /***********************************************************************
4246 ***********************************************************************/
4248 #ifdef COLOR_TABLE_SUPPORT
4250 /* An entry in the color table mapping an RGB color to a pixel color. */
4255 unsigned long pixel
;
4257 /* Next in color table collision list. */
4258 struct ct_color
*next
;
4261 /* The bucket vector size to use. Must be prime. */
4265 /* Value is a hash of the RGB color given by R, G, and B. */
4267 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4269 /* The color hash table. */
4271 struct ct_color
**ct_table
;
4273 /* Number of entries in the color table. */
4275 int ct_colors_allocated
;
4277 /* Initialize the color table. */
4282 int size
= CT_SIZE
* sizeof (*ct_table
);
4283 ct_table
= (struct ct_color
**) xmalloc (size
);
4284 bzero (ct_table
, size
);
4285 ct_colors_allocated
= 0;
4289 /* Free memory associated with the color table. */
4295 struct ct_color
*p
, *next
;
4297 for (i
= 0; i
< CT_SIZE
; ++i
)
4298 for (p
= ct_table
[i
]; p
; p
= next
)
4309 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4310 entry for that color already is in the color table, return the
4311 pixel color of that entry. Otherwise, allocate a new color for R,
4312 G, B, and make an entry in the color table. */
4314 static unsigned long
4315 lookup_rgb_color (f
, r
, g
, b
)
4319 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4320 int i
= hash
% CT_SIZE
;
4322 Display_Info
*dpyinfo
;
4324 /* Handle TrueColor visuals specially, which improves performance by
4325 two orders of magnitude. Freeing colors on TrueColor visuals is
4326 a nop, and pixel colors specify RGB values directly. See also
4327 the Xlib spec, chapter 3.1. */
4328 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4329 if (dpyinfo
->red_bits
> 0)
4331 unsigned long pr
, pg
, pb
;
4333 /* Apply gamma-correction like normal color allocation does. */
4337 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4338 gamma_correct (f
, &color
);
4339 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4342 /* Scale down RGB values to the visual's bits per RGB, and shift
4343 them to the right position in the pixel color. Note that the
4344 original RGB values are 16-bit values, as usual in X. */
4345 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4346 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4347 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4349 /* Assemble the pixel color. */
4350 return pr
| pg
| pb
;
4353 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4354 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4360 #ifdef HAVE_X_WINDOWS
4369 cmap
= FRAME_X_COLORMAP (f
);
4370 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4373 ++ct_colors_allocated
;
4374 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4378 p
->pixel
= color
.pixel
;
4379 p
->next
= ct_table
[i
];
4383 return FRAME_FOREGROUND_PIXEL (f
);
4388 color
= PALETTERGB (r
, g
, b
);
4390 color
= RGB_TO_ULONG (r
, g
, b
);
4391 #endif /* HAVE_NTGUI */
4392 ++ct_colors_allocated
;
4393 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4398 p
->next
= ct_table
[i
];
4400 #endif /* HAVE_X_WINDOWS */
4408 /* Look up pixel color PIXEL which is used on frame F in the color
4409 table. If not already present, allocate it. Value is PIXEL. */
4411 static unsigned long
4412 lookup_pixel_color (f
, pixel
)
4414 unsigned long pixel
;
4416 int i
= pixel
% CT_SIZE
;
4419 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4420 if (p
->pixel
== pixel
)
4429 #ifdef HAVE_X_WINDOWS
4430 cmap
= FRAME_X_COLORMAP (f
);
4431 color
.pixel
= pixel
;
4432 x_query_color (f
, &color
);
4433 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4436 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4437 color
.pixel
= pixel
;
4438 XQueryColor (NULL
, cmap
, &color
);
4439 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4441 #endif /* HAVE_X_WINDOWS */
4445 ++ct_colors_allocated
;
4447 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4452 p
->next
= ct_table
[i
];
4456 return FRAME_FOREGROUND_PIXEL (f
);
4462 /* Value is a vector of all pixel colors contained in the color table,
4463 allocated via xmalloc. Set *N to the number of colors. */
4465 static unsigned long *
4466 colors_in_color_table (n
)
4471 unsigned long *colors
;
4473 if (ct_colors_allocated
== 0)
4480 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4482 *n
= ct_colors_allocated
;
4484 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4485 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4486 colors
[j
++] = p
->pixel
;
4492 #else /* COLOR_TABLE_SUPPORT */
4494 static unsigned long
4495 lookup_rgb_color (f
, r
, g
, b
)
4499 unsigned long pixel
;
4502 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4503 gamma_correct (f
, &pixel
);
4507 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4508 #endif /* HAVE_NTGUI */
4517 #endif /* COLOR_TABLE_SUPPORT */
4520 /***********************************************************************
4522 ***********************************************************************/
4524 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4525 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4526 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4529 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4530 #endif /* HAVE_NTGUI */
4532 /* Non-zero means draw a cross on images having `:conversion
4535 int cross_disabled_images
;
4537 /* Edge detection matrices for different edge-detection
4540 static int emboss_matrix
[9] = {
4542 2, -1, 0, /* y - 1 */
4544 0, 1, -2 /* y + 1 */
4547 static int laplace_matrix
[9] = {
4549 1, 0, 0, /* y - 1 */
4551 0, 0, -1 /* y + 1 */
4554 /* Value is the intensity of the color whose red/green/blue values
4557 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4560 /* On frame F, return an array of XColor structures describing image
4561 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4562 non-zero means also fill the red/green/blue members of the XColor
4563 structures. Value is a pointer to the array of XColors structures,
4564 allocated with xmalloc; it must be freed by the caller. */
4567 x_to_xcolors (f
, img
, rgb_p
)
4574 XImagePtr_or_DC ximg
;
4578 #endif /* HAVE_NTGUI */
4580 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4583 /* Get the X image IMG->pixmap. */
4584 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4585 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4587 /* Load the image into a memory device context. */
4588 hdc
= get_frame_dc (f
);
4589 ximg
= CreateCompatibleDC (hdc
);
4590 release_frame_dc (f
, hdc
);
4591 prev
= SelectObject (ximg
, img
->pixmap
);
4592 #endif /* HAVE_NTGUI */
4594 /* Fill the `pixel' members of the XColor array. I wished there
4595 were an easy and portable way to circumvent XGetPixel. */
4597 for (y
= 0; y
< img
->height
; ++y
)
4601 #ifdef HAVE_X_WINDOWS
4602 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4603 p
->pixel
= XGetPixel (ximg
, x
, y
);
4605 x_query_colors (f
, row
, img
->width
);
4609 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4611 /* W32_TODO: palette support needed here? */
4612 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4616 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4617 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4618 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4621 p
->red
= 256 * GetRValue (p
->pixel
);
4622 p
->green
= 256 * GetGValue (p
->pixel
);
4623 p
->blue
= 256 * GetBValue (p
->pixel
);
4624 #endif /* HAVE_NTGUI */
4627 #endif /* HAVE_X_WINDOWS */
4630 Destroy_Image (ximg
, prev
);
4637 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4638 created with CreateDIBSection, with the pointer to the bit values
4639 stored in ximg->data. */
4641 static void XPutPixel (ximg
, x
, y
, color
)
4646 int width
= ximg
->info
.bmiHeader
.biWidth
;
4647 int height
= ximg
->info
.bmiHeader
.biHeight
;
4648 unsigned char * pixel
;
4650 /* True color images. */
4651 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4653 int rowbytes
= width
* 3;
4654 /* Ensure scanlines are aligned on 4 byte boundaries. */
4656 rowbytes
+= 4 - (rowbytes
% 4);
4658 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4659 /* Windows bitmaps are in BGR order. */
4660 *pixel
= GetBValue (color
);
4661 *(pixel
+ 1) = GetGValue (color
);
4662 *(pixel
+ 2) = GetRValue (color
);
4664 /* Monochrome images. */
4665 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4667 int rowbytes
= width
/ 8;
4668 /* Ensure scanlines are aligned on 4 byte boundaries. */
4670 rowbytes
+= 4 - (rowbytes
% 4);
4671 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4672 /* Filter out palette info. */
4673 if (color
& 0x00ffffff)
4674 *pixel
= *pixel
| (1 << x
% 8);
4676 *pixel
= *pixel
& ~(1 << x
% 8);
4679 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4682 #endif /* HAVE_NTGUI */
4684 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4685 RGB members are set. F is the frame on which this all happens.
4686 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4689 x_from_xcolors (f
, img
, colors
)
4699 init_color_table ();
4701 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4704 for (y
= 0; y
< img
->height
; ++y
)
4705 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4707 unsigned long pixel
;
4708 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4709 XPutPixel (oimg
, x
, y
, pixel
);
4713 x_clear_image_1 (f
, img
, 1, 0, 1);
4715 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4716 x_destroy_x_image (oimg
);
4717 img
->pixmap
= pixmap
;
4718 #ifdef COLOR_TABLE_SUPPORT
4719 img
->colors
= colors_in_color_table (&img
->ncolors
);
4720 free_color_table ();
4721 #endif /* COLOR_TABLE_SUPPORT */
4725 /* On frame F, perform edge-detection on image IMG.
4727 MATRIX is a nine-element array specifying the transformation
4728 matrix. See emboss_matrix for an example.
4730 COLOR_ADJUST is a color adjustment added to each pixel of the
4734 x_detect_edges (f
, img
, matrix
, color_adjust
)
4737 int matrix
[9], color_adjust
;
4739 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4743 for (i
= sum
= 0; i
< 9; ++i
)
4744 sum
+= abs (matrix
[i
]);
4746 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4748 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4750 for (y
= 0; y
< img
->height
; ++y
)
4752 p
= COLOR (new, 0, y
);
4753 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4754 p
= COLOR (new, img
->width
- 1, y
);
4755 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4758 for (x
= 1; x
< img
->width
- 1; ++x
)
4760 p
= COLOR (new, x
, 0);
4761 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4762 p
= COLOR (new, x
, img
->height
- 1);
4763 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4766 for (y
= 1; y
< img
->height
- 1; ++y
)
4768 p
= COLOR (new, 1, y
);
4770 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4772 int r
, g
, b
, y1
, x1
;
4775 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4776 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4779 XColor
*t
= COLOR (colors
, x1
, y1
);
4780 r
+= matrix
[i
] * t
->red
;
4781 g
+= matrix
[i
] * t
->green
;
4782 b
+= matrix
[i
] * t
->blue
;
4785 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4786 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4787 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4788 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4793 x_from_xcolors (f
, img
, new);
4799 /* Perform the pre-defined `emboss' edge-detection on image IMG
4807 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4811 /* Transform image IMG which is used on frame F with a Laplace
4812 edge-detection algorithm. The result is an image that can be used
4813 to draw disabled buttons, for example. */
4820 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4824 /* Perform edge-detection on image IMG on frame F, with specified
4825 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4827 MATRIX must be either
4829 - a list of at least 9 numbers in row-major form
4830 - a vector of at least 9 numbers
4832 COLOR_ADJUST nil means use a default; otherwise it must be a
4836 x_edge_detection (f
, img
, matrix
, color_adjust
)
4839 Lisp_Object matrix
, color_adjust
;
4847 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4848 ++i
, matrix
= XCDR (matrix
))
4849 trans
[i
] = XFLOATINT (XCAR (matrix
));
4851 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4853 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4854 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4857 if (NILP (color_adjust
))
4858 color_adjust
= make_number (0xffff / 2);
4860 if (i
== 9 && NUMBERP (color_adjust
))
4861 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4865 /* Transform image IMG on frame F so that it looks disabled. */
4868 x_disable_image (f
, img
)
4872 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4874 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4876 int n_planes
= dpyinfo
->n_planes
;
4877 #endif /* HAVE_NTGUI */
4881 /* Color (or grayscale). Convert to gray, and equalize. Just
4882 drawing such images with a stipple can look very odd, so
4883 we're using this method instead. */
4884 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4886 const int h
= 15000;
4887 const int l
= 30000;
4889 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4893 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4894 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4895 p
->red
= p
->green
= p
->blue
= i2
;
4898 x_from_xcolors (f
, img
, colors
);
4901 /* Draw a cross over the disabled image, if we must or if we
4903 if (n_planes
< 2 || cross_disabled_images
)
4906 Display
*dpy
= FRAME_X_DISPLAY (f
);
4910 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4911 #define MaskForeground(f) PIX_MASK_DRAW (f)
4913 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4914 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4917 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4918 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4919 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4920 img
->width
- 1, img
->height
- 1);
4921 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4927 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4928 XSetForeground (dpy
, gc
, MaskForeground (f
));
4929 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4930 img
->width
- 1, img
->height
- 1);
4931 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
4939 hdc
= get_frame_dc (f
);
4940 bmpdc
= CreateCompatibleDC (hdc
);
4941 release_frame_dc (f
, hdc
);
4943 prev
= SelectObject (bmpdc
, img
->pixmap
);
4945 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
4946 MoveToEx (bmpdc
, 0, 0, NULL
);
4947 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4948 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4949 LineTo (bmpdc
, img
->width
- 1, 0);
4953 SelectObject (bmpdc
, img
->mask
);
4954 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
4955 MoveToEx (bmpdc
, 0, 0, NULL
);
4956 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4957 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4958 LineTo (bmpdc
, img
->width
- 1, 0);
4960 SelectObject (bmpdc
, prev
);
4962 #endif /* HAVE_NTGUI */
4967 /* Build a mask for image IMG which is used on frame F. FILE is the
4968 name of an image file, for error messages. HOW determines how to
4969 determine the background color of IMG. If it is a list '(R G B)',
4970 with R, G, and B being integers >= 0, take that as the color of the
4971 background. Otherwise, determine the background color of IMG
4972 heuristically. Value is non-zero if successful. */
4975 x_build_heuristic_mask (f
, img
, how
)
4980 XImagePtr_or_DC ximg
;
4988 #endif /* HAVE_NTGUI */
4989 int x
, y
, rc
, use_img_background
;
4990 unsigned long bg
= 0;
4994 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4995 img
->mask
= NO_PIXMAP
;
4996 img
->background_transparent_valid
= 0;
5000 /* Create an image and pixmap serving as mask. */
5001 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5002 &mask_img
, &img
->mask
);
5006 /* Get the X image of IMG->pixmap. */
5007 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5008 img
->width
, img
->height
,
5011 /* Create the bit array serving as mask. */
5012 row_width
= (img
->width
+ 7) / 8;
5013 mask_img
= xmalloc (row_width
* img
->height
);
5014 bzero (mask_img
, row_width
* img
->height
);
5016 /* Create a memory device context for IMG->pixmap. */
5017 frame_dc
= get_frame_dc (f
);
5018 ximg
= CreateCompatibleDC (frame_dc
);
5019 release_frame_dc (f
, frame_dc
);
5020 prev
= SelectObject (ximg
, img
->pixmap
);
5021 #endif /* HAVE_NTGUI */
5023 /* Determine the background color of ximg. If HOW is `(R G B)'
5024 take that as color. Otherwise, use the image's background color. */
5025 use_img_background
= 1;
5031 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5033 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5037 if (i
== 3 && NILP (how
))
5039 char color_name
[30];
5040 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5043 0x00ffffff & /* Filter out palette info. */
5044 #endif /* HAVE_NTGUI */
5045 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5046 use_img_background
= 0;
5050 if (use_img_background
)
5051 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
5053 /* Set all bits in mask_img to 1 whose color in ximg is different
5054 from the background color bg. */
5056 for (y
= 0; y
< img
->height
; ++y
)
5057 for (x
= 0; x
< img
->width
; ++x
)
5058 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5059 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
5061 /* Fill in the background_transparent field while we have the mask handy. */
5062 image_background_transparent (img
, f
, mask_img
);
5064 /* Put mask_img into img->mask. */
5065 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5066 x_destroy_x_image (mask_img
);
5069 for (y
= 0; y
< img
->height
; ++y
)
5070 for (x
= 0; x
< img
->width
; ++x
)
5072 COLORREF p
= GetPixel (ximg
, x
, y
);
5074 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5077 /* Create the mask image. */
5078 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5080 /* Fill in the background_transparent field while we have the mask handy. */
5081 SelectObject (ximg
, img
->mask
);
5082 image_background_transparent (img
, f
, ximg
);
5084 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5086 #endif /* HAVE_NTGUI */
5088 Destroy_Image (ximg
, prev
);
5094 /***********************************************************************
5095 PBM (mono, gray, color)
5096 ***********************************************************************/
5098 static int pbm_image_p
P_ ((Lisp_Object object
));
5099 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5100 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5102 /* The symbol `pbm' identifying images of this type. */
5106 /* Indices of image specification fields in gs_format, below. */
5108 enum pbm_keyword_index
5124 /* Vector of image_keyword structures describing the format
5125 of valid user-defined image specifications. */
5127 static struct image_keyword pbm_format
[PBM_LAST
] =
5129 {":type", IMAGE_SYMBOL_VALUE
, 1},
5130 {":file", IMAGE_STRING_VALUE
, 0},
5131 {":data", IMAGE_STRING_VALUE
, 0},
5132 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5133 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5134 {":relief", IMAGE_INTEGER_VALUE
, 0},
5135 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5136 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5137 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5138 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5139 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5142 /* Structure describing the image type `pbm'. */
5144 static struct image_type pbm_type
=
5154 /* Return non-zero if OBJECT is a valid PBM image specification. */
5157 pbm_image_p (object
)
5160 struct image_keyword fmt
[PBM_LAST
];
5162 bcopy (pbm_format
, fmt
, sizeof fmt
);
5164 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5167 /* Must specify either :data or :file. */
5168 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5172 /* Scan a decimal number from *S and return it. Advance *S while
5173 reading the number. END is the end of the string. Value is -1 at
5177 pbm_scan_number (s
, end
)
5178 unsigned char **s
, *end
;
5180 int c
= 0, val
= -1;
5184 /* Skip white-space. */
5185 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5190 /* Skip comment to end of line. */
5191 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5194 else if (isdigit (c
))
5196 /* Read decimal number. */
5198 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5199 val
= 10 * val
+ c
- '0';
5211 #if 0 /* Unused. ++kfs */
5213 /* Read FILE into memory. Value is a pointer to a buffer allocated
5214 with xmalloc holding FILE's contents. Value is null if an error
5215 occurred. *SIZE is set to the size of the file. */
5218 pbm_read_file (file
, size
)
5226 if (stat (SDATA (file
), &st
) == 0
5227 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5228 && (buf
= (char *) xmalloc (st
.st_size
),
5229 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5248 #endif /* HAVE_NTGUI */
5250 /* Load PBM image IMG for use on frame F. */
5258 int width
, height
, max_color_idx
= 0;
5260 Lisp_Object file
, specified_file
;
5261 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5262 struct gcpro gcpro1
;
5263 unsigned char *contents
= NULL
;
5264 unsigned char *end
, *p
;
5267 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5271 if (STRINGP (specified_file
))
5273 file
= x_find_image_file (specified_file
);
5274 if (!STRINGP (file
))
5276 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5281 contents
= slurp_file (SDATA (file
), &size
);
5282 if (contents
== NULL
)
5284 image_error ("Error reading `%s'", file
, Qnil
);
5290 end
= contents
+ size
;
5295 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5297 end
= p
+ SBYTES (data
);
5300 /* Check magic number. */
5301 if (end
- p
< 2 || *p
++ != 'P')
5303 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5313 raw_p
= 0, type
= PBM_MONO
;
5317 raw_p
= 0, type
= PBM_GRAY
;
5321 raw_p
= 0, type
= PBM_COLOR
;
5325 raw_p
= 1, type
= PBM_MONO
;
5329 raw_p
= 1, type
= PBM_GRAY
;
5333 raw_p
= 1, type
= PBM_COLOR
;
5337 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5341 /* Read width, height, maximum color-component. Characters
5342 starting with `#' up to the end of a line are ignored. */
5343 width
= pbm_scan_number (&p
, end
);
5344 height
= pbm_scan_number (&p
, end
);
5346 if (type
!= PBM_MONO
)
5348 max_color_idx
= pbm_scan_number (&p
, end
);
5349 if (raw_p
&& max_color_idx
> 255)
5350 max_color_idx
= 255;
5355 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5358 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5359 &ximg
, &img
->pixmap
))
5362 /* Initialize the color hash table. */
5363 init_color_table ();
5365 if (type
== PBM_MONO
)
5368 struct image_keyword fmt
[PBM_LAST
];
5369 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5370 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5372 /* Parse the image specification. */
5373 bcopy (pbm_format
, fmt
, sizeof fmt
);
5374 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5376 /* Get foreground and background colors, maybe allocate colors. */
5377 if (fmt
[PBM_FOREGROUND
].count
5378 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5379 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5380 if (fmt
[PBM_BACKGROUND
].count
5381 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5383 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5384 img
->background
= bg
;
5385 img
->background_valid
= 1;
5388 for (y
= 0; y
< height
; ++y
)
5389 for (x
= 0; x
< width
; ++x
)
5399 g
= pbm_scan_number (&p
, end
);
5401 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5406 for (y
= 0; y
< height
; ++y
)
5407 for (x
= 0; x
< width
; ++x
)
5411 if (type
== PBM_GRAY
)
5412 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5421 r
= pbm_scan_number (&p
, end
);
5422 g
= pbm_scan_number (&p
, end
);
5423 b
= pbm_scan_number (&p
, end
);
5426 if (r
< 0 || g
< 0 || b
< 0)
5428 x_destroy_x_image (ximg
);
5429 image_error ("Invalid pixel value in image `%s'",
5434 /* RGB values are now in the range 0..max_color_idx.
5435 Scale this to the range 0..0xffff supported by X. */
5436 r
= (double) r
* 65535 / max_color_idx
;
5437 g
= (double) g
* 65535 / max_color_idx
;
5438 b
= (double) b
* 65535 / max_color_idx
;
5439 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5443 #ifdef COLOR_TABLE_SUPPORT
5444 /* Store in IMG->colors the colors allocated for the image, and
5445 free the color table. */
5446 img
->colors
= colors_in_color_table (&img
->ncolors
);
5447 free_color_table ();
5448 #endif /* COLOR_TABLE_SUPPORT */
5451 img
->height
= height
;
5453 /* Maybe fill in the background field while we have ximg handy. */
5455 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5456 IMAGE_BACKGROUND (img
, f
, ximg
);
5458 /* Put the image into a pixmap. */
5459 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5460 x_destroy_x_image (ximg
);
5462 /* X and W32 versions did it here, MAC version above. ++kfs
5464 img->height = height; */
5472 /***********************************************************************
5474 ***********************************************************************/
5476 #if defined (HAVE_PNG) || defined (MAC_OS)
5478 /* Function prototypes. */
5480 static int png_image_p
P_ ((Lisp_Object object
));
5481 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5483 /* The symbol `png' identifying images of this type. */
5487 /* Indices of image specification fields in png_format, below. */
5489 enum png_keyword_index
5504 /* Vector of image_keyword structures describing the format
5505 of valid user-defined image specifications. */
5507 static struct image_keyword png_format
[PNG_LAST
] =
5509 {":type", IMAGE_SYMBOL_VALUE
, 1},
5510 {":data", IMAGE_STRING_VALUE
, 0},
5511 {":file", IMAGE_STRING_VALUE
, 0},
5512 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5513 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5514 {":relief", IMAGE_INTEGER_VALUE
, 0},
5515 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5516 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5517 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5518 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5521 /* Structure describing the image type `png'. */
5523 static struct image_type png_type
=
5532 /* Return non-zero if OBJECT is a valid PNG image specification. */
5535 png_image_p (object
)
5538 struct image_keyword fmt
[PNG_LAST
];
5539 bcopy (png_format
, fmt
, sizeof fmt
);
5541 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5544 /* Must specify either the :data or :file keyword. */
5545 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5548 #endif /* HAVE_PNG || MAC_OS */
5553 #if defined HAVE_LIBPNG_PNG_H
5554 # include <libpng/png.h>
5560 /* PNG library details. */
5562 DEF_IMGLIB_FN (png_get_io_ptr
);
5563 DEF_IMGLIB_FN (png_check_sig
);
5564 DEF_IMGLIB_FN (png_create_read_struct
);
5565 DEF_IMGLIB_FN (png_create_info_struct
);
5566 DEF_IMGLIB_FN (png_destroy_read_struct
);
5567 DEF_IMGLIB_FN (png_set_read_fn
);
5568 DEF_IMGLIB_FN (png_init_io
);
5569 DEF_IMGLIB_FN (png_set_sig_bytes
);
5570 DEF_IMGLIB_FN (png_read_info
);
5571 DEF_IMGLIB_FN (png_get_IHDR
);
5572 DEF_IMGLIB_FN (png_get_valid
);
5573 DEF_IMGLIB_FN (png_set_strip_16
);
5574 DEF_IMGLIB_FN (png_set_expand
);
5575 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5576 DEF_IMGLIB_FN (png_set_background
);
5577 DEF_IMGLIB_FN (png_get_bKGD
);
5578 DEF_IMGLIB_FN (png_read_update_info
);
5579 DEF_IMGLIB_FN (png_get_channels
);
5580 DEF_IMGLIB_FN (png_get_rowbytes
);
5581 DEF_IMGLIB_FN (png_read_image
);
5582 DEF_IMGLIB_FN (png_read_end
);
5583 DEF_IMGLIB_FN (png_error
);
5586 init_png_functions (void)
5590 /* Ensure zlib is loaded. Try debug version first. */
5591 if (!LoadLibrary ("zlibd.dll")
5592 && !LoadLibrary ("zlib.dll"))
5595 /* Try loading libpng under probable names. */
5596 if (!(library
= LoadLibrary ("libpng13d.dll"))
5597 && !(library
= LoadLibrary ("libpng13.dll"))
5598 && !(library
= LoadLibrary ("libpng12d.dll"))
5599 && !(library
= LoadLibrary ("libpng12.dll"))
5600 && !(library
= LoadLibrary ("libpng.dll")))
5603 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5604 LOAD_IMGLIB_FN (library
, png_check_sig
);
5605 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5606 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5607 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5608 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5609 LOAD_IMGLIB_FN (library
, png_init_io
);
5610 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5611 LOAD_IMGLIB_FN (library
, png_read_info
);
5612 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5613 LOAD_IMGLIB_FN (library
, png_get_valid
);
5614 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5615 LOAD_IMGLIB_FN (library
, png_set_expand
);
5616 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5617 LOAD_IMGLIB_FN (library
, png_set_background
);
5618 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5619 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5620 LOAD_IMGLIB_FN (library
, png_get_channels
);
5621 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5622 LOAD_IMGLIB_FN (library
, png_read_image
);
5623 LOAD_IMGLIB_FN (library
, png_read_end
);
5624 LOAD_IMGLIB_FN (library
, png_error
);
5629 #define fn_png_get_io_ptr png_get_io_ptr
5630 #define fn_png_check_sig png_check_sig
5631 #define fn_png_create_read_struct png_create_read_struct
5632 #define fn_png_create_info_struct png_create_info_struct
5633 #define fn_png_destroy_read_struct png_destroy_read_struct
5634 #define fn_png_set_read_fn png_set_read_fn
5635 #define fn_png_init_io png_init_io
5636 #define fn_png_set_sig_bytes png_set_sig_bytes
5637 #define fn_png_read_info png_read_info
5638 #define fn_png_get_IHDR png_get_IHDR
5639 #define fn_png_get_valid png_get_valid
5640 #define fn_png_set_strip_16 png_set_strip_16
5641 #define fn_png_set_expand png_set_expand
5642 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5643 #define fn_png_set_background png_set_background
5644 #define fn_png_get_bKGD png_get_bKGD
5645 #define fn_png_read_update_info png_read_update_info
5646 #define fn_png_get_channels png_get_channels
5647 #define fn_png_get_rowbytes png_get_rowbytes
5648 #define fn_png_read_image png_read_image
5649 #define fn_png_read_end png_read_end
5650 #define fn_png_error png_error
5652 #endif /* HAVE_NTGUI */
5654 /* Error and warning handlers installed when the PNG library
5658 my_png_error (png_ptr
, msg
)
5659 png_struct
*png_ptr
;
5662 xassert (png_ptr
!= NULL
);
5663 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5664 longjmp (png_ptr
->jmpbuf
, 1);
5669 my_png_warning (png_ptr
, msg
)
5670 png_struct
*png_ptr
;
5673 xassert (png_ptr
!= NULL
);
5674 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5677 /* Memory source for PNG decoding. */
5679 struct png_memory_storage
5681 unsigned char *bytes
; /* The data */
5682 size_t len
; /* How big is it? */
5683 int index
; /* Where are we? */
5687 /* Function set as reader function when reading PNG image from memory.
5688 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5689 bytes from the input to DATA. */
5692 png_read_from_memory (png_ptr
, data
, length
)
5693 png_structp png_ptr
;
5697 struct png_memory_storage
*tbr
5698 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5700 if (length
> tbr
->len
- tbr
->index
)
5701 fn_png_error (png_ptr
, "Read error");
5703 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5704 tbr
->index
= tbr
->index
+ length
;
5707 /* Load PNG image IMG for use on frame F. Value is non-zero if
5715 Lisp_Object file
, specified_file
;
5716 Lisp_Object specified_data
;
5718 XImagePtr ximg
, mask_img
= NULL
;
5719 struct gcpro gcpro1
;
5720 png_struct
*png_ptr
= NULL
;
5721 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5722 FILE *volatile fp
= NULL
;
5724 png_byte
* volatile pixels
= NULL
;
5725 png_byte
** volatile rows
= NULL
;
5726 png_uint_32 width
, height
;
5727 int bit_depth
, color_type
, interlace_type
;
5729 png_uint_32 row_bytes
;
5731 double screen_gamma
;
5732 struct png_memory_storage tbr
; /* Data to be read */
5734 /* Find out what file to load. */
5735 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5736 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5740 if (NILP (specified_data
))
5742 file
= x_find_image_file (specified_file
);
5743 if (!STRINGP (file
))
5745 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5750 /* Open the image file. */
5751 fp
= fopen (SDATA (file
), "rb");
5754 image_error ("Cannot open image file `%s'", file
, Qnil
);
5760 /* Check PNG signature. */
5761 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5762 || !fn_png_check_sig (sig
, sizeof sig
))
5764 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5772 /* Read from memory. */
5773 tbr
.bytes
= SDATA (specified_data
);
5774 tbr
.len
= SBYTES (specified_data
);
5777 /* Check PNG signature. */
5778 if (tbr
.len
< sizeof sig
5779 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5781 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5786 /* Need to skip past the signature. */
5787 tbr
.bytes
+= sizeof (sig
);
5790 /* Initialize read and info structs for PNG lib. */
5791 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5792 my_png_error
, my_png_warning
);
5795 if (fp
) fclose (fp
);
5800 info_ptr
= fn_png_create_info_struct (png_ptr
);
5803 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5804 if (fp
) fclose (fp
);
5809 end_info
= fn_png_create_info_struct (png_ptr
);
5812 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5813 if (fp
) fclose (fp
);
5818 /* Set error jump-back. We come back here when the PNG library
5819 detects an error. */
5820 if (setjmp (png_ptr
->jmpbuf
))
5824 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5827 if (fp
) fclose (fp
);
5832 /* Read image info. */
5833 if (!NILP (specified_data
))
5834 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5836 fn_png_init_io (png_ptr
, fp
);
5838 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5839 fn_png_read_info (png_ptr
, info_ptr
);
5840 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5841 &interlace_type
, NULL
, NULL
);
5843 /* If image contains simply transparency data, we prefer to
5844 construct a clipping mask. */
5845 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5850 /* This function is easier to write if we only have to handle
5851 one data format: RGB or RGBA with 8 bits per channel. Let's
5852 transform other formats into that format. */
5854 /* Strip more than 8 bits per channel. */
5855 if (bit_depth
== 16)
5856 fn_png_set_strip_16 (png_ptr
);
5858 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5860 fn_png_set_expand (png_ptr
);
5862 /* Convert grayscale images to RGB. */
5863 if (color_type
== PNG_COLOR_TYPE_GRAY
5864 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5865 fn_png_set_gray_to_rgb (png_ptr
);
5867 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5869 #if 0 /* Avoid double gamma correction for PNG images. */
5870 { /* Tell the PNG lib to handle gamma correction for us. */
5873 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5874 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5875 /* The libpng documentation says this is right in this case. */
5876 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5879 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5880 /* Image contains gamma information. */
5881 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5883 /* Use the standard default for the image gamma. */
5884 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5888 /* Handle alpha channel by combining the image with a background
5889 color. Do this only if a real alpha channel is supplied. For
5890 simple transparency, we prefer a clipping mask. */
5893 png_color_16
*image_bg
;
5894 Lisp_Object specified_bg
5895 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5897 if (STRINGP (specified_bg
))
5898 /* The user specified `:background', use that. */
5900 /* W32 version incorrectly used COLORREF here!! ++kfs */
5902 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5904 png_color_16 user_bg
;
5906 bzero (&user_bg
, sizeof user_bg
);
5907 user_bg
.red
= color
.red
>> 8;
5908 user_bg
.green
= color
.green
>> 8;
5909 user_bg
.blue
= color
.blue
>> 8;
5911 fn_png_set_background (png_ptr
, &user_bg
,
5912 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5915 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5916 /* Image contains a background color with which to
5917 combine the image. */
5918 fn_png_set_background (png_ptr
, image_bg
,
5919 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5922 /* Image does not contain a background color with which
5923 to combine the image data via an alpha channel. Use
5924 the frame's background instead. */
5925 #ifdef HAVE_X_WINDOWS
5927 png_color_16 frame_background
;
5929 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5930 x_query_color (f
, &color
);
5932 bzero (&frame_background
, sizeof frame_background
);
5933 frame_background
.red
= color
.red
>> 8;
5934 frame_background
.green
= color
.green
>> 8;
5935 frame_background
.blue
= color
.blue
>> 8;
5936 #endif /* HAVE_X_WINDOWS */
5940 png_color_16 frame_background
;
5941 color
= FRAME_BACKGROUND_PIXEL (f
);
5942 #if 0 /* W32 TODO : Colormap support. */
5943 x_query_color (f
, &color
);
5945 bzero (&frame_background
, sizeof frame_background
);
5946 frame_background
.red
= GetRValue (color
);
5947 frame_background
.green
= GetGValue (color
);
5948 frame_background
.blue
= GetBValue (color
);
5949 #endif /* HAVE_NTGUI */
5952 unsigned long color
;
5953 png_color_16 frame_background
;
5954 color
= FRAME_BACKGROUND_PIXEL (f
);
5955 #if 0 /* MAC/W32 TODO : Colormap support. */
5956 x_query_color (f
, &color
);
5958 bzero (&frame_background
, sizeof frame_background
);
5959 frame_background
.red
= RED_FROM_ULONG (color
);
5960 frame_background
.green
= GREEN_FROM_ULONG (color
);
5961 frame_background
.blue
= BLUE_FROM_ULONG (color
);
5964 fn_png_set_background (png_ptr
, &frame_background
,
5965 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5969 /* Update info structure. */
5970 fn_png_read_update_info (png_ptr
, info_ptr
);
5972 /* Get number of channels. Valid values are 1 for grayscale images
5973 and images with a palette, 2 for grayscale images with transparency
5974 information (alpha channel), 3 for RGB images, and 4 for RGB
5975 images with alpha channel, i.e. RGBA. If conversions above were
5976 sufficient we should only have 3 or 4 channels here. */
5977 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
5978 xassert (channels
== 3 || channels
== 4);
5980 /* Number of bytes needed for one row of the image. */
5981 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
5983 /* Allocate memory for the image. */
5984 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
5985 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
5986 for (i
= 0; i
< height
; ++i
)
5987 rows
[i
] = pixels
+ i
* row_bytes
;
5989 /* Read the entire image. */
5990 fn_png_read_image (png_ptr
, rows
);
5991 fn_png_read_end (png_ptr
, info_ptr
);
5998 /* Create the X image and pixmap. */
5999 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6003 /* Create an image and pixmap serving as mask if the PNG image
6004 contains an alpha channel. */
6007 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6008 &mask_img
, &img
->mask
))
6010 x_destroy_x_image (ximg
);
6011 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6012 img
->pixmap
= NO_PIXMAP
;
6016 /* Fill the X image and mask from PNG data. */
6017 init_color_table ();
6019 for (y
= 0; y
< height
; ++y
)
6021 png_byte
*p
= rows
[y
];
6023 for (x
= 0; x
< width
; ++x
)
6030 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6031 /* An alpha channel, aka mask channel, associates variable
6032 transparency with an image. Where other image formats
6033 support binary transparency---fully transparent or fully
6034 opaque---PNG allows up to 254 levels of partial transparency.
6035 The PNG library implements partial transparency by combining
6036 the image with a specified background color.
6038 I'm not sure how to handle this here nicely: because the
6039 background on which the image is displayed may change, for
6040 real alpha channel support, it would be necessary to create
6041 a new image for each possible background.
6043 What I'm doing now is that a mask is created if we have
6044 boolean transparency information. Otherwise I'm using
6045 the frame's background color to combine the image with. */
6050 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
6056 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6057 /* Set IMG's background color from the PNG image, unless the user
6061 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6063 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6064 img
->background_valid
= 1;
6068 #ifdef COLOR_TABLE_SUPPORT
6069 /* Remember colors allocated for this image. */
6070 img
->colors
= colors_in_color_table (&img
->ncolors
);
6071 free_color_table ();
6072 #endif /* COLOR_TABLE_SUPPORT */
6075 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6080 img
->height
= height
;
6082 /* Maybe fill in the background field while we have ximg handy. */
6083 IMAGE_BACKGROUND (img
, f
, ximg
);
6085 /* Put the image into the pixmap, then free the X image and its buffer. */
6086 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6087 x_destroy_x_image (ximg
);
6089 /* Same for the mask. */
6092 /* Fill in the background_transparent field while we have the mask
6094 image_background_transparent (img
, f
, mask_img
);
6096 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6097 x_destroy_x_image (mask_img
);
6104 #else /* HAVE_PNG */
6113 if (MyCGImageCreateWithPNGDataProvider
)
6114 return image_load_quartz2d (f
, img
, 1);
6117 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6121 #endif /* !HAVE_PNG */
6125 /***********************************************************************
6127 ***********************************************************************/
6129 #if defined (HAVE_JPEG) || defined (MAC_OS)
6131 static int jpeg_image_p
P_ ((Lisp_Object object
));
6132 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6134 /* The symbol `jpeg' identifying images of this type. */
6138 /* Indices of image specification fields in gs_format, below. */
6140 enum jpeg_keyword_index
6149 JPEG_HEURISTIC_MASK
,
6155 /* Vector of image_keyword structures describing the format
6156 of valid user-defined image specifications. */
6158 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6160 {":type", IMAGE_SYMBOL_VALUE
, 1},
6161 {":data", IMAGE_STRING_VALUE
, 0},
6162 {":file", IMAGE_STRING_VALUE
, 0},
6163 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6164 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6165 {":relief", IMAGE_INTEGER_VALUE
, 0},
6166 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6167 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6168 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6169 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6172 /* Structure describing the image type `jpeg'. */
6174 static struct image_type jpeg_type
=
6183 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6186 jpeg_image_p (object
)
6189 struct image_keyword fmt
[JPEG_LAST
];
6191 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6193 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6196 /* Must specify either the :data or :file keyword. */
6197 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6200 #endif /* HAVE_JPEG || MAC_OS */
6204 /* Work around a warning about HAVE_STDLIB_H being redefined in
6206 #ifdef HAVE_STDLIB_H
6207 #define HAVE_STDLIB_H_1
6208 #undef HAVE_STDLIB_H
6209 #endif /* HAVE_STLIB_H */
6211 #include <jpeglib.h>
6215 #ifdef HAVE_STLIB_H_1
6216 #define HAVE_STDLIB_H 1
6221 /* JPEG library details. */
6222 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6223 DEF_IMGLIB_FN (jpeg_start_decompress
);
6224 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6225 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6226 DEF_IMGLIB_FN (jpeg_read_header
);
6227 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6228 DEF_IMGLIB_FN (jpeg_stdio_src
);
6229 DEF_IMGLIB_FN (jpeg_std_error
);
6230 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6233 init_jpeg_functions (void)
6237 if (!(library
= LoadLibrary ("libjpeg.dll"))
6238 && !(library
= LoadLibrary ("jpeg-62.dll"))
6239 && !(library
= LoadLibrary ("jpeg.dll")))
6242 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6243 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6244 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6245 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6246 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
6247 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6248 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6249 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6250 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6254 /* Wrapper since we can't directly assign the function pointer
6255 to another function pointer that was declared more completely easily. */
6257 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6258 j_decompress_ptr cinfo
;
6261 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6266 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6267 #define fn_jpeg_start_decompress jpeg_start_decompress
6268 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6269 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6270 #define fn_jpeg_read_header jpeg_read_header
6271 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6272 #define fn_jpeg_stdio_src jpeg_stdio_src
6273 #define fn_jpeg_std_error jpeg_std_error
6274 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6276 #endif /* HAVE_NTGUI */
6278 struct my_jpeg_error_mgr
6280 struct jpeg_error_mgr pub
;
6281 jmp_buf setjmp_buffer
;
6286 my_error_exit (cinfo
)
6289 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6290 longjmp (mgr
->setjmp_buffer
, 1);
6294 /* Init source method for JPEG data source manager. Called by
6295 jpeg_read_header() before any data is actually read. See
6296 libjpeg.doc from the JPEG lib distribution. */
6299 our_init_source (cinfo
)
6300 j_decompress_ptr cinfo
;
6305 /* Fill input buffer method for JPEG data source manager. Called
6306 whenever more data is needed. We read the whole image in one step,
6307 so this only adds a fake end of input marker at the end. */
6310 our_fill_input_buffer (cinfo
)
6311 j_decompress_ptr cinfo
;
6313 /* Insert a fake EOI marker. */
6314 struct jpeg_source_mgr
*src
= cinfo
->src
;
6315 static JOCTET buffer
[2];
6317 buffer
[0] = (JOCTET
) 0xFF;
6318 buffer
[1] = (JOCTET
) JPEG_EOI
;
6320 src
->next_input_byte
= buffer
;
6321 src
->bytes_in_buffer
= 2;
6326 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6327 is the JPEG data source manager. */
6330 our_skip_input_data (cinfo
, num_bytes
)
6331 j_decompress_ptr cinfo
;
6334 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6338 if (num_bytes
> src
->bytes_in_buffer
)
6339 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6341 src
->bytes_in_buffer
-= num_bytes
;
6342 src
->next_input_byte
+= num_bytes
;
6347 /* Method to terminate data source. Called by
6348 jpeg_finish_decompress() after all data has been processed. */
6351 our_term_source (cinfo
)
6352 j_decompress_ptr cinfo
;
6357 /* Set up the JPEG lib for reading an image from DATA which contains
6358 LEN bytes. CINFO is the decompression info structure created for
6359 reading the image. */
6362 jpeg_memory_src (cinfo
, data
, len
)
6363 j_decompress_ptr cinfo
;
6367 struct jpeg_source_mgr
*src
;
6369 if (cinfo
->src
== NULL
)
6371 /* First time for this JPEG object? */
6372 cinfo
->src
= (struct jpeg_source_mgr
*)
6373 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6374 sizeof (struct jpeg_source_mgr
));
6375 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6376 src
->next_input_byte
= data
;
6379 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6380 src
->init_source
= our_init_source
;
6381 src
->fill_input_buffer
= our_fill_input_buffer
;
6382 src
->skip_input_data
= our_skip_input_data
;
6383 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6384 src
->term_source
= our_term_source
;
6385 src
->bytes_in_buffer
= len
;
6386 src
->next_input_byte
= data
;
6390 /* Load image IMG for use on frame F. Patterned after example.c
6391 from the JPEG lib. */
6398 struct jpeg_decompress_struct cinfo
;
6399 struct my_jpeg_error_mgr mgr
;
6400 Lisp_Object file
, specified_file
;
6401 Lisp_Object specified_data
;
6402 FILE * volatile fp
= NULL
;
6404 int row_stride
, x
, y
;
6405 XImagePtr ximg
= NULL
;
6407 unsigned long *colors
;
6409 struct gcpro gcpro1
;
6411 /* Open the JPEG file. */
6412 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6413 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6417 if (NILP (specified_data
))
6419 file
= x_find_image_file (specified_file
);
6420 if (!STRINGP (file
))
6422 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6427 fp
= fopen (SDATA (file
), "rb");
6430 image_error ("Cannot open `%s'", file
, Qnil
);
6436 /* Customize libjpeg's error handling to call my_error_exit when an
6437 error is detected. This function will perform a longjmp. */
6438 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
6439 mgr
.pub
.error_exit
= my_error_exit
;
6441 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6445 /* Called from my_error_exit. Display a JPEG error. */
6446 char buffer
[JMSG_LENGTH_MAX
];
6447 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6448 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6449 build_string (buffer
));
6452 /* Close the input file and destroy the JPEG object. */
6454 fclose ((FILE *) fp
);
6455 fn_jpeg_destroy_decompress (&cinfo
);
6457 /* If we already have an XImage, free that. */
6458 x_destroy_x_image (ximg
);
6460 /* Free pixmap and colors. */
6461 x_clear_image (f
, img
);
6467 /* Create the JPEG decompression object. Let it read from fp.
6468 Read the JPEG image header. */
6469 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6471 if (NILP (specified_data
))
6472 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
6474 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6475 SBYTES (specified_data
));
6477 fn_jpeg_read_header (&cinfo
, TRUE
);
6479 /* Customize decompression so that color quantization will be used.
6480 Start decompression. */
6481 cinfo
.quantize_colors
= TRUE
;
6482 fn_jpeg_start_decompress (&cinfo
);
6483 width
= img
->width
= cinfo
.output_width
;
6484 height
= img
->height
= cinfo
.output_height
;
6486 /* Create X image and pixmap. */
6487 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6488 longjmp (mgr
.setjmp_buffer
, 2);
6490 /* Allocate colors. When color quantization is used,
6491 cinfo.actual_number_of_colors has been set with the number of
6492 colors generated, and cinfo.colormap is a two-dimensional array
6493 of color indices in the range 0..cinfo.actual_number_of_colors.
6494 No more than 255 colors will be generated. */
6498 if (cinfo
.out_color_components
> 2)
6499 ir
= 0, ig
= 1, ib
= 2;
6500 else if (cinfo
.out_color_components
> 1)
6501 ir
= 0, ig
= 1, ib
= 0;
6503 ir
= 0, ig
= 0, ib
= 0;
6505 /* Use the color table mechanism because it handles colors that
6506 cannot be allocated nicely. Such colors will be replaced with
6507 a default color, and we don't have to care about which colors
6508 can be freed safely, and which can't. */
6509 init_color_table ();
6510 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6513 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6515 /* Multiply RGB values with 255 because X expects RGB values
6516 in the range 0..0xffff. */
6517 int r
= cinfo
.colormap
[ir
][i
] << 8;
6518 int g
= cinfo
.colormap
[ig
][i
] << 8;
6519 int b
= cinfo
.colormap
[ib
][i
] << 8;
6520 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6523 #ifdef COLOR_TABLE_SUPPORT
6524 /* Remember those colors actually allocated. */
6525 img
->colors
= colors_in_color_table (&img
->ncolors
);
6526 free_color_table ();
6527 #endif /* COLOR_TABLE_SUPPORT */
6531 row_stride
= width
* cinfo
.output_components
;
6532 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6534 for (y
= 0; y
< height
; ++y
)
6536 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6537 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6538 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6542 fn_jpeg_finish_decompress (&cinfo
);
6543 fn_jpeg_destroy_decompress (&cinfo
);
6545 fclose ((FILE *) fp
);
6547 /* Maybe fill in the background field while we have ximg handy. */
6548 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6549 IMAGE_BACKGROUND (img
, f
, ximg
);
6551 /* Put the image into the pixmap. */
6552 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6553 x_destroy_x_image (ximg
);
6558 #else /* HAVE_JPEG */
6567 return image_load_quartz2d (f
, img
, 0);
6569 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6574 #endif /* !HAVE_JPEG */
6578 /***********************************************************************
6580 ***********************************************************************/
6582 #if defined (HAVE_TIFF) || defined (MAC_OS)
6584 static int tiff_image_p
P_ ((Lisp_Object object
));
6585 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6587 /* The symbol `tiff' identifying images of this type. */
6591 /* Indices of image specification fields in tiff_format, below. */
6593 enum tiff_keyword_index
6602 TIFF_HEURISTIC_MASK
,
6608 /* Vector of image_keyword structures describing the format
6609 of valid user-defined image specifications. */
6611 static struct image_keyword tiff_format
[TIFF_LAST
] =
6613 {":type", IMAGE_SYMBOL_VALUE
, 1},
6614 {":data", IMAGE_STRING_VALUE
, 0},
6615 {":file", IMAGE_STRING_VALUE
, 0},
6616 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6617 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6618 {":relief", IMAGE_INTEGER_VALUE
, 0},
6619 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6620 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6621 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6622 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6625 /* Structure describing the image type `tiff'. */
6627 static struct image_type tiff_type
=
6636 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6639 tiff_image_p (object
)
6642 struct image_keyword fmt
[TIFF_LAST
];
6643 bcopy (tiff_format
, fmt
, sizeof fmt
);
6645 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6648 /* Must specify either the :data or :file keyword. */
6649 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6652 #endif /* HAVE_TIFF || MAC_OS */
6660 /* TIFF library details. */
6661 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6662 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6663 DEF_IMGLIB_FN (TIFFOpen
);
6664 DEF_IMGLIB_FN (TIFFClientOpen
);
6665 DEF_IMGLIB_FN (TIFFGetField
);
6666 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6667 DEF_IMGLIB_FN (TIFFClose
);
6670 init_tiff_functions (void)
6674 if (!(library
= LoadLibrary ("libtiff.dll")))
6677 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6678 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6679 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6680 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6681 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6682 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6683 LOAD_IMGLIB_FN (library
, TIFFClose
);
6689 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6690 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6691 #define fn_TIFFOpen TIFFOpen
6692 #define fn_TIFFClientOpen TIFFClientOpen
6693 #define fn_TIFFGetField TIFFGetField
6694 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6695 #define fn_TIFFClose TIFFClose
6697 #endif /* HAVE_NTGUI */
6700 /* Reading from a memory buffer for TIFF images Based on the PNG
6701 memory source, but we have to provide a lot of extra functions.
6704 We really only need to implement read and seek, but I am not
6705 convinced that the TIFF library is smart enough not to destroy
6706 itself if we only hand it the function pointers we need to
6711 unsigned char *bytes
;
6718 tiff_read_from_memory (data
, buf
, size
)
6723 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6725 if (size
> src
->len
- src
->index
)
6727 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6733 tiff_write_from_memory (data
, buf
, size
)
6742 tiff_seek_in_memory (data
, off
, whence
)
6747 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6752 case SEEK_SET
: /* Go from beginning of source. */
6756 case SEEK_END
: /* Go from end of source. */
6757 idx
= src
->len
+ off
;
6760 case SEEK_CUR
: /* Go from current position. */
6761 idx
= src
->index
+ off
;
6764 default: /* Invalid `whence'. */
6768 if (idx
> src
->len
|| idx
< 0)
6776 tiff_close_memory (data
)
6784 tiff_mmap_memory (data
, pbase
, psize
)
6789 /* It is already _IN_ memory. */
6794 tiff_unmap_memory (data
, base
, size
)
6799 /* We don't need to do this. */
6803 tiff_size_of_memory (data
)
6806 return ((tiff_memory_source
*) data
)->len
;
6811 tiff_error_handler (title
, format
, ap
)
6812 const char *title
, *format
;
6818 len
= sprintf (buf
, "TIFF error: %s ", title
);
6819 vsprintf (buf
+ len
, format
, ap
);
6820 add_to_log (buf
, Qnil
, Qnil
);
6825 tiff_warning_handler (title
, format
, ap
)
6826 const char *title
, *format
;
6832 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6833 vsprintf (buf
+ len
, format
, ap
);
6834 add_to_log (buf
, Qnil
, Qnil
);
6838 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6846 Lisp_Object file
, specified_file
;
6847 Lisp_Object specified_data
;
6849 int width
, height
, x
, y
;
6853 struct gcpro gcpro1
;
6854 tiff_memory_source memsrc
;
6856 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6857 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6861 fn_TIFFSetErrorHandler (tiff_error_handler
);
6862 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6864 if (NILP (specified_data
))
6866 /* Read from a file */
6867 file
= x_find_image_file (specified_file
);
6868 if (!STRINGP (file
))
6870 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6875 /* Try to open the image file. */
6876 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6879 image_error ("Cannot open `%s'", file
, Qnil
);
6886 /* Memory source! */
6887 memsrc
.bytes
= SDATA (specified_data
);
6888 memsrc
.len
= SBYTES (specified_data
);
6891 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6892 (TIFFReadWriteProc
) tiff_read_from_memory
,
6893 (TIFFReadWriteProc
) tiff_write_from_memory
,
6894 tiff_seek_in_memory
,
6896 tiff_size_of_memory
,
6902 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6908 /* Get width and height of the image, and allocate a raster buffer
6909 of width x height 32-bit values. */
6910 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6911 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6912 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6914 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6915 fn_TIFFClose (tiff
);
6918 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6924 /* Create the X image and pixmap. */
6925 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6932 /* Initialize the color table. */
6933 init_color_table ();
6935 /* Process the pixel raster. Origin is in the lower-left corner. */
6936 for (y
= 0; y
< height
; ++y
)
6938 uint32
*row
= buf
+ y
* width
;
6940 for (x
= 0; x
< width
; ++x
)
6942 uint32 abgr
= row
[x
];
6943 int r
= TIFFGetR (abgr
) << 8;
6944 int g
= TIFFGetG (abgr
) << 8;
6945 int b
= TIFFGetB (abgr
) << 8;
6946 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
6950 #ifdef COLOR_TABLE_SUPPORT
6951 /* Remember the colors allocated for the image. Free the color table. */
6952 img
->colors
= colors_in_color_table (&img
->ncolors
);
6953 free_color_table ();
6954 #endif /* COLOR_TABLE_SUPPORT */
6957 img
->height
= height
;
6959 /* Maybe fill in the background field while we have ximg handy. */
6960 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6961 IMAGE_BACKGROUND (img
, f
, ximg
);
6963 /* Put the image into the pixmap, then free the X image and its buffer. */
6964 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6965 x_destroy_x_image (ximg
);
6972 #else /* HAVE_TIFF */
6980 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
6984 #endif /* !HAVE_TIFF */
6988 /***********************************************************************
6990 ***********************************************************************/
6992 #if defined (HAVE_GIF) || defined (MAC_OS)
6994 static int gif_image_p
P_ ((Lisp_Object object
));
6995 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
6997 /* The symbol `gif' identifying images of this type. */
7001 /* Indices of image specification fields in gif_format, below. */
7003 enum gif_keyword_index
7019 /* Vector of image_keyword structures describing the format
7020 of valid user-defined image specifications. */
7022 static struct image_keyword gif_format
[GIF_LAST
] =
7024 {":type", IMAGE_SYMBOL_VALUE
, 1},
7025 {":data", IMAGE_STRING_VALUE
, 0},
7026 {":file", IMAGE_STRING_VALUE
, 0},
7027 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7028 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7029 {":relief", IMAGE_INTEGER_VALUE
, 0},
7030 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7031 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7032 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7033 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7034 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7037 /* Structure describing the image type `gif'. */
7039 static struct image_type gif_type
=
7048 /* Return non-zero if OBJECT is a valid GIF image specification. */
7051 gif_image_p (object
)
7054 struct image_keyword fmt
[GIF_LAST
];
7055 bcopy (gif_format
, fmt
, sizeof fmt
);
7057 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7060 /* Must specify either the :data or :file keyword. */
7061 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7064 #endif /* HAVE_GIF || MAC_OS */
7068 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7069 /* avoid conflict with QuickdrawText.h */
7070 #define DrawText gif_DrawText
7071 #include <gif_lib.h>
7074 #else /* HAVE_NTGUI || MAC_OS */
7076 #include <gif_lib.h>
7078 #endif /* HAVE_NTGUI || MAC_OS */
7083 /* GIF library details. */
7084 DEF_IMGLIB_FN (DGifCloseFile
);
7085 DEF_IMGLIB_FN (DGifSlurp
);
7086 DEF_IMGLIB_FN (DGifOpen
);
7087 DEF_IMGLIB_FN (DGifOpenFileName
);
7090 init_gif_functions (void)
7094 if (!(library
= LoadLibrary ("libungif.dll")))
7097 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7098 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7099 LOAD_IMGLIB_FN (library
, DGifOpen
);
7100 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7106 #define fn_DGifCloseFile DGifCloseFile
7107 #define fn_DGifSlurp DGifSlurp
7108 #define fn_DGifOpen DGifOpen
7109 #define fn_DGifOpenFileName DGifOpenFileName
7111 #endif /* HAVE_NTGUI */
7113 /* Reading a GIF image from memory
7114 Based on the PNG memory stuff to a certain extent. */
7118 unsigned char *bytes
;
7124 /* Make the current memory source available to gif_read_from_memory.
7125 It's done this way because not all versions of libungif support
7126 a UserData field in the GifFileType structure. */
7127 static gif_memory_source
*current_gif_memory_src
;
7130 gif_read_from_memory (file
, buf
, len
)
7135 gif_memory_source
*src
= current_gif_memory_src
;
7137 if (len
> src
->len
- src
->index
)
7140 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7146 /* Load GIF image IMG for use on frame F. Value is non-zero if
7154 Lisp_Object file
, specified_file
;
7155 Lisp_Object specified_data
;
7156 int rc
, width
, height
, x
, y
, i
;
7158 ColorMapObject
*gif_color_map
;
7159 unsigned long pixel_colors
[256];
7161 struct gcpro gcpro1
;
7163 int ino
, image_left
, image_top
, image_width
, image_height
;
7164 gif_memory_source memsrc
;
7165 unsigned char *raster
;
7167 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7168 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7172 if (NILP (specified_data
))
7174 file
= x_find_image_file (specified_file
);
7175 if (!STRINGP (file
))
7177 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7182 /* Open the GIF file. */
7183 gif
= fn_DGifOpenFileName (SDATA (file
));
7186 image_error ("Cannot open `%s'", file
, Qnil
);
7193 /* Read from memory! */
7194 current_gif_memory_src
= &memsrc
;
7195 memsrc
.bytes
= SDATA (specified_data
);
7196 memsrc
.len
= SBYTES (specified_data
);
7199 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7202 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7208 /* Read entire contents. */
7209 rc
= fn_DGifSlurp (gif
);
7210 if (rc
== GIF_ERROR
)
7212 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7213 fn_DGifCloseFile (gif
);
7218 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7219 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7220 if (ino
>= gif
->ImageCount
)
7222 image_error ("Invalid image number `%s' in image `%s'",
7224 fn_DGifCloseFile (gif
);
7229 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
7230 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
7232 /* Create the X image and pixmap. */
7233 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7235 fn_DGifCloseFile (gif
);
7240 /* Allocate colors. */
7241 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7243 gif_color_map
= gif
->SColorMap
;
7244 init_color_table ();
7245 bzero (pixel_colors
, sizeof pixel_colors
);
7247 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7249 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7250 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7251 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7252 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7255 #ifdef COLOR_TABLE_SUPPORT
7256 img
->colors
= colors_in_color_table (&img
->ncolors
);
7257 free_color_table ();
7258 #endif /* COLOR_TABLE_SUPPORT */
7260 /* Clear the part of the screen image that are not covered by
7261 the image from the GIF file. Full animated GIF support
7262 requires more than can be done here (see the gif89 spec,
7263 disposal methods). Let's simply assume that the part
7264 not covered by a sub-image is in the frame's background color. */
7265 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
7266 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
7267 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7268 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7270 for (y
= 0; y
< image_top
; ++y
)
7271 for (x
= 0; x
< width
; ++x
)
7272 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7274 for (y
= image_top
+ image_height
; y
< height
; ++y
)
7275 for (x
= 0; x
< width
; ++x
)
7276 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7278 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
7280 for (x
= 0; x
< image_left
; ++x
)
7281 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7282 for (x
= image_left
+ image_width
; x
< width
; ++x
)
7283 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7286 /* Read the GIF image into the X image. We use a local variable
7287 `raster' here because RasterBits below is a char *, and invites
7288 problems with bytes >= 0x80. */
7289 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7291 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7293 static int interlace_start
[] = {0, 4, 2, 1};
7294 static int interlace_increment
[] = {8, 8, 4, 2};
7296 int row
= interlace_start
[0];
7300 for (y
= 0; y
< image_height
; y
++)
7302 if (row
>= image_height
)
7304 row
= interlace_start
[++pass
];
7305 while (row
>= image_height
)
7306 row
= interlace_start
[++pass
];
7309 for (x
= 0; x
< image_width
; x
++)
7311 int i
= raster
[(y
* image_width
) + x
];
7312 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
7316 row
+= interlace_increment
[pass
];
7321 for (y
= 0; y
< image_height
; ++y
)
7322 for (x
= 0; x
< image_width
; ++x
)
7324 int i
= raster
[y
* image_width
+ x
];
7325 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
7329 fn_DGifCloseFile (gif
);
7331 /* Maybe fill in the background field while we have ximg handy. */
7332 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7333 IMAGE_BACKGROUND (img
, f
, ximg
);
7335 /* Put the image into the pixmap, then free the X image and its buffer. */
7336 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7337 x_destroy_x_image (ximg
);
7351 Lisp_Object specified_file
, file
;
7352 Lisp_Object specified_data
;
7354 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
7362 Lisp_Object specified_bg
;
7368 struct gcpro gcpro1
;
7373 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7374 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7376 if (NILP (specified_data
))
7378 /* Read from a file */
7382 err
= find_image_fsspec (specified_file
, &file
, &fss
);
7386 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7391 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
7392 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
7396 if (!graphic_p
&& !movie_p
)
7398 if (prefer_graphic_p
)
7399 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
7400 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
7403 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
7404 CloseMovieFile (refnum
);
7407 image_error ("Error reading `%s'", file
, Qnil
);
7413 /* Memory source! */
7415 long file_type_atom
[3];
7417 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
7420 image_error ("Cannot allocate data handle for `%s'",
7425 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
7426 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
7427 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
7428 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
7431 err
= PtrAndHand ("\p", dref
, 1);
7433 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
7436 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
7439 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
7440 &movie_p
, &prefer_graphic_p
, 0);
7444 if (!graphic_p
&& !movie_p
)
7446 if (prefer_graphic_p
)
7450 DisposeHandle (dref
);
7451 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
7455 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
7456 HandleDataHandlerSubType
);
7457 DisposeHandle (dref
);
7462 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7463 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7464 track
= GetMovieIndTrack (movie
, 1);
7465 media
= GetTrackMedia (track
);
7466 nsamples
= GetMediaSampleCount (media
);
7467 if (ino
>= nsamples
)
7469 image_error ("Invalid image number `%s' in image `%s'",
7474 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7475 if (!STRINGP (specified_bg
) ||
7476 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
7478 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7479 color
.red
= RED16_FROM_ULONG (color
.pixel
);
7480 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
7481 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
7483 GetMovieBox (movie
, &rect
);
7484 width
= img
->width
= rect
.right
- rect
.left
;
7485 height
= img
->height
= rect
.bottom
- rect
.top
;
7486 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7489 GetGWorld (&old_port
, &old_gdh
);
7490 SetGWorld (ximg
, NULL
);
7491 bg_color
.red
= color
.red
;
7492 bg_color
.green
= color
.green
;
7493 bg_color
.blue
= color
.blue
;
7494 RGBBackColor (&bg_color
);
7495 SetGWorld (old_port
, old_gdh
);
7496 SetMovieActive (movie
, TRUE
);
7497 SetMovieGWorld (movie
, ximg
, NULL
);
7498 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7499 SetMovieTimeValue (movie
, time
);
7500 MoviesTask (movie
, 0L);
7501 DisposeTrackMedia (media
);
7502 DisposeMovieTrack (track
);
7503 DisposeMovie (movie
);
7506 /* Maybe fill in the background field while we have ximg handy. */
7507 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7508 IMAGE_BACKGROUND (img
, f
, ximg
);
7510 /* Put the image into the pixmap. */
7511 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7512 x_destroy_x_image (ximg
);
7516 image_error ("Cannot open `%s'", file
, Qnil
);
7519 DisposeTrackMedia (media
);
7521 DisposeMovieTrack (track
);
7523 DisposeMovie (movie
);
7530 #endif /* HAVE_GIF */
7534 /***********************************************************************
7536 ***********************************************************************/
7538 #ifdef HAVE_X_WINDOWS
7539 #define HAVE_GHOSTSCRIPT 1
7540 #endif /* HAVE_X_WINDOWS */
7542 /* The symbol `postscript' identifying images of this type. */
7544 Lisp_Object Qpostscript
;
7546 #ifdef HAVE_GHOSTSCRIPT
7548 static int gs_image_p
P_ ((Lisp_Object object
));
7549 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7550 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7552 /* Keyword symbols. */
7554 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7556 /* Indices of image specification fields in gs_format, below. */
7558 enum gs_keyword_index
7576 /* Vector of image_keyword structures describing the format
7577 of valid user-defined image specifications. */
7579 static struct image_keyword gs_format
[GS_LAST
] =
7581 {":type", IMAGE_SYMBOL_VALUE
, 1},
7582 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7583 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7584 {":file", IMAGE_STRING_VALUE
, 1},
7585 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7586 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7587 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7588 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7589 {":relief", IMAGE_INTEGER_VALUE
, 0},
7590 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7591 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7592 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7593 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7596 /* Structure describing the image type `ghostscript'. */
7598 static struct image_type gs_type
=
7608 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7611 gs_clear_image (f
, img
)
7615 /* IMG->data.ptr_val may contain a recorded colormap. */
7616 xfree (img
->data
.ptr_val
);
7617 x_clear_image (f
, img
);
7621 /* Return non-zero if OBJECT is a valid Ghostscript image
7628 struct image_keyword fmt
[GS_LAST
];
7632 bcopy (gs_format
, fmt
, sizeof fmt
);
7634 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7637 /* Bounding box must be a list or vector containing 4 integers. */
7638 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7641 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7642 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7647 else if (VECTORP (tem
))
7649 if (XVECTOR (tem
)->size
!= 4)
7651 for (i
= 0; i
< 4; ++i
)
7652 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7662 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7671 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7672 struct gcpro gcpro1
, gcpro2
;
7674 double in_width
, in_height
;
7675 Lisp_Object pixel_colors
= Qnil
;
7677 /* Compute pixel size of pixmap needed from the given size in the
7678 image specification. Sizes in the specification are in pt. 1 pt
7679 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7681 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7682 in_width
= XFASTINT (pt_width
) / 72.0;
7683 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7684 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7685 in_height
= XFASTINT (pt_height
) / 72.0;
7686 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7688 /* Create the pixmap. */
7689 xassert (img
->pixmap
== NO_PIXMAP
);
7691 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7693 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7694 img
->width
, img
->height
,
7695 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7700 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7704 /* Call the loader to fill the pixmap. It returns a process object
7705 if successful. We do not record_unwind_protect here because
7706 other places in redisplay like calling window scroll functions
7707 don't either. Let the Lisp loader use `unwind-protect' instead. */
7708 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7710 sprintf (buffer
, "%lu %lu",
7711 (unsigned long) FRAME_X_WINDOW (f
),
7712 (unsigned long) img
->pixmap
);
7713 window_and_pixmap_id
= build_string (buffer
);
7715 sprintf (buffer
, "%lu %lu",
7716 FRAME_FOREGROUND_PIXEL (f
),
7717 FRAME_BACKGROUND_PIXEL (f
));
7718 pixel_colors
= build_string (buffer
);
7720 XSETFRAME (frame
, f
);
7721 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7723 loader
= intern ("gs-load-image");
7725 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7726 make_number (img
->width
),
7727 make_number (img
->height
),
7728 window_and_pixmap_id
,
7731 return PROCESSP (img
->data
.lisp_val
);
7735 /* Kill the Ghostscript process that was started to fill PIXMAP on
7736 frame F. Called from XTread_socket when receiving an event
7737 telling Emacs that Ghostscript has finished drawing. */
7740 x_kill_gs_process (pixmap
, f
)
7744 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7748 /* Find the image containing PIXMAP. */
7749 for (i
= 0; i
< c
->used
; ++i
)
7750 if (c
->images
[i
]->pixmap
== pixmap
)
7753 /* Should someone in between have cleared the image cache, for
7754 instance, give up. */
7758 /* Kill the GS process. We should have found PIXMAP in the image
7759 cache and its image should contain a process object. */
7761 xassert (PROCESSP (img
->data
.lisp_val
));
7762 Fkill_process (img
->data
.lisp_val
, Qnil
);
7763 img
->data
.lisp_val
= Qnil
;
7765 #if defined (HAVE_X_WINDOWS)
7767 /* On displays with a mutable colormap, figure out the colors
7768 allocated for the image by looking at the pixels of an XImage for
7770 class = FRAME_X_VISUAL (f
)->class;
7771 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7777 /* Try to get an XImage for img->pixmep. */
7778 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7779 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7784 /* Initialize the color table. */
7785 init_color_table ();
7787 /* For each pixel of the image, look its color up in the
7788 color table. After having done so, the color table will
7789 contain an entry for each color used by the image. */
7790 for (y
= 0; y
< img
->height
; ++y
)
7791 for (x
= 0; x
< img
->width
; ++x
)
7793 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7794 lookup_pixel_color (f
, pixel
);
7797 /* Record colors in the image. Free color table and XImage. */
7798 #ifdef COLOR_TABLE_SUPPORT
7799 img
->colors
= colors_in_color_table (&img
->ncolors
);
7800 free_color_table ();
7802 XDestroyImage (ximg
);
7804 #if 0 /* This doesn't seem to be the case. If we free the colors
7805 here, we get a BadAccess later in x_clear_image when
7806 freeing the colors. */
7807 /* We have allocated colors once, but Ghostscript has also
7808 allocated colors on behalf of us. So, to get the
7809 reference counts right, free them once. */
7811 x_free_colors (f
, img
->colors
, img
->ncolors
);
7815 image_error ("Cannot get X image of `%s'; colors will not be freed",
7820 #endif /* HAVE_X_WINDOWS */
7822 /* Now that we have the pixmap, compute mask and transform the
7823 image if requested. */
7825 postprocess_image (f
, img
);
7829 #endif /* HAVE_GHOSTSCRIPT */
7832 /***********************************************************************
7834 ***********************************************************************/
7838 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7839 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7843 return valid_image_p (spec
) ? Qt
: Qnil
;
7847 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7853 if (valid_image_p (spec
))
7854 id
= lookup_image (SELECTED_FRAME (), spec
);
7857 return make_number (id
);
7860 #endif /* GLYPH_DEBUG != 0 */
7863 /***********************************************************************
7865 ***********************************************************************/
7870 QCascent
= intern (":ascent");
7871 staticpro (&QCascent
);
7872 QCmargin
= intern (":margin");
7873 staticpro (&QCmargin
);
7874 QCrelief
= intern (":relief");
7875 staticpro (&QCrelief
);
7876 QCconversion
= intern (":conversion");
7877 staticpro (&QCconversion
);
7878 QCcolor_symbols
= intern (":color-symbols");
7879 staticpro (&QCcolor_symbols
);
7880 QCheuristic_mask
= intern (":heuristic-mask");
7881 staticpro (&QCheuristic_mask
);
7882 QCindex
= intern (":index");
7883 staticpro (&QCindex
);
7884 QCmatrix
= intern (":matrix");
7885 staticpro (&QCmatrix
);
7886 QCcolor_adjustment
= intern (":color-adjustment");
7887 staticpro (&QCcolor_adjustment
);
7888 QCmask
= intern (":mask");
7889 staticpro (&QCmask
);
7891 Qlaplace
= intern ("laplace");
7892 staticpro (&Qlaplace
);
7893 Qemboss
= intern ("emboss");
7894 staticpro (&Qemboss
);
7895 Qedge_detection
= intern ("edge-detection");
7896 staticpro (&Qedge_detection
);
7897 Qheuristic
= intern ("heuristic");
7898 staticpro (&Qheuristic
);
7900 Qpostscript
= intern ("postscript");
7901 staticpro (&Qpostscript
);
7902 #ifdef HAVE_GHOSTSCRIPT
7903 QCloader
= intern (":loader");
7904 staticpro (&QCloader
);
7905 QCbounding_box
= intern (":bounding-box");
7906 staticpro (&QCbounding_box
);
7907 QCpt_width
= intern (":pt-width");
7908 staticpro (&QCpt_width
);
7909 QCpt_height
= intern (":pt-height");
7910 staticpro (&QCpt_height
);
7911 #endif /* HAVE_GHOSTSCRIPT */
7913 Qpbm
= intern ("pbm");
7916 Qxbm
= intern ("xbm");
7919 #if defined (HAVE_XPM) || defined (MAC_OS)
7920 Qxpm
= intern ("xpm");
7924 #if defined (HAVE_JPEG) || defined (MAC_OS)
7925 Qjpeg
= intern ("jpeg");
7929 #if defined (HAVE_TIFF) || defined (MAC_OS)
7930 Qtiff
= intern ("tiff");
7934 #if defined (HAVE_GIF) || defined (MAC_OS)
7935 Qgif
= intern ("gif");
7939 #if defined (HAVE_PNG) || defined (MAC_OS)
7940 Qpng
= intern ("png");
7944 defsubr (&Sclear_image_cache
);
7945 defsubr (&Simage_size
);
7946 defsubr (&Simage_mask_p
);
7950 defsubr (&Slookup_image
);
7953 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
7954 doc
: /* Non-nil means always draw a cross over disabled images.
7955 Disabled images are those having an `:conversion disabled' property.
7956 A cross is always drawn on black & white displays. */);
7957 cross_disabled_images
= 0;
7959 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7960 doc
: /* List of directories to search for window system bitmap files. */);
7961 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
7963 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
7964 doc
: /* Time after which cached images are removed from the cache.
7965 When an image has not been displayed this many seconds, remove it
7966 from the image cache. Value must be an integer or nil with nil
7967 meaning don't clear the cache. */);
7968 Vimage_cache_eviction_delay
= make_number (30 * 60);
7973 /* Image types that rely on external libraries are loaded dynamically
7974 if the library is available. */
7975 #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn())
7977 #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */
7978 #endif /* HAVE_NTGUI */
7984 Vimage_types
= Qnil
;
7986 define_image_type (&xbm_type
);
7987 define_image_type (&pbm_type
);
7989 #if defined (HAVE_XPM) || defined (MAC_OS)
7990 IF_LIB_AVAILABLE(init_xpm_functions
)
7991 define_image_type (&xpm_type
);
7994 #if defined (HAVE_JPEG) || defined (MAC_OS)
7995 IF_LIB_AVAILABLE(init_jpeg_functions
)
7996 define_image_type (&jpeg_type
);
7999 #if defined (HAVE_TIFF) || defined (MAC_OS)
8000 IF_LIB_AVAILABLE(init_tiff_functions
)
8001 define_image_type (&tiff_type
);
8004 #if defined (HAVE_GIF) || defined (MAC_OS)
8005 IF_LIB_AVAILABLE(init_gif_functions
)
8006 define_image_type (&gif_type
);
8009 #if defined (HAVE_PNG) || defined (MAC_OS)
8010 IF_LIB_AVAILABLE(init_png_functions
)
8011 define_image_type (&png_type
);
8014 #ifdef HAVE_GHOSTSCRIPT
8015 define_image_type (&gs_type
);
8019 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8022 init_image_func_pointer ();
8027 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8028 (do not change this comment) */