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. */
32 /* This makes the fields of a Display accessible, in Xlib header files. */
34 #define XLIB_ILLEGAL_ACCESS
39 #include "dispextern.h"
40 #include "blockinput.h"
47 #include <sys/types.h>
50 #define COLOR_TABLE_SUPPORT 1
52 typedef struct x_bitmap_record Bitmap_Record
;
53 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
54 #define NO_PIXMAP None
56 #define RGB_PIXEL_COLOR unsigned long
58 #define PIX_MASK_RETAIN(f) 0
59 #define PIX_MASK_DRAW(f) 1
60 #endif /* HAVE_X_WINDOWS */
66 /* W32_TODO : Color tables on W32. */
67 #undef COLOR_TABLE_SUPPORT
69 typedef struct w32_bitmap_record Bitmap_Record
;
70 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
73 #define RGB_PIXEL_COLOR COLORREF
75 #define PIX_MASK_RETAIN(f) 0
76 #define PIX_MASK_DRAW(f) 1
78 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
79 #define x_defined_color w32_defined_color
80 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
81 #endif /* HAVE_NTGUI */
89 #include <sys/param.h>
92 #include <QuickTime/QuickTime.h>
93 #else /* not MAC_OSX */
96 #include <TextUtils.h>
97 #include <ImageCompression.h>
98 #include <QuickTimeComponents.h>
99 #endif /* not MAC_OSX */
101 /* MAC_TODO : Color tables on Mac. */
102 #undef COLOR_TABLE_SUPPORT
104 #define ZPixmap 0 /* arbitrary */
105 typedef struct mac_bitmap_record Bitmap_Record
;
107 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
110 #define RGB_PIXEL_COLOR unsigned long
112 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
113 #define x_defined_color mac_defined_color
114 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
115 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
116 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
121 /* Search path for bitmap files. */
123 Lisp_Object Vx_bitmap_file_path
;
126 static void x_disable_image
P_ ((struct frame
*, struct image
*));
127 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
130 static void init_color_table
P_ ((void));
131 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
132 #ifdef COLOR_TABLE_SUPPORT
133 static void free_color_table
P_ ((void));
134 static unsigned long *colors_in_color_table
P_ ((int *n
));
135 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
138 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
139 id, which is just an int that this section returns. Bitmaps are
140 reference counted so they can be shared among frames.
142 Bitmap indices are guaranteed to be > 0, so a negative number can
143 be used to indicate no bitmap.
145 If you use x_create_bitmap_from_data, then you must keep track of
146 the bitmaps yourself. That is, creating a bitmap from the same
147 data more than once will not be caught. */
152 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
153 Display
*display
; /* not used */
155 int x
, y
; /* not used */
156 unsigned int width
, height
; /* not used */
157 unsigned long plane_mask
; /* not used */
158 int format
; /* not used */
161 xassert (x
== 0 && y
== 0);
164 SetRect (&ri
, 0, 0, width
, height
);
165 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
167 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
170 LockPixels (GetGWorldPixMap (pixmap
));
176 XPutPixel (ximage
, x
, y
, pixel
)
185 GetGWorld (&old_port
, &old_gdh
);
186 SetGWorld (ximage
, NULL
);
188 color
.red
= RED16_FROM_ULONG (pixel
);
189 color
.green
= GREEN16_FROM_ULONG (pixel
);
190 color
.blue
= BLUE16_FROM_ULONG (pixel
);
191 SetCPixel (x
, y
, &color
);
193 SetGWorld (old_port
, old_gdh
);
197 XGetPixel (ximage
, x
, y
)
205 GetGWorld (&old_port
, &old_gdh
);
206 SetGWorld (ximage
, NULL
);
208 GetCPixel (x
, y
, &color
);
210 SetGWorld (old_port
, old_gdh
);
211 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
218 UnlockPixels (GetGWorldPixMap (ximg
));
223 /* Functions to access the contents of a bitmap, given an id. */
226 x_bitmap_height (f
, id
)
230 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
234 x_bitmap_width (f
, id
)
238 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
241 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
243 x_bitmap_pixmap (f
, id
)
247 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
251 #ifdef HAVE_X_WINDOWS
253 x_bitmap_mask (f
, id
)
257 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
261 /* Allocate a new bitmap record. Returns index of new record. */
264 x_allocate_bitmap_record (f
)
267 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
270 if (dpyinfo
->bitmaps
== NULL
)
272 dpyinfo
->bitmaps_size
= 10;
274 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
275 dpyinfo
->bitmaps_last
= 1;
279 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
280 return ++dpyinfo
->bitmaps_last
;
282 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
283 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
286 dpyinfo
->bitmaps_size
*= 2;
288 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
289 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
290 return ++dpyinfo
->bitmaps_last
;
293 /* Add one reference to the reference count of the bitmap with id ID. */
296 x_reference_bitmap (f
, id
)
300 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
303 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
306 x_create_bitmap_from_data (f
, bits
, width
, height
)
309 unsigned int width
, height
;
311 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
314 #ifdef HAVE_X_WINDOWS
316 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
317 bits
, width
, height
);
320 #endif /* HAVE_X_WINDOWS */
324 bitmap
= CreateBitmap (width
, height
,
325 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
326 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
330 #endif /* HAVE_NTGUI */
333 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
338 id
= x_allocate_bitmap_record (f
);
340 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
341 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
343 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
346 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
347 dpyinfo
->bitmaps
[id
- 1].height
= height
;
348 dpyinfo
->bitmaps
[id
- 1].width
= width
;
349 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
351 #ifdef HAVE_X_WINDOWS
352 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
353 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
354 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
355 #endif /* HAVE_X_WINDOWS */
358 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
359 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
360 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
361 #endif /* HAVE_NTGUI */
366 /* Create bitmap from file FILE for frame F. */
369 x_create_bitmap_from_file (f
, file
)
374 return -1; /* MAC_TODO : bitmap support */
378 return -1; /* W32_TODO : bitmap support */
379 #endif /* HAVE_NTGUI */
381 #ifdef HAVE_X_WINDOWS
382 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
383 unsigned int width
, height
;
385 int xhot
, yhot
, result
, id
;
390 /* Look for an existing bitmap with the same name. */
391 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
393 if (dpyinfo
->bitmaps
[id
].refcount
394 && dpyinfo
->bitmaps
[id
].file
395 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
397 ++dpyinfo
->bitmaps
[id
].refcount
;
402 /* Search bitmap-file-path for the file, if appropriate. */
403 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
408 filename
= (char *) SDATA (found
);
410 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
411 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
412 if (result
!= BitmapSuccess
)
415 id
= x_allocate_bitmap_record (f
);
416 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
417 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
418 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
419 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
420 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
421 dpyinfo
->bitmaps
[id
- 1].height
= height
;
422 dpyinfo
->bitmaps
[id
- 1].width
= width
;
423 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
426 #endif /* HAVE_X_WINDOWS */
432 Free_Bitmap_Record (dpyinfo
, bm
)
433 Display_Info
*dpyinfo
;
436 #ifdef HAVE_X_WINDOWS
437 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
439 XFreePixmap (dpyinfo
->display
, bm
->mask
);
440 #endif /* HAVE_X_WINDOWS */
443 DeleteObject (bm
->pixmap
);
444 #endif /* HAVE_NTGUI */
447 xfree (bm
->bitmap_data
); /* Added ++kfs */
448 bm
->bitmap_data
= NULL
;
458 /* Remove reference to bitmap with id number ID. */
461 x_destroy_bitmap (f
, id
)
465 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
469 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
471 if (--bm
->refcount
== 0)
474 Free_Bitmap_Record (dpyinfo
, bm
);
480 /* Free all the bitmaps for the display specified by DPYINFO. */
483 x_destroy_all_bitmaps (dpyinfo
)
484 Display_Info
*dpyinfo
;
487 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
489 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
490 if (bm
->refcount
> 0)
491 Free_Bitmap_Record (dpyinfo
, bm
);
493 dpyinfo
->bitmaps_last
= 0;
497 #ifdef HAVE_X_WINDOWS
499 /* Useful functions defined in the section
500 `Image type independent image structures' below. */
502 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
503 unsigned long height
));
505 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
506 int depth
, XImagePtr
*ximg
,
509 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
512 /* Create a mask of a bitmap. Note is this not a perfect mask.
513 It's nicer with some borders in this context */
516 x_create_bitmap_mask (f
, id
)
521 XImagePtr ximg
, mask_img
;
522 unsigned long width
, height
;
525 unsigned long x
, y
, xp
, xm
, yp
, ym
;
528 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
533 pixmap
= x_bitmap_pixmap (f
, id
);
534 width
= x_bitmap_width (f
, id
);
535 height
= x_bitmap_height (f
, id
);
538 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
547 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
552 XDestroyImage (ximg
);
556 bg
= four_corners_best (ximg
, width
, height
);
558 for (y
= 0; y
< ximg
->height
; ++y
)
560 for (x
= 0; x
< ximg
->width
; ++x
)
562 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
563 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
564 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
565 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
566 if (XGetPixel (ximg
, x
, y
) == bg
567 && XGetPixel (ximg
, x
, yp
) == bg
568 && XGetPixel (ximg
, x
, ym
) == bg
569 && XGetPixel (ximg
, xp
, y
) == bg
570 && XGetPixel (ximg
, xp
, yp
) == bg
571 && XGetPixel (ximg
, xp
, ym
) == bg
572 && XGetPixel (ximg
, xm
, y
) == bg
573 && XGetPixel (ximg
, xm
, yp
) == bg
574 && XGetPixel (ximg
, xm
, ym
) == bg
)
575 XPutPixel (mask_img
, x
, y
, 0);
577 XPutPixel (mask_img
, x
, y
, 1);
581 xassert (interrupt_input_blocked
);
582 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
583 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
585 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
587 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
588 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
590 XDestroyImage (ximg
);
591 x_destroy_x_image (mask_img
);
596 #endif /* HAVE_X_WINDOWS */
599 /***********************************************************************
601 ***********************************************************************/
603 /* Value is the number of elements of vector VECTOR. */
605 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
607 /* List of supported image types. Use define_image_type to add new
608 types. Use lookup_image_type to find a type for a given symbol. */
610 static struct image_type
*image_types
;
612 /* A list of symbols, one for each supported image type. */
614 Lisp_Object Vimage_types
;
616 /* Cache for delayed-loading image types. */
618 static Lisp_Object Vimage_type_cache
;
620 /* The symbol `xbm' which is used as the type symbol for XBM images. */
626 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
627 extern Lisp_Object QCdata
, QCtype
;
628 extern Lisp_Object Qcenter
;
629 Lisp_Object QCascent
, QCmargin
, QCrelief
;
630 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
631 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
635 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
637 /* Time in seconds after which images should be removed from the cache
640 Lisp_Object Vimage_cache_eviction_delay
;
642 /* Function prototypes. */
644 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
645 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
646 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
647 static void x_laplace
P_ ((struct frame
*, struct image
*));
648 static void x_emboss
P_ ((struct frame
*, struct image
*));
649 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
652 #define CACHE_IMAGE_TYPE(type, status) \
653 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
655 #define ADD_IMAGE_TYPE(type) \
656 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
658 /* Define a new image type from TYPE. This adds a copy of TYPE to
659 image_types and caches the loading status of TYPE. */
662 define_image_type (type
, loaded
)
663 struct image_type
*type
;
672 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
673 The initialized data segment is read-only. */
674 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
675 bcopy (type
, p
, sizeof *p
);
676 p
->next
= image_types
;
681 CACHE_IMAGE_TYPE (*type
->type
, success
);
686 /* Look up image type SYMBOL, and return a pointer to its image_type
687 structure. Value is null if SYMBOL is not a known image type. */
689 static INLINE
struct image_type
*
690 lookup_image_type (symbol
)
693 struct image_type
*type
;
695 /* We must initialize the image-type if it hasn't been already. */
696 if (NILP (Finit_image_library (symbol
, Qnil
)))
697 return 0; /* unimplemented */
699 for (type
= image_types
; type
; type
= type
->next
)
700 if (EQ (symbol
, *type
->type
))
707 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
708 valid image specification is a list whose car is the symbol
709 `image', and whose rest is a property list. The property list must
710 contain a value for key `:type'. That value must be the name of a
711 supported image type. The rest of the property list depends on the
715 valid_image_p (object
)
724 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
725 if (EQ (XCAR (tem
), QCtype
))
728 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
730 struct image_type
*type
;
731 type
= lookup_image_type (XCAR (tem
));
733 valid_p
= type
->valid_p (object
);
744 /* Log error message with format string FORMAT and argument ARG.
745 Signaling an error, e.g. when an image cannot be loaded, is not a
746 good idea because this would interrupt redisplay, and the error
747 message display would lead to another redisplay. This function
748 therefore simply displays a message. */
751 image_error (format
, arg1
, arg2
)
753 Lisp_Object arg1
, arg2
;
755 add_to_log (format
, arg1
, arg2
);
760 /***********************************************************************
762 ***********************************************************************/
764 enum image_value_type
766 IMAGE_DONT_CHECK_VALUE_TYPE
,
768 IMAGE_STRING_OR_NIL_VALUE
,
770 IMAGE_POSITIVE_INTEGER_VALUE
,
771 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
772 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
775 IMAGE_FUNCTION_VALUE
,
780 /* Structure used when parsing image specifications. */
784 /* Name of keyword. */
787 /* The type of value allowed. */
788 enum image_value_type type
;
790 /* Non-zero means key must be present. */
793 /* Used to recognize duplicate keywords in a property list. */
796 /* The value that was found. */
801 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
803 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
806 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
807 has the format (image KEYWORD VALUE ...). One of the keyword/
808 value pairs must be `:type TYPE'. KEYWORDS is a vector of
809 image_keywords structures of size NKEYWORDS describing other
810 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
813 parse_image_spec (spec
, keywords
, nkeywords
, type
)
815 struct image_keyword
*keywords
;
826 while (CONSP (plist
))
828 Lisp_Object key
, value
;
830 /* First element of a pair must be a symbol. */
832 plist
= XCDR (plist
);
836 /* There must follow a value. */
839 value
= XCAR (plist
);
840 plist
= XCDR (plist
);
842 /* Find key in KEYWORDS. Error if not found. */
843 for (i
= 0; i
< nkeywords
; ++i
)
844 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
850 /* Record that we recognized the keyword. If a keywords
851 was found more than once, it's an error. */
852 keywords
[i
].value
= value
;
855 if (keywords
[i
].count
> 1)
858 /* Check type of value against allowed type. */
859 switch (keywords
[i
].type
)
861 case IMAGE_STRING_VALUE
:
862 if (!STRINGP (value
))
866 case IMAGE_STRING_OR_NIL_VALUE
:
867 if (!STRINGP (value
) && !NILP (value
))
871 case IMAGE_SYMBOL_VALUE
:
872 if (!SYMBOLP (value
))
876 case IMAGE_POSITIVE_INTEGER_VALUE
:
877 if (!INTEGERP (value
) || XINT (value
) <= 0)
881 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
882 if (INTEGERP (value
) && XINT (value
) >= 0)
885 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
886 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
890 case IMAGE_ASCENT_VALUE
:
891 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
893 else if (INTEGERP (value
)
895 && XINT (value
) <= 100)
899 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
900 if (!INTEGERP (value
) || XINT (value
) < 0)
904 case IMAGE_DONT_CHECK_VALUE_TYPE
:
907 case IMAGE_FUNCTION_VALUE
:
908 value
= indirect_function (value
);
911 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
915 case IMAGE_NUMBER_VALUE
:
916 if (!INTEGERP (value
) && !FLOATP (value
))
920 case IMAGE_INTEGER_VALUE
:
921 if (!INTEGERP (value
))
925 case IMAGE_BOOL_VALUE
:
926 if (!NILP (value
) && !EQ (value
, Qt
))
935 if (EQ (key
, QCtype
) && !EQ (type
, value
))
939 /* Check that all mandatory fields are present. */
940 for (i
= 0; i
< nkeywords
; ++i
)
941 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
948 /* Return the value of KEY in image specification SPEC. Value is nil
949 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
950 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
953 image_spec_value (spec
, key
, found
)
954 Lisp_Object spec
, key
;
959 xassert (valid_image_p (spec
));
961 for (tail
= XCDR (spec
);
962 CONSP (tail
) && CONSP (XCDR (tail
));
963 tail
= XCDR (XCDR (tail
)))
965 if (EQ (XCAR (tail
), key
))
969 return XCAR (XCDR (tail
));
979 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
980 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
981 PIXELS non-nil means return the size in pixels, otherwise return the
982 size in canonical character units.
983 FRAME is the frame on which the image will be displayed. FRAME nil
984 or omitted means use the selected frame. */)
985 (spec
, pixels
, frame
)
986 Lisp_Object spec
, pixels
, frame
;
991 if (valid_image_p (spec
))
993 struct frame
*f
= check_x_frame (frame
);
994 int id
= lookup_image (f
, spec
);
995 struct image
*img
= IMAGE_FROM_ID (f
, id
);
996 int width
= img
->width
+ 2 * img
->hmargin
;
997 int height
= img
->height
+ 2 * img
->vmargin
;
1000 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1001 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1003 size
= Fcons (make_number (width
), make_number (height
));
1006 error ("Invalid image specification");
1012 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1013 doc
: /* Return t if image SPEC has a mask bitmap.
1014 FRAME is the frame on which the image will be displayed. FRAME nil
1015 or omitted means use the selected frame. */)
1017 Lisp_Object spec
, frame
;
1022 if (valid_image_p (spec
))
1024 struct frame
*f
= check_x_frame (frame
);
1025 int id
= lookup_image (f
, spec
);
1026 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1031 error ("Invalid image specification");
1037 /***********************************************************************
1038 Image type independent image structures
1039 ***********************************************************************/
1041 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1042 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1045 /* Allocate and return a new image structure for image specification
1046 SPEC. SPEC has a hash value of HASH. */
1048 static struct image
*
1049 make_image (spec
, hash
)
1053 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1055 xassert (valid_image_p (spec
));
1056 bzero (img
, sizeof *img
);
1057 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1058 xassert (img
->type
!= NULL
);
1060 img
->data
.lisp_val
= Qnil
;
1061 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1067 /* Free image IMG which was used on frame F, including its resources. */
1076 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1078 /* Remove IMG from the hash table of its cache. */
1080 img
->prev
->next
= img
->next
;
1082 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1085 img
->next
->prev
= img
->prev
;
1087 c
->images
[img
->id
] = NULL
;
1089 /* Free resources, then free IMG. */
1090 img
->type
->free (f
, img
);
1096 /* Prepare image IMG for display on frame F. Must be called before
1097 drawing an image. */
1100 prepare_image_for_display (f
, img
)
1106 /* We're about to display IMG, so set its timestamp to `now'. */
1108 img
->timestamp
= EMACS_SECS (t
);
1110 /* If IMG doesn't have a pixmap yet, load it now, using the image
1111 type dependent loader function. */
1112 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1113 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1117 /* Value is the number of pixels for the ascent of image IMG when
1118 drawn in face FACE. */
1121 image_ascent (img
, face
, slice
)
1124 struct glyph_slice
*slice
;
1129 if (slice
->height
== img
->height
)
1130 height
= img
->height
+ img
->vmargin
;
1131 else if (slice
->y
== 0)
1132 height
= slice
->height
+ img
->vmargin
;
1134 height
= slice
->height
;
1136 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1141 /* W32 specific version. Why?. ++kfs */
1142 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1143 - FONT_BASE(face
->font
)) / 2;
1145 /* This expression is arranged so that if the image can't be
1146 exactly centered, it will be moved slightly up. This is
1147 because a typical font is `top-heavy' (due to the presence
1148 uppercase letters), so the image placement should err towards
1149 being top-heavy too. It also just generally looks better. */
1150 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1151 #endif /* HAVE_NTGUI */
1154 ascent
= height
/ 2;
1157 ascent
= (int) (height
* img
->ascent
/ 100.0);
1163 /* Image background colors. */
1165 /* Find the "best" corner color of a bitmap.
1166 On W32, XIMG is assumed to a device context with the bitmap selected. */
1168 static RGB_PIXEL_COLOR
1169 four_corners_best (ximg
, width
, height
)
1170 XImagePtr_or_DC ximg
;
1171 unsigned long width
, height
;
1173 RGB_PIXEL_COLOR corners
[4], best
;
1176 /* Get the colors at the corners of ximg. */
1177 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1178 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1179 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1180 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1182 /* Choose the most frequently found color as background. */
1183 for (i
= best_count
= 0; i
< 4; ++i
)
1187 for (j
= n
= 0; j
< 4; ++j
)
1188 if (corners
[i
] == corners
[j
])
1192 best
= corners
[i
], best_count
= n
;
1198 /* Portability macros */
1202 #define Destroy_Image(img_dc, prev) \
1203 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1205 #define Free_Pixmap(display, pixmap) \
1206 DeleteObject (pixmap)
1210 #define Destroy_Image(ximg, dummy) \
1211 XDestroyImage (ximg)
1213 #define Free_Pixmap(display, pixmap) \
1214 XFreePixmap (display, pixmap)
1216 #endif /* HAVE_NTGUI */
1219 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1220 it is guessed heuristically. If non-zero, XIMG is an existing
1221 XImage object (or device context with the image selected on W32) to
1222 use for the heuristic. */
1225 image_background (img
, f
, ximg
)
1228 XImagePtr_or_DC ximg
;
1230 if (! img
->background_valid
)
1231 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1233 int free_ximg
= !ximg
;
1236 #endif /* HAVE_NTGUI */
1241 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1242 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1244 HDC frame_dc
= get_frame_dc (f
);
1245 ximg
= CreateCompatibleDC (frame_dc
);
1246 release_frame_dc (f
, frame_dc
);
1247 prev
= SelectObject (ximg
, img
->pixmap
);
1248 #endif /* !HAVE_NTGUI */
1251 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1254 Destroy_Image (ximg
, prev
);
1256 img
->background_valid
= 1;
1259 return img
->background
;
1262 /* Return the `background_transparent' field of IMG. If IMG doesn't
1263 have one yet, it is guessed heuristically. If non-zero, MASK is an
1264 existing XImage object to use for the heuristic. */
1267 image_background_transparent (img
, f
, mask
)
1270 XImagePtr_or_DC mask
;
1272 if (! img
->background_transparent_valid
)
1273 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1277 int free_mask
= !mask
;
1280 #endif /* HAVE_NTGUI */
1285 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1286 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1288 HDC frame_dc
= get_frame_dc (f
);
1289 mask
= CreateCompatibleDC (frame_dc
);
1290 release_frame_dc (f
, frame_dc
);
1291 prev
= SelectObject (mask
, img
->mask
);
1292 #endif /* HAVE_NTGUI */
1295 img
->background_transparent
1296 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1299 Destroy_Image (mask
, prev
);
1302 img
->background_transparent
= 0;
1304 img
->background_transparent_valid
= 1;
1307 return img
->background_transparent
;
1311 /***********************************************************************
1312 Helper functions for X image types
1313 ***********************************************************************/
1315 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1317 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1318 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1320 Lisp_Object color_name
,
1321 unsigned long dflt
));
1324 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1325 free the pixmap if any. MASK_P non-zero means clear the mask
1326 pixmap if any. COLORS_P non-zero means free colors allocated for
1327 the image, if any. */
1330 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1333 int pixmap_p
, mask_p
, colors_p
;
1335 if (pixmap_p
&& img
->pixmap
)
1337 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1338 img
->pixmap
= NO_PIXMAP
;
1339 img
->background_valid
= 0;
1342 if (mask_p
&& img
->mask
)
1344 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1345 img
->mask
= NO_PIXMAP
;
1346 img
->background_transparent_valid
= 0;
1349 if (colors_p
&& img
->ncolors
)
1351 /* MAC_TODO: color table support. */
1352 /* W32_TODO: color table support. */
1353 #ifdef HAVE_X_WINDOWS
1354 x_free_colors (f
, img
->colors
, img
->ncolors
);
1355 #endif /* HAVE_X_WINDOWS */
1356 xfree (img
->colors
);
1362 /* Free X resources of image IMG which is used on frame F. */
1365 x_clear_image (f
, img
)
1370 x_clear_image_1 (f
, img
, 1, 1, 1);
1375 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1376 cannot be allocated, use DFLT. Add a newly allocated color to
1377 IMG->colors, so that it can be freed again. Value is the pixel
1380 static unsigned long
1381 x_alloc_image_color (f
, img
, color_name
, dflt
)
1384 Lisp_Object color_name
;
1388 unsigned long result
;
1390 xassert (STRINGP (color_name
));
1392 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1394 /* This isn't called frequently so we get away with simply
1395 reallocating the color vector to the needed size, here. */
1398 (unsigned long *) xrealloc (img
->colors
,
1399 img
->ncolors
* sizeof *img
->colors
);
1400 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1401 result
= color
.pixel
;
1411 /***********************************************************************
1413 ***********************************************************************/
1415 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1416 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1418 /* Return a new, initialized image cache that is allocated from the
1419 heap. Call free_image_cache to free an image cache. */
1421 struct image_cache
*
1424 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1427 bzero (c
, sizeof *c
);
1429 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1430 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1431 c
->buckets
= (struct image
**) xmalloc (size
);
1432 bzero (c
->buckets
, size
);
1437 /* Free image cache of frame F. Be aware that X frames share images
1441 free_image_cache (f
)
1444 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1449 /* Cache should not be referenced by any frame when freed. */
1450 xassert (c
->refcount
== 0);
1452 for (i
= 0; i
< c
->used
; ++i
)
1453 free_image (f
, c
->images
[i
]);
1457 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1462 /* Clear image cache of frame F. FORCE_P non-zero means free all
1463 images. FORCE_P zero means clear only images that haven't been
1464 displayed for some time. Should be called from time to time to
1465 reduce the number of loaded images. If image-eviction-seconds is
1466 non-nil, this frees images in the cache which weren't displayed for
1467 at least that many seconds. */
1470 clear_image_cache (f
, force_p
)
1474 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1476 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1483 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1485 /* Block input so that we won't be interrupted by a SIGIO
1486 while being in an inconsistent state. */
1489 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1491 struct image
*img
= c
->images
[i
];
1493 && (force_p
|| img
->timestamp
< old
))
1495 free_image (f
, img
);
1500 /* We may be clearing the image cache because, for example,
1501 Emacs was iconified for a longer period of time. In that
1502 case, current matrices may still contain references to
1503 images freed above. So, clear these matrices. */
1506 Lisp_Object tail
, frame
;
1508 FOR_EACH_FRAME (tail
, frame
)
1510 struct frame
*f
= XFRAME (frame
);
1511 if (FRAME_WINDOW_P (f
)
1512 && FRAME_X_IMAGE_CACHE (f
) == c
)
1513 clear_current_matrices (f
);
1516 ++windows_or_buffers_changed
;
1524 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1526 doc
: /* Clear the image cache of FRAME.
1527 FRAME nil or omitted means use the selected frame.
1528 FRAME t means clear the image caches of all frames. */)
1536 FOR_EACH_FRAME (tail
, frame
)
1537 if (FRAME_WINDOW_P (XFRAME (frame
)))
1538 clear_image_cache (XFRAME (frame
), 1);
1541 clear_image_cache (check_x_frame (frame
), 1);
1547 /* Compute masks and transform image IMG on frame F, as specified
1548 by the image's specification, */
1551 postprocess_image (f
, img
)
1555 /* Manipulation of the image's mask. */
1558 Lisp_Object conversion
, spec
;
1563 /* `:heuristic-mask t'
1565 means build a mask heuristically.
1566 `:heuristic-mask (R G B)'
1567 `:mask (heuristic (R G B))'
1568 means build a mask from color (R G B) in the
1571 means remove a mask, if any. */
1573 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1575 x_build_heuristic_mask (f
, img
, mask
);
1580 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1582 if (EQ (mask
, Qheuristic
))
1583 x_build_heuristic_mask (f
, img
, Qt
);
1584 else if (CONSP (mask
)
1585 && EQ (XCAR (mask
), Qheuristic
))
1587 if (CONSP (XCDR (mask
)))
1588 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1590 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1592 else if (NILP (mask
) && found_p
&& img
->mask
)
1594 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1595 img
->mask
= NO_PIXMAP
;
1600 /* Should we apply an image transformation algorithm? */
1601 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1602 if (EQ (conversion
, Qdisabled
))
1603 x_disable_image (f
, img
);
1604 else if (EQ (conversion
, Qlaplace
))
1606 else if (EQ (conversion
, Qemboss
))
1608 else if (CONSP (conversion
)
1609 && EQ (XCAR (conversion
), Qedge_detection
))
1612 tem
= XCDR (conversion
);
1614 x_edge_detection (f
, img
,
1615 Fplist_get (tem
, QCmatrix
),
1616 Fplist_get (tem
, QCcolor_adjustment
));
1622 /* Return the id of image with Lisp specification SPEC on frame F.
1623 SPEC must be a valid Lisp image specification (see valid_image_p). */
1626 lookup_image (f
, spec
)
1630 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1632 /* Work around a problem with MinGW builds of graphics libraries
1633 not honoring calling conventions. */
1639 struct gcpro gcpro1
;
1642 /* F must be a window-system frame, and SPEC must be a valid image
1644 xassert (FRAME_WINDOW_P (f
));
1645 xassert (valid_image_p (spec
));
1649 /* Look up SPEC in the hash table of the image cache. */
1650 hash
= sxhash (spec
, 0);
1651 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1653 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1654 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1657 /* If not found, create a new image and cache it. */
1660 extern Lisp_Object Qpostscript
;
1663 img
= make_image (spec
, hash
);
1664 cache_image (f
, img
);
1665 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1667 /* If we can't load the image, and we don't have a width and
1668 height, use some arbitrary width and height so that we can
1669 draw a rectangle for it. */
1670 if (img
->load_failed_p
)
1674 value
= image_spec_value (spec
, QCwidth
, NULL
);
1675 img
->width
= (INTEGERP (value
)
1676 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1677 value
= image_spec_value (spec
, QCheight
, NULL
);
1678 img
->height
= (INTEGERP (value
)
1679 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1683 /* Handle image type independent image attributes
1684 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1685 `:background COLOR'. */
1686 Lisp_Object ascent
, margin
, relief
, bg
;
1688 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1689 if (INTEGERP (ascent
))
1690 img
->ascent
= XFASTINT (ascent
);
1691 else if (EQ (ascent
, Qcenter
))
1692 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1694 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1695 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1696 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1697 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1698 && INTEGERP (XCDR (margin
)))
1700 if (XINT (XCAR (margin
)) > 0)
1701 img
->hmargin
= XFASTINT (XCAR (margin
));
1702 if (XINT (XCDR (margin
)) > 0)
1703 img
->vmargin
= XFASTINT (XCDR (margin
));
1706 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1707 if (INTEGERP (relief
))
1709 img
->relief
= XINT (relief
);
1710 img
->hmargin
+= abs (img
->relief
);
1711 img
->vmargin
+= abs (img
->relief
);
1714 if (! img
->background_valid
)
1716 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1720 = x_alloc_image_color (f
, img
, bg
,
1721 FRAME_BACKGROUND_PIXEL (f
));
1722 img
->background_valid
= 1;
1726 /* Do image transformations and compute masks, unless we
1727 don't have the image yet. */
1728 if (!EQ (*img
->type
->type
, Qpostscript
))
1729 postprocess_image (f
, img
);
1735 /* We're using IMG, so set its timestamp to `now'. */
1736 EMACS_GET_TIME (now
);
1737 img
->timestamp
= EMACS_SECS (now
);
1741 /* Value is the image id. */
1746 /* Cache image IMG in the image cache of frame F. */
1749 cache_image (f
, img
)
1753 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1756 /* Find a free slot in c->images. */
1757 for (i
= 0; i
< c
->used
; ++i
)
1758 if (c
->images
[i
] == NULL
)
1761 /* If no free slot found, maybe enlarge c->images. */
1762 if (i
== c
->used
&& c
->used
== c
->size
)
1765 c
->images
= (struct image
**) xrealloc (c
->images
,
1766 c
->size
* sizeof *c
->images
);
1769 /* Add IMG to c->images, and assign IMG an id. */
1775 /* Add IMG to the cache's hash table. */
1776 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1777 img
->next
= c
->buckets
[i
];
1779 img
->next
->prev
= img
;
1781 c
->buckets
[i
] = img
;
1785 /* Call FN on every image in the image cache of frame F. Used to mark
1786 Lisp Objects in the image cache. */
1789 forall_images_in_image_cache (f
, fn
)
1791 void (*fn
) P_ ((struct image
*img
));
1793 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1795 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1799 for (i
= 0; i
< c
->used
; ++i
)
1808 /***********************************************************************
1809 X / MAC / W32 support code
1810 ***********************************************************************/
1814 /* Macro for defining functions that will be loaded from image DLLs. */
1815 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1817 /* Macro for loading those image functions from the library. */
1818 #define LOAD_IMGLIB_FN(lib,func) { \
1819 fn_##func = (void *) GetProcAddress (lib, #func); \
1820 if (!fn_##func) return 0; \
1823 /* Load a DLL implementing an image type.
1824 The `image-library-alist' variable associates a symbol,
1825 identifying an image type, to a list of possible filenames.
1826 The function returns NULL if no library could be loaded for
1827 the given image type, or if the library was previously loaded;
1828 else the handle of the DLL. */
1830 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
1832 HMODULE library
= NULL
;
1834 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
1836 Lisp_Object dlls
= Fassq (type
, libraries
);
1839 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
1841 CHECK_STRING_CAR (dlls
);
1842 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
1850 #endif /* HAVE_NTGUI */
1852 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1853 XImagePtr
*, Pixmap
*));
1854 static void x_destroy_x_image
P_ ((XImagePtr
));
1855 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1858 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1859 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1860 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1861 via xmalloc. Print error messages via image_error if an error
1862 occurs. Value is non-zero if successful.
1864 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1865 should indicate the bit depth of the image. */
1868 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1870 int width
, height
, depth
;
1874 #ifdef HAVE_X_WINDOWS
1875 Display
*display
= FRAME_X_DISPLAY (f
);
1876 Window window
= FRAME_X_WINDOW (f
);
1877 Screen
*screen
= FRAME_X_SCREEN (f
);
1879 xassert (interrupt_input_blocked
);
1882 depth
= DefaultDepthOfScreen (screen
);
1883 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1884 depth
, ZPixmap
, 0, NULL
, width
, height
,
1885 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1888 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1892 /* Allocate image raster. */
1893 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1895 /* Allocate a pixmap of the same size. */
1896 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1897 if (*pixmap
== NO_PIXMAP
)
1899 x_destroy_x_image (*ximg
);
1901 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1906 #endif /* HAVE_X_WINDOWS */
1910 BITMAPINFOHEADER
*header
;
1912 int scanline_width_bits
;
1914 int palette_colors
= 0;
1919 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1920 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1922 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1926 scanline_width_bits
= width
* depth
;
1927 remainder
= scanline_width_bits
% 32;
1930 scanline_width_bits
+= 32 - remainder
;
1932 /* Bitmaps with a depth less than 16 need a palette. */
1933 /* BITMAPINFO structure already contains the first RGBQUAD. */
1935 palette_colors
= 1 << depth
- 1;
1937 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1940 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1944 header
= &((*ximg
)->info
.bmiHeader
);
1945 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1946 header
->biSize
= sizeof (*header
);
1947 header
->biWidth
= width
;
1948 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1949 header
->biPlanes
= 1;
1950 header
->biBitCount
= depth
;
1951 header
->biCompression
= BI_RGB
;
1952 header
->biClrUsed
= palette_colors
;
1954 /* TODO: fill in palette. */
1957 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1958 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1959 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1960 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1961 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1962 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1963 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1964 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1967 hdc
= get_frame_dc (f
);
1969 /* Create a DIBSection and raster array for the bitmap,
1970 and store its handle in *pixmap. */
1971 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1972 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1973 &((*ximg
)->data
), NULL
, 0);
1975 /* Realize display palette and garbage all frames. */
1976 release_frame_dc (f
, hdc
);
1978 if (*pixmap
== NULL
)
1980 DWORD err
= GetLastError();
1981 Lisp_Object errcode
;
1982 /* All system errors are < 10000, so the following is safe. */
1983 XSETINT (errcode
, (int) err
);
1984 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1985 x_destroy_x_image (*ximg
);
1991 #endif /* HAVE_NTGUI */
1994 Display
*display
= FRAME_X_DISPLAY (f
);
1995 Window window
= FRAME_X_WINDOW (f
);
1997 xassert (interrupt_input_blocked
);
1999 /* Allocate a pixmap of the same size. */
2000 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2001 if (*pixmap
== NO_PIXMAP
)
2003 x_destroy_x_image (*ximg
);
2005 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2009 LockPixels (GetGWorldPixMap (*pixmap
));
2017 /* Destroy XImage XIMG. Free XIMG->data. */
2020 x_destroy_x_image (ximg
)
2023 xassert (interrupt_input_blocked
);
2026 #ifdef HAVE_X_WINDOWS
2029 XDestroyImage (ximg
);
2030 #endif /* HAVE_X_WINDOWS */
2032 /* Data will be freed by DestroyObject. */
2035 #endif /* HAVE_NTGUI */
2037 XDestroyImage (ximg
);
2043 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2044 are width and height of both the image and pixmap. */
2047 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2053 #ifdef HAVE_X_WINDOWS
2056 xassert (interrupt_input_blocked
);
2057 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2058 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2059 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2060 #endif /* HAVE_X_WINDOWS */
2063 #if 0 /* I don't think this is necessary looking at where it is used. */
2064 HDC hdc
= get_frame_dc (f
);
2065 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2066 release_frame_dc (f
, hdc
);
2068 #endif /* HAVE_NTGUI */
2071 xassert (ximg
== pixmap
);
2076 /***********************************************************************
2078 ***********************************************************************/
2080 static unsigned char *slurp_file
P_ ((char *, int *));
2083 /* Find image file FILE. Look in data-directory, then
2084 x-bitmap-file-path. Value is the full name of the file found, or
2085 nil if not found. */
2088 x_find_image_file (file
)
2091 Lisp_Object file_found
, search_path
;
2092 struct gcpro gcpro1
, gcpro2
;
2096 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2097 GCPRO2 (file_found
, search_path
);
2099 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2100 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2112 /* Read FILE into memory. Value is a pointer to a buffer allocated
2113 with xmalloc holding FILE's contents. Value is null if an error
2114 occurred. *SIZE is set to the size of the file. */
2116 static unsigned char *
2117 slurp_file (file
, size
)
2122 unsigned char *buf
= NULL
;
2125 if (stat (file
, &st
) == 0
2126 && (fp
= fopen (file
, "rb")) != NULL
2127 && (buf
= (char *) xmalloc (st
.st_size
),
2128 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2151 /***********************************************************************
2152 MAC Image Load Functions
2153 ***********************************************************************/
2155 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2158 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2162 find_image_fsspec (specified_file
, file
, fss
)
2163 Lisp_Object specified_file
, *file
;
2166 #if TARGET_API_MAC_CARBON
2169 Str255 mac_pathname
;
2173 *file
= x_find_image_file (specified_file
);
2174 if (!STRINGP (*file
))
2175 return fnfErr
; /* file or directory not found;
2176 incomplete pathname */
2177 /* Try to open the image file. */
2178 #if TARGET_API_MAC_CARBON
2179 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2181 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2183 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2185 c2pstr (mac_pathname
);
2186 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2192 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2200 GraphicsImportComponent gi
;
2203 short draw_all_pixels
;
2204 Lisp_Object specified_bg
;
2209 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2213 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2218 /* read from file system spec */
2219 err
= GraphicsImportSetDataFile (gi
, fss
);
2222 image_error ("Cannot set fsspec to graphics importer for '%s'",
2229 /* read from data handle */
2230 err
= GraphicsImportSetDataHandle (gi
, dh
);
2233 image_error ("Cannot set data handle to graphics importer for `%s'",
2238 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2241 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2244 width
= img
->width
= rect
.right
- rect
.left
;
2245 height
= img
->height
= rect
.bottom
- rect
.top
;
2246 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2248 /* Don't check the error code here. It may have an undocumented
2252 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2256 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2258 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2259 if (!STRINGP (specified_bg
) ||
2260 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2262 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2263 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2264 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2265 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2269 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2271 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2276 GetGWorld (&old_port
, &old_gdh
);
2277 SetGWorld (ximg
, NULL
);
2278 bg_color
.red
= color
.red
;
2279 bg_color
.green
= color
.green
;
2280 bg_color
.blue
= color
.blue
;
2281 RGBBackColor (&bg_color
);
2282 #if TARGET_API_MAC_CARBON
2283 GetPortBounds (ximg
, &rect
);
2286 EraseRect (&(ximg
->portRect
));
2288 SetGWorld (old_port
, old_gdh
);
2290 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2291 GraphicsImportDraw (gi
);
2292 CloseComponent (gi
);
2294 /* Maybe fill in the background field while we have ximg handy. */
2295 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2296 IMAGE_BACKGROUND (img
, f
, ximg
);
2298 /* Put the image into the pixmap. */
2299 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2300 x_destroy_x_image (ximg
);
2304 CloseComponent (gi
);
2309 /* Load an image using the QuickTime Graphics Importer.
2310 Note: The alpha channel does not work for PNG images. */
2312 image_load_quicktime (f
, img
, type
)
2317 Lisp_Object specified_file
;
2318 Lisp_Object specified_data
;
2321 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2322 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2324 if (NILP (specified_data
))
2326 /* Read from a file */
2330 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2334 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2336 image_error ("Cannot open `%s'", file
, Qnil
);
2339 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2343 /* Memory source! */
2347 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2350 image_error ("Cannot allocate data handle for `%s'",
2354 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2362 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2363 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2364 So don't use this function directly but determine at runtime
2365 whether it exists. */
2366 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2367 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2368 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2372 init_image_func_pointer ()
2374 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2376 MyCGImageCreateWithPNGDataProvider
2377 = (CGImageCreateWithPNGDataProviderProcType
)
2378 NSAddressOfSymbol (NSLookupAndBindSymbol
2379 ("_CGImageCreateWithPNGDataProvider"));
2382 MyCGImageCreateWithPNGDataProvider
= NULL
;
2387 image_load_quartz2d (f
, img
, png_p
)
2392 Lisp_Object file
, specified_file
;
2393 Lisp_Object specified_data
, specified_bg
;
2394 struct gcpro gcpro1
;
2395 CGDataProviderRef source
;
2399 XImagePtr ximg
= NULL
;
2400 CGContextRef context
;
2403 /* Open the file. */
2404 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2405 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2410 if (NILP (specified_data
))
2415 file
= x_find_image_file (specified_file
);
2416 if (!STRINGP (file
))
2418 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2422 path
= cfstring_create_with_utf8_cstring (SDATA (file
));
2423 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2424 kCFURLPOSIXPathStyle
, 0);
2426 source
= CGDataProviderCreateWithURL (url
);
2430 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2431 SBYTES (specified_data
), NULL
);
2434 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2435 kCGRenderingIntentDefault
);
2437 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2438 kCGRenderingIntentDefault
);
2440 CGDataProviderRelease (source
);
2444 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2450 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2451 if (!STRINGP (specified_bg
) ||
2452 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2454 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2455 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2456 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2457 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2460 width
= img
->width
= CGImageGetWidth (image
);
2461 height
= img
->height
= CGImageGetHeight (image
);
2462 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2464 CGImageRelease (image
);
2468 rectangle
= CGRectMake (0, 0, width
, height
);
2469 QDBeginCGContext (ximg
, &context
);
2472 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2473 color
.green
/ 65535.0,
2474 color
.blue
/ 65535.0, 1.0);
2475 CGContextFillRect (context
, rectangle
);
2477 CGContextDrawImage (context
, rectangle
, image
);
2478 QDEndCGContext (ximg
, &context
);
2479 CGImageRelease (image
);
2481 /* Maybe fill in the background field while we have ximg handy. */
2482 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2483 IMAGE_BACKGROUND (img
, f
, ximg
);
2485 /* Put the image into the pixmap. */
2486 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2487 x_destroy_x_image (ximg
);
2496 /***********************************************************************
2498 ***********************************************************************/
2500 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2501 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2502 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2503 unsigned char *, unsigned char *));
2504 static int xbm_image_p
P_ ((Lisp_Object object
));
2505 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2506 int *, int *, unsigned char **));
2507 static int xbm_file_p
P_ ((Lisp_Object
));
2510 /* Indices of image specification fields in xbm_format, below. */
2512 enum xbm_keyword_index
2530 /* Vector of image_keyword structures describing the format
2531 of valid XBM image specifications. */
2533 static struct image_keyword xbm_format
[XBM_LAST
] =
2535 {":type", IMAGE_SYMBOL_VALUE
, 1},
2536 {":file", IMAGE_STRING_VALUE
, 0},
2537 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2538 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2539 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2540 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2541 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2542 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2543 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2544 {":relief", IMAGE_INTEGER_VALUE
, 0},
2545 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2546 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2547 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2550 /* Structure describing the image type XBM. */
2552 static struct image_type xbm_type
=
2561 /* Tokens returned from xbm_scan. */
2570 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2571 A valid specification is a list starting with the symbol `image'
2572 The rest of the list is a property list which must contain an
2575 If the specification specifies a file to load, it must contain
2576 an entry `:file FILENAME' where FILENAME is a string.
2578 If the specification is for a bitmap loaded from memory it must
2579 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2580 WIDTH and HEIGHT are integers > 0. DATA may be:
2582 1. a string large enough to hold the bitmap data, i.e. it must
2583 have a size >= (WIDTH + 7) / 8 * HEIGHT
2585 2. a bool-vector of size >= WIDTH * HEIGHT
2587 3. a vector of strings or bool-vectors, one for each line of the
2590 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2591 may not be specified in this case because they are defined in the
2594 Both the file and data forms may contain the additional entries
2595 `:background COLOR' and `:foreground COLOR'. If not present,
2596 foreground and background of the frame on which the image is
2597 displayed is used. */
2600 xbm_image_p (object
)
2603 struct image_keyword kw
[XBM_LAST
];
2605 bcopy (xbm_format
, kw
, sizeof kw
);
2606 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2609 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2611 if (kw
[XBM_FILE
].count
)
2613 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2616 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2618 /* In-memory XBM file. */
2619 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2627 /* Entries for `:width', `:height' and `:data' must be present. */
2628 if (!kw
[XBM_WIDTH
].count
2629 || !kw
[XBM_HEIGHT
].count
2630 || !kw
[XBM_DATA
].count
)
2633 data
= kw
[XBM_DATA
].value
;
2634 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2635 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2637 /* Check type of data, and width and height against contents of
2643 /* Number of elements of the vector must be >= height. */
2644 if (XVECTOR (data
)->size
< height
)
2647 /* Each string or bool-vector in data must be large enough
2648 for one line of the image. */
2649 for (i
= 0; i
< height
; ++i
)
2651 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2656 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2659 else if (BOOL_VECTOR_P (elt
))
2661 if (XBOOL_VECTOR (elt
)->size
< width
)
2668 else if (STRINGP (data
))
2671 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2674 else if (BOOL_VECTOR_P (data
))
2676 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2687 /* Scan a bitmap file. FP is the stream to read from. Value is
2688 either an enumerator from enum xbm_token, or a character for a
2689 single-character token, or 0 at end of file. If scanning an
2690 identifier, store the lexeme of the identifier in SVAL. If
2691 scanning a number, store its value in *IVAL. */
2694 xbm_scan (s
, end
, sval
, ival
)
2695 unsigned char **s
, *end
;
2703 /* Skip white space. */
2704 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2709 else if (isdigit (c
))
2711 int value
= 0, digit
;
2713 if (c
== '0' && *s
< end
)
2716 if (c
== 'x' || c
== 'X')
2723 else if (c
>= 'a' && c
<= 'f')
2724 digit
= c
- 'a' + 10;
2725 else if (c
>= 'A' && c
<= 'F')
2726 digit
= c
- 'A' + 10;
2729 value
= 16 * value
+ digit
;
2732 else if (isdigit (c
))
2736 && (c
= *(*s
)++, isdigit (c
)))
2737 value
= 8 * value
+ c
- '0';
2744 && (c
= *(*s
)++, isdigit (c
)))
2745 value
= 10 * value
+ c
- '0';
2753 else if (isalpha (c
) || c
== '_')
2757 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2764 else if (c
== '/' && **s
== '*')
2766 /* C-style comment. */
2768 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2782 /* Create a Windows bitmap from X bitmap data. */
2784 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2786 static unsigned char swap_nibble
[16]
2787 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2788 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2789 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2790 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2792 unsigned char *bits
, *p
;
2795 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2796 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2797 bits
= (unsigned char *) alloca (height
* w2
);
2798 bzero (bits
, height
* w2
);
2799 for (i
= 0; i
< height
; i
++)
2802 for (j
= 0; j
< w1
; j
++)
2804 /* Bitswap XBM bytes to match how Windows does things. */
2805 unsigned char c
= *data
++;
2806 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2807 | (swap_nibble
[(c
>>4) & 0xf]));
2810 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2815 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2818 COLORREF foreground
, background
;
2820 HDC hdc
, old_img_dc
, new_img_dc
;
2821 HGDIOBJ old_prev
, new_prev
;
2824 hdc
= get_frame_dc (f
);
2825 old_img_dc
= CreateCompatibleDC (hdc
);
2826 new_img_dc
= CreateCompatibleDC (hdc
);
2827 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2828 release_frame_dc (f
, hdc
);
2829 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2830 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2831 SetTextColor (new_img_dc
, foreground
);
2832 SetBkColor (new_img_dc
, background
);
2834 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2837 SelectObject (old_img_dc
, old_prev
);
2838 SelectObject (new_img_dc
, new_prev
);
2839 DeleteDC (old_img_dc
);
2840 DeleteDC (new_img_dc
);
2841 DeleteObject (img
->pixmap
);
2842 if (new_pixmap
== 0)
2843 fprintf (stderr
, "Failed to convert image to color.\n");
2845 img
->pixmap
= new_pixmap
;
2848 #define XBM_BIT_SHUFFLE(b) (~(b))
2852 #define XBM_BIT_SHUFFLE(b) (b)
2854 #endif /* HAVE_NTGUI */
2858 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2862 RGB_PIXEL_COLOR fg
, bg
;
2863 int non_default_colors
;
2867 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2869 /* If colors were specified, transfer the bitmap to a color one. */
2870 if (non_default_colors
)
2871 convert_mono_to_color_image (f
, img
, fg
, bg
);
2874 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2877 img
->width
, img
->height
,
2879 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2880 #endif /* HAVE_NTGUI */
2885 /* Replacement for XReadBitmapFileData which isn't available under old
2886 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2887 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2888 the image. Return in *DATA the bitmap data allocated with xmalloc.
2889 Value is non-zero if successful. DATA null means just test if
2890 CONTENTS looks like an in-memory XBM file. */
2893 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2894 unsigned char *contents
, *end
;
2895 int *width
, *height
;
2896 unsigned char **data
;
2898 unsigned char *s
= contents
;
2899 char buffer
[BUFSIZ
];
2902 int bytes_per_line
, i
, nbytes
;
2908 LA1 = xbm_scan (&s, end, buffer, &value)
2910 #define expect(TOKEN) \
2911 if (LA1 != (TOKEN)) \
2916 #define expect_ident(IDENT) \
2917 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2922 *width
= *height
= -1;
2925 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2927 /* Parse defines for width, height and hot-spots. */
2931 expect_ident ("define");
2932 expect (XBM_TK_IDENT
);
2934 if (LA1
== XBM_TK_NUMBER
);
2936 char *p
= strrchr (buffer
, '_');
2937 p
= p
? p
+ 1 : buffer
;
2938 if (strcmp (p
, "width") == 0)
2940 else if (strcmp (p
, "height") == 0)
2943 expect (XBM_TK_NUMBER
);
2946 if (*width
< 0 || *height
< 0)
2948 else if (data
== NULL
)
2951 /* Parse bits. Must start with `static'. */
2952 expect_ident ("static");
2953 if (LA1
== XBM_TK_IDENT
)
2955 if (strcmp (buffer
, "unsigned") == 0)
2958 expect_ident ("char");
2960 else if (strcmp (buffer
, "short") == 0)
2964 if (*width
% 16 && *width
% 16 < 9)
2967 else if (strcmp (buffer
, "char") == 0)
2975 expect (XBM_TK_IDENT
);
2981 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2982 nbytes
= bytes_per_line
* *height
;
2983 p
= *data
= (char *) xmalloc (nbytes
);
2987 for (i
= 0; i
< nbytes
; i
+= 2)
2990 expect (XBM_TK_NUMBER
);
2992 *p
++ = XBM_BIT_SHUFFLE (val
);
2993 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2994 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2996 if (LA1
== ',' || LA1
== '}')
3004 for (i
= 0; i
< nbytes
; ++i
)
3007 expect (XBM_TK_NUMBER
);
3009 *p
++ = XBM_BIT_SHUFFLE (val
);
3011 if (LA1
== ',' || LA1
== '}')
3036 /* Load XBM image IMG which will be displayed on frame F from buffer
3037 CONTENTS. END is the end of the buffer. Value is non-zero if
3041 xbm_load_image (f
, img
, contents
, end
)
3044 unsigned char *contents
, *end
;
3047 unsigned char *data
;
3050 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
3053 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3054 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3055 int non_default_colors
= 0;
3058 xassert (img
->width
> 0 && img
->height
> 0);
3060 /* Get foreground and background colors, maybe allocate colors. */
3061 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3064 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3065 non_default_colors
= 1;
3067 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3070 background
= x_alloc_image_color (f
, img
, value
, background
);
3071 img
->background
= background
;
3072 img
->background_valid
= 1;
3073 non_default_colors
= 1;
3076 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3077 foreground
, background
,
3078 non_default_colors
);
3081 if (img
->pixmap
== NO_PIXMAP
)
3083 x_clear_image (f
, img
);
3084 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3090 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3096 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3103 return (STRINGP (data
)
3104 && xbm_read_bitmap_data (SDATA (data
),
3111 /* Fill image IMG which is used on frame F with pixmap data. Value is
3112 non-zero if successful. */
3120 Lisp_Object file_name
;
3122 xassert (xbm_image_p (img
->spec
));
3124 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3125 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3126 if (STRINGP (file_name
))
3129 unsigned char *contents
;
3131 struct gcpro gcpro1
;
3133 file
= x_find_image_file (file_name
);
3135 if (!STRINGP (file
))
3137 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3142 contents
= slurp_file (SDATA (file
), &size
);
3143 if (contents
== NULL
)
3145 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3150 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3155 struct image_keyword fmt
[XBM_LAST
];
3157 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3158 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3159 int non_default_colors
= 0;
3162 int in_memory_file_p
= 0;
3164 /* See if data looks like an in-memory XBM file. */
3165 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3166 in_memory_file_p
= xbm_file_p (data
);
3168 /* Parse the image specification. */
3169 bcopy (xbm_format
, fmt
, sizeof fmt
);
3170 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3173 /* Get specified width, and height. */
3174 if (!in_memory_file_p
)
3176 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3177 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3178 xassert (img
->width
> 0 && img
->height
> 0);
3181 /* Get foreground and background colors, maybe allocate colors. */
3182 if (fmt
[XBM_FOREGROUND
].count
3183 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3185 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3187 non_default_colors
= 1;
3190 if (fmt
[XBM_BACKGROUND
].count
3191 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3193 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3195 non_default_colors
= 1;
3198 if (in_memory_file_p
)
3199 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3208 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3210 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3211 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3213 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3215 bcopy (SDATA (line
), p
, nbytes
);
3217 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3220 else if (STRINGP (data
))
3221 bits
= SDATA (data
);
3223 bits
= XBOOL_VECTOR (data
)->data
;
3225 /* Create the pixmap. */
3227 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3228 foreground
, background
,
3229 non_default_colors
);
3234 image_error ("Unable to create pixmap for XBM image `%s'",
3236 x_clear_image (f
, img
);
3246 /***********************************************************************
3248 ***********************************************************************/
3250 #if defined (HAVE_XPM) || defined (MAC_OS)
3252 static int xpm_image_p
P_ ((Lisp_Object object
));
3253 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3254 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3256 #endif /* HAVE_XPM || MAC_OS */
3260 /* Indicate to xpm.h that we don't have Xlib. */
3262 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3263 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3264 #define XColor xpm_XColor
3265 #define XImage xpm_XImage
3266 #define Display xpm_Display
3267 #define PIXEL_ALREADY_TYPEDEFED
3268 #include "X11/xpm.h"
3273 #undef PIXEL_ALREADY_TYPEDEFED
3275 #include "X11/xpm.h"
3276 #endif /* HAVE_NTGUI */
3277 #endif /* HAVE_XPM */
3279 #if defined (HAVE_XPM) || defined (MAC_OS)
3280 /* The symbol `xpm' identifying XPM-format images. */
3284 /* Indices of image specification fields in xpm_format, below. */
3286 enum xpm_keyword_index
3302 /* Vector of image_keyword structures describing the format
3303 of valid XPM image specifications. */
3305 static struct image_keyword xpm_format
[XPM_LAST
] =
3307 {":type", IMAGE_SYMBOL_VALUE
, 1},
3308 {":file", IMAGE_STRING_VALUE
, 0},
3309 {":data", IMAGE_STRING_VALUE
, 0},
3310 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3311 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3312 {":relief", IMAGE_INTEGER_VALUE
, 0},
3313 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3314 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3315 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3316 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3317 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3320 /* Structure describing the image type XPM. */
3322 static struct image_type xpm_type
=
3331 #ifdef HAVE_X_WINDOWS
3333 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3334 functions for allocating image colors. Our own functions handle
3335 color allocation failures more gracefully than the ones on the XPM
3338 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3339 #define ALLOC_XPM_COLORS
3341 #endif /* HAVE_X_WINDOWS */
3343 #ifdef ALLOC_XPM_COLORS
3345 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3346 static void xpm_free_color_cache
P_ ((void));
3347 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3348 static int xpm_color_bucket
P_ ((char *));
3349 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3352 /* An entry in a hash table used to cache color definitions of named
3353 colors. This cache is necessary to speed up XPM image loading in
3354 case we do color allocations ourselves. Without it, we would need
3355 a call to XParseColor per pixel in the image. */
3357 struct xpm_cached_color
3359 /* Next in collision chain. */
3360 struct xpm_cached_color
*next
;
3362 /* Color definition (RGB and pixel color). */
3369 /* The hash table used for the color cache, and its bucket vector
3372 #define XPM_COLOR_CACHE_BUCKETS 1001
3373 struct xpm_cached_color
**xpm_color_cache
;
3375 /* Initialize the color cache. */
3378 xpm_init_color_cache (f
, attrs
)
3380 XpmAttributes
*attrs
;
3382 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3383 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3384 memset (xpm_color_cache
, 0, nbytes
);
3385 init_color_table ();
3387 if (attrs
->valuemask
& XpmColorSymbols
)
3392 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3393 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3394 attrs
->colorsymbols
[i
].value
, &color
))
3396 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3398 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3403 /* Free the color cache. */
3406 xpm_free_color_cache ()
3408 struct xpm_cached_color
*p
, *next
;
3411 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3412 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3418 xfree (xpm_color_cache
);
3419 xpm_color_cache
= NULL
;
3420 free_color_table ();
3423 /* Return the bucket index for color named COLOR_NAME in the color
3427 xpm_color_bucket (color_name
)
3433 for (s
= color_name
; *s
; ++s
)
3435 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3439 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3440 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3443 static struct xpm_cached_color
*
3444 xpm_cache_color (f
, color_name
, color
, bucket
)
3451 struct xpm_cached_color
*p
;
3454 bucket
= xpm_color_bucket (color_name
);
3456 nbytes
= sizeof *p
+ strlen (color_name
);
3457 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3458 strcpy (p
->name
, color_name
);
3460 p
->next
= xpm_color_cache
[bucket
];
3461 xpm_color_cache
[bucket
] = p
;
3465 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3466 return the cached definition in *COLOR. Otherwise, make a new
3467 entry in the cache and allocate the color. Value is zero if color
3468 allocation failed. */
3471 xpm_lookup_color (f
, color_name
, color
)
3476 struct xpm_cached_color
*p
;
3477 int h
= xpm_color_bucket (color_name
);
3479 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3480 if (strcmp (p
->name
, color_name
) == 0)
3485 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3488 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3490 p
= xpm_cache_color (f
, color_name
, color
, h
);
3492 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3493 with transparency, and it's useful. */
3494 else if (strcmp ("opaque", color_name
) == 0)
3496 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3497 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3498 p
= xpm_cache_color (f
, color_name
, color
, h
);
3505 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3506 CLOSURE is a pointer to the frame on which we allocate the
3507 color. Return in *COLOR the allocated color. Value is non-zero
3511 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3518 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3522 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3523 is a pointer to the frame on which we allocate the color. Value is
3524 non-zero if successful. */
3527 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3537 #endif /* ALLOC_XPM_COLORS */
3542 /* XPM library details. */
3544 DEF_IMGLIB_FN (XpmFreeAttributes
);
3545 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3546 DEF_IMGLIB_FN (XpmReadFileToImage
);
3547 DEF_IMGLIB_FN (XImageFree
);
3550 init_xpm_functions (Lisp_Object libraries
)
3554 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3557 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3558 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3559 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3560 LOAD_IMGLIB_FN (library
, XImageFree
);
3564 #endif /* HAVE_NTGUI */
3567 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3568 for XPM images. Such a list must consist of conses whose car and
3572 xpm_valid_color_symbols_p (color_symbols
)
3573 Lisp_Object color_symbols
;
3575 while (CONSP (color_symbols
))
3577 Lisp_Object sym
= XCAR (color_symbols
);
3579 || !STRINGP (XCAR (sym
))
3580 || !STRINGP (XCDR (sym
)))
3582 color_symbols
= XCDR (color_symbols
);
3585 return NILP (color_symbols
);
3589 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3592 xpm_image_p (object
)
3595 struct image_keyword fmt
[XPM_LAST
];
3596 bcopy (xpm_format
, fmt
, sizeof fmt
);
3597 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3598 /* Either `:file' or `:data' must be present. */
3599 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3600 /* Either no `:color-symbols' or it's a list of conses
3601 whose car and cdr are strings. */
3602 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3603 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3606 #endif /* HAVE_XPM || MAC_OS */
3608 /* Load image IMG which will be displayed on frame F. Value is
3609 non-zero if successful. */
3619 XpmAttributes attrs
;
3620 Lisp_Object specified_file
, color_symbols
;
3623 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3624 #endif /* HAVE_NTGUI */
3626 /* Configure the XPM lib. Use the visual of frame F. Allocate
3627 close colors. Return colors allocated. */
3628 bzero (&attrs
, sizeof attrs
);
3631 attrs
.visual
= FRAME_X_VISUAL (f
);
3632 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3633 attrs
.valuemask
|= XpmVisual
;
3634 attrs
.valuemask
|= XpmColormap
;
3635 #endif /* HAVE_NTGUI */
3637 #ifdef ALLOC_XPM_COLORS
3638 /* Allocate colors with our own functions which handle
3639 failing color allocation more gracefully. */
3640 attrs
.color_closure
= f
;
3641 attrs
.alloc_color
= xpm_alloc_color
;
3642 attrs
.free_colors
= xpm_free_colors
;
3643 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3644 #else /* not ALLOC_XPM_COLORS */
3645 /* Let the XPM lib allocate colors. */
3646 attrs
.valuemask
|= XpmReturnAllocPixels
;
3647 #ifdef XpmAllocCloseColors
3648 attrs
.alloc_close_colors
= 1;
3649 attrs
.valuemask
|= XpmAllocCloseColors
;
3650 #else /* not XpmAllocCloseColors */
3651 attrs
.closeness
= 600;
3652 attrs
.valuemask
|= XpmCloseness
;
3653 #endif /* not XpmAllocCloseColors */
3654 #endif /* ALLOC_XPM_COLORS */
3656 /* If image specification contains symbolic color definitions, add
3657 these to `attrs'. */
3658 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3659 if (CONSP (color_symbols
))
3662 XpmColorSymbol
*xpm_syms
;
3665 attrs
.valuemask
|= XpmColorSymbols
;
3667 /* Count number of symbols. */
3668 attrs
.numsymbols
= 0;
3669 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3672 /* Allocate an XpmColorSymbol array. */
3673 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3674 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3675 bzero (xpm_syms
, size
);
3676 attrs
.colorsymbols
= xpm_syms
;
3678 /* Fill the color symbol array. */
3679 for (tail
= color_symbols
, i
= 0;
3681 ++i
, tail
= XCDR (tail
))
3683 Lisp_Object name
= XCAR (XCAR (tail
));
3684 Lisp_Object color
= XCDR (XCAR (tail
));
3685 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3686 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3687 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3688 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3692 /* Create a pixmap for the image, either from a file, or from a
3693 string buffer containing data in the same format as an XPM file. */
3694 #ifdef ALLOC_XPM_COLORS
3695 xpm_init_color_cache (f
, &attrs
);
3698 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3702 HDC frame_dc
= get_frame_dc (f
);
3703 hdc
= CreateCompatibleDC (frame_dc
);
3704 release_frame_dc (f
, frame_dc
);
3706 #endif /* HAVE_NTGUI */
3708 if (STRINGP (specified_file
))
3710 Lisp_Object file
= x_find_image_file (specified_file
);
3711 if (!STRINGP (file
))
3713 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3718 /* XpmReadFileToPixmap is not available in the Windows port of
3719 libxpm. But XpmReadFileToImage almost does what we want. */
3720 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3721 &xpm_image
, &xpm_mask
,
3724 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3725 SDATA (file
), &img
->pixmap
, &img
->mask
,
3727 #endif /* HAVE_NTGUI */
3731 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3733 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3734 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3735 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3736 &xpm_image
, &xpm_mask
,
3739 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3741 &img
->pixmap
, &img
->mask
,
3743 #endif /* HAVE_NTGUI */
3746 if (rc
== XpmSuccess
)
3748 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3749 img
->colors
= colors_in_color_table (&img
->ncolors
);
3750 #else /* not ALLOC_XPM_COLORS */
3754 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3755 plus some duplicate attributes. */
3756 if (xpm_image
&& xpm_image
->bitmap
)
3758 img
->pixmap
= xpm_image
->bitmap
;
3759 /* XImageFree in libXpm frees XImage struct without destroying
3760 the bitmap, which is what we want. */
3761 fn_XImageFree (xpm_image
);
3763 if (xpm_mask
&& xpm_mask
->bitmap
)
3765 /* The mask appears to be inverted compared with what we expect.
3766 TODO: invert our expectations. See other places where we
3767 have to invert bits because our idea of masks is backwards. */
3769 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3771 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3772 SelectObject (hdc
, old_obj
);
3774 img
->mask
= xpm_mask
->bitmap
;
3775 fn_XImageFree (xpm_mask
);
3780 #endif /* HAVE_NTGUI */
3782 /* Remember allocated colors. */
3783 img
->ncolors
= attrs
.nalloc_pixels
;
3784 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3785 * sizeof *img
->colors
);
3786 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3788 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3789 #ifdef DEBUG_X_COLORS
3790 register_color (img
->colors
[i
]);
3793 #endif /* not ALLOC_XPM_COLORS */
3795 img
->width
= attrs
.width
;
3796 img
->height
= attrs
.height
;
3797 xassert (img
->width
> 0 && img
->height
> 0);
3799 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3801 fn_XpmFreeAttributes (&attrs
);
3803 XpmFreeAttributes (&attrs
);
3804 #endif /* HAVE_NTGUI */
3810 #endif /* HAVE_NTGUI */
3815 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3818 case XpmFileInvalid
:
3819 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3823 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3826 case XpmColorFailed
:
3827 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3831 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3836 #ifdef ALLOC_XPM_COLORS
3837 xpm_free_color_cache ();
3839 return rc
== XpmSuccess
;
3842 #endif /* HAVE_XPM */
3846 /* XPM support functions for Mac OS where libxpm is not available.
3847 Only XPM version 3 (without any extensions) is supported. */
3849 static int xpm_scan
P_ ((unsigned char **, unsigned char *,
3850 unsigned char **, int *));
3851 static Lisp_Object xpm_make_color_table_v
3852 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3853 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3854 static void xpm_put_color_table_v
P_ ((Lisp_Object
, unsigned char *,
3856 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3857 unsigned char *, int));
3858 static Lisp_Object xpm_make_color_table_h
3859 P_ ((void (**) (Lisp_Object
, unsigned char *, int, Lisp_Object
),
3860 Lisp_Object (**) (Lisp_Object
, unsigned char *, int)));
3861 static void xpm_put_color_table_h
P_ ((Lisp_Object
, unsigned char *,
3863 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3864 unsigned char *, int));
3865 static int xpm_str_to_color_key
P_ ((char *));
3866 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3867 unsigned char *, unsigned char *));
3869 /* Tokens returned from xpm_scan. */
3878 /* Scan an XPM data and return a character (< 256) or a token defined
3879 by enum xpm_token above. *S and END are the start (inclusive) and
3880 the end (exclusive) addresses of the data, respectively. Advance
3881 *S while scanning. If token is either XPM_TK_IDENT or
3882 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3883 length of the corresponding token, respectively. */
3886 xpm_scan (s
, end
, beg
, len
)
3887 unsigned char **s
, *end
, **beg
;
3894 /* Skip white-space. */
3895 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3898 /* gnus-pointer.xpm uses '-' in its identifier.
3899 sb-dir-plus.xpm uses '+' in its identifier. */
3900 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
3904 (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
3907 return XPM_TK_IDENT
;
3912 while (*s
< end
&& **s
!= '"')
3917 return XPM_TK_STRING
;
3921 if (*s
< end
&& **s
== '*')
3923 /* C-style comment. */
3927 while (*s
< end
&& *(*s
)++ != '*')
3930 while (*s
< end
&& **s
!= '/');
3944 /* Functions for color table lookup in XPM data. A Key is a string
3945 specifying the color of each pixel in XPM data. A value is either
3946 an integer that specifies a pixel color, Qt that specifies
3947 transparency, or Qnil for the unspecified color. If the length of
3948 the key string is one, a vector is used as a table. Otherwise, a
3949 hash table is used. */
3952 xpm_make_color_table_v (put_func
, get_func
)
3953 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3954 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3956 *put_func
= xpm_put_color_table_v
;
3957 *get_func
= xpm_get_color_table_v
;
3958 return Fmake_vector (make_number (256), Qnil
);
3962 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
3963 Lisp_Object color_table
;
3964 unsigned char *chars_start
;
3968 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
3972 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
3973 Lisp_Object color_table
;
3974 unsigned char *chars_start
;
3977 return XVECTOR (color_table
)->contents
[*chars_start
];
3981 xpm_make_color_table_h (put_func
, get_func
)
3982 void (**put_func
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
3983 Lisp_Object (**get_func
) (Lisp_Object
, unsigned char *, int);
3985 *put_func
= xpm_put_color_table_h
;
3986 *get_func
= xpm_get_color_table_h
;
3987 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
3988 make_float (DEFAULT_REHASH_SIZE
),
3989 make_float (DEFAULT_REHASH_THRESHOLD
),
3994 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
3995 Lisp_Object color_table
;
3996 unsigned char *chars_start
;
4000 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4002 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4004 hash_lookup (table
, chars
, &hash_code
);
4005 hash_put (table
, chars
, color
, hash_code
);
4009 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4010 Lisp_Object color_table
;
4011 unsigned char *chars_start
;
4014 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4015 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4018 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4021 enum xpm_color_key
{
4029 static char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4032 xpm_str_to_color_key (s
)
4038 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4040 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4046 xpm_load_image (f
, img
, contents
, end
)
4049 unsigned char *contents
, *end
;
4051 unsigned char *s
= contents
, *beg
, *str
;
4052 unsigned char buffer
[BUFSIZ
];
4053 int width
, height
, x
, y
;
4054 int num_colors
, chars_per_pixel
;
4056 void (*put_color_table
) (Lisp_Object
, unsigned char *, int, Lisp_Object
);
4057 Lisp_Object (*get_color_table
) (Lisp_Object
, unsigned char *, int);
4058 Lisp_Object frame
, color_symbols
, color_table
;
4059 int best_key
, have_mask
= 0;
4060 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4063 LA1 = xpm_scan (&s, end, &beg, &len)
4065 #define expect(TOKEN) \
4066 if (LA1 != (TOKEN)) \
4071 #define expect_ident(IDENT) \
4072 if (LA1 == XPM_TK_IDENT \
4073 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4078 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4082 expect_ident ("static");
4083 expect_ident ("char");
4085 expect (XPM_TK_IDENT
);
4090 expect (XPM_TK_STRING
);
4093 memcpy (buffer
, beg
, len
);
4095 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4096 &num_colors
, &chars_per_pixel
) != 4
4097 || width
<= 0 || height
<= 0
4098 || num_colors
<= 0 || chars_per_pixel
<= 0)
4102 XSETFRAME (frame
, f
);
4103 if (!NILP (Fxw_display_color_p (frame
)))
4104 best_key
= XPM_COLOR_KEY_C
;
4105 else if (!NILP (Fx_display_grayscale_p (frame
)))
4106 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4107 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4109 best_key
= XPM_COLOR_KEY_M
;
4111 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4112 if (chars_per_pixel
== 1)
4113 color_table
= xpm_make_color_table_v (&put_color_table
,
4116 color_table
= xpm_make_color_table_h (&put_color_table
,
4119 while (num_colors
-- > 0)
4121 unsigned char *color
, *max_color
;
4122 int key
, next_key
, max_key
= 0;
4123 Lisp_Object symbol_color
= Qnil
, color_val
;
4126 expect (XPM_TK_STRING
);
4127 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4129 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4130 buffer
[len
- chars_per_pixel
] = '\0';
4132 str
= strtok (buffer
, " \t");
4135 key
= xpm_str_to_color_key (str
);
4140 color
= strtok (NULL
, " \t");
4144 while (str
= strtok (NULL
, " \t"))
4146 next_key
= xpm_str_to_color_key (str
);
4149 color
[strlen (color
)] = ' ';
4152 if (key
== XPM_COLOR_KEY_S
)
4154 if (NILP (symbol_color
))
4155 symbol_color
= build_string (color
);
4157 else if (max_key
< key
&& key
<= best_key
)
4167 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4169 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4171 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4172 if (xstricmp (SDATA (XCDR (specified_color
)), "None") == 0)
4174 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4176 color_val
= make_number (cdef
.pixel
);
4178 if (NILP (color_val
) && max_key
> 0)
4179 if (xstricmp (max_color
, "None") == 0)
4181 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4182 color_val
= make_number (cdef
.pixel
);
4183 if (!NILP (color_val
))
4184 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4189 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4190 &ximg
, &img
->pixmap
)
4191 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4192 &mask_img
, &img
->mask
))
4194 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4198 for (y
= 0; y
< height
; y
++)
4200 expect (XPM_TK_STRING
);
4202 if (len
< width
* chars_per_pixel
)
4204 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4206 Lisp_Object color_val
=
4207 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4209 XPutPixel (ximg
, x
, y
,
4210 (INTEGERP (color_val
) ? XINT (color_val
)
4211 : FRAME_FOREGROUND_PIXEL (f
)));
4212 XPutPixel (mask_img
, x
, y
,
4213 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW (f
)
4214 : (have_mask
= 1, PIX_MASK_RETAIN (f
))));
4221 img
->height
= height
;
4223 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4224 x_destroy_x_image (ximg
);
4227 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4228 x_destroy_x_image (mask_img
);
4232 x_destroy_x_image (mask_img
);
4233 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4234 img
->mask
= NO_PIXMAP
;
4240 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4242 x_destroy_x_image (ximg
);
4243 x_destroy_x_image (mask_img
);
4244 x_clear_image (f
, img
);
4258 Lisp_Object file_name
;
4260 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4261 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4262 if (STRINGP (file_name
))
4265 unsigned char *contents
;
4267 struct gcpro gcpro1
;
4269 file
= x_find_image_file (file_name
);
4271 if (!STRINGP (file
))
4273 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4278 contents
= slurp_file (SDATA (file
), &size
);
4279 if (contents
== NULL
)
4281 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4286 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4294 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4295 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4296 SDATA (data
) + SBYTES (data
));
4306 /***********************************************************************
4308 ***********************************************************************/
4310 #ifdef COLOR_TABLE_SUPPORT
4312 /* An entry in the color table mapping an RGB color to a pixel color. */
4317 unsigned long pixel
;
4319 /* Next in color table collision list. */
4320 struct ct_color
*next
;
4323 /* The bucket vector size to use. Must be prime. */
4327 /* Value is a hash of the RGB color given by R, G, and B. */
4329 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4331 /* The color hash table. */
4333 struct ct_color
**ct_table
;
4335 /* Number of entries in the color table. */
4337 int ct_colors_allocated
;
4339 /* Initialize the color table. */
4344 int size
= CT_SIZE
* sizeof (*ct_table
);
4345 ct_table
= (struct ct_color
**) xmalloc (size
);
4346 bzero (ct_table
, size
);
4347 ct_colors_allocated
= 0;
4351 /* Free memory associated with the color table. */
4357 struct ct_color
*p
, *next
;
4359 for (i
= 0; i
< CT_SIZE
; ++i
)
4360 for (p
= ct_table
[i
]; p
; p
= next
)
4371 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4372 entry for that color already is in the color table, return the
4373 pixel color of that entry. Otherwise, allocate a new color for R,
4374 G, B, and make an entry in the color table. */
4376 static unsigned long
4377 lookup_rgb_color (f
, r
, g
, b
)
4381 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4382 int i
= hash
% CT_SIZE
;
4384 Display_Info
*dpyinfo
;
4386 /* Handle TrueColor visuals specially, which improves performance by
4387 two orders of magnitude. Freeing colors on TrueColor visuals is
4388 a nop, and pixel colors specify RGB values directly. See also
4389 the Xlib spec, chapter 3.1. */
4390 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4391 if (dpyinfo
->red_bits
> 0)
4393 unsigned long pr
, pg
, pb
;
4395 /* Apply gamma-correction like normal color allocation does. */
4399 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4400 gamma_correct (f
, &color
);
4401 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4404 /* Scale down RGB values to the visual's bits per RGB, and shift
4405 them to the right position in the pixel color. Note that the
4406 original RGB values are 16-bit values, as usual in X. */
4407 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4408 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4409 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4411 /* Assemble the pixel color. */
4412 return pr
| pg
| pb
;
4415 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4416 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4422 #ifdef HAVE_X_WINDOWS
4431 cmap
= FRAME_X_COLORMAP (f
);
4432 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4435 ++ct_colors_allocated
;
4436 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4440 p
->pixel
= color
.pixel
;
4441 p
->next
= ct_table
[i
];
4445 return FRAME_FOREGROUND_PIXEL (f
);
4450 color
= PALETTERGB (r
, g
, b
);
4452 color
= RGB_TO_ULONG (r
, g
, b
);
4453 #endif /* HAVE_NTGUI */
4454 ++ct_colors_allocated
;
4455 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4460 p
->next
= ct_table
[i
];
4462 #endif /* HAVE_X_WINDOWS */
4470 /* Look up pixel color PIXEL which is used on frame F in the color
4471 table. If not already present, allocate it. Value is PIXEL. */
4473 static unsigned long
4474 lookup_pixel_color (f
, pixel
)
4476 unsigned long pixel
;
4478 int i
= pixel
% CT_SIZE
;
4481 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4482 if (p
->pixel
== pixel
)
4491 #ifdef HAVE_X_WINDOWS
4492 cmap
= FRAME_X_COLORMAP (f
);
4493 color
.pixel
= pixel
;
4494 x_query_color (f
, &color
);
4495 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4498 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4499 color
.pixel
= pixel
;
4500 XQueryColor (NULL
, cmap
, &color
);
4501 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4503 #endif /* HAVE_X_WINDOWS */
4507 ++ct_colors_allocated
;
4509 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4514 p
->next
= ct_table
[i
];
4518 return FRAME_FOREGROUND_PIXEL (f
);
4524 /* Value is a vector of all pixel colors contained in the color table,
4525 allocated via xmalloc. Set *N to the number of colors. */
4527 static unsigned long *
4528 colors_in_color_table (n
)
4533 unsigned long *colors
;
4535 if (ct_colors_allocated
== 0)
4542 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4544 *n
= ct_colors_allocated
;
4546 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4547 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4548 colors
[j
++] = p
->pixel
;
4554 #else /* COLOR_TABLE_SUPPORT */
4556 static unsigned long
4557 lookup_rgb_color (f
, r
, g
, b
)
4561 unsigned long pixel
;
4564 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4565 gamma_correct (f
, &pixel
);
4569 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4570 #endif /* HAVE_NTGUI */
4579 #endif /* COLOR_TABLE_SUPPORT */
4582 /***********************************************************************
4584 ***********************************************************************/
4586 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4587 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4588 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4591 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4592 #endif /* HAVE_NTGUI */
4594 /* Non-zero means draw a cross on images having `:conversion
4597 int cross_disabled_images
;
4599 /* Edge detection matrices for different edge-detection
4602 static int emboss_matrix
[9] = {
4604 2, -1, 0, /* y - 1 */
4606 0, 1, -2 /* y + 1 */
4609 static int laplace_matrix
[9] = {
4611 1, 0, 0, /* y - 1 */
4613 0, 0, -1 /* y + 1 */
4616 /* Value is the intensity of the color whose red/green/blue values
4619 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4622 /* On frame F, return an array of XColor structures describing image
4623 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4624 non-zero means also fill the red/green/blue members of the XColor
4625 structures. Value is a pointer to the array of XColors structures,
4626 allocated with xmalloc; it must be freed by the caller. */
4629 x_to_xcolors (f
, img
, rgb_p
)
4636 XImagePtr_or_DC ximg
;
4640 #endif /* HAVE_NTGUI */
4642 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4645 /* Get the X image IMG->pixmap. */
4646 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4647 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4649 /* Load the image into a memory device context. */
4650 hdc
= get_frame_dc (f
);
4651 ximg
= CreateCompatibleDC (hdc
);
4652 release_frame_dc (f
, hdc
);
4653 prev
= SelectObject (ximg
, img
->pixmap
);
4654 #endif /* HAVE_NTGUI */
4656 /* Fill the `pixel' members of the XColor array. I wished there
4657 were an easy and portable way to circumvent XGetPixel. */
4659 for (y
= 0; y
< img
->height
; ++y
)
4663 #ifdef HAVE_X_WINDOWS
4664 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4665 p
->pixel
= XGetPixel (ximg
, x
, y
);
4667 x_query_colors (f
, row
, img
->width
);
4671 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4673 /* W32_TODO: palette support needed here? */
4674 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4678 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4679 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4680 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4683 p
->red
= 256 * GetRValue (p
->pixel
);
4684 p
->green
= 256 * GetGValue (p
->pixel
);
4685 p
->blue
= 256 * GetBValue (p
->pixel
);
4686 #endif /* HAVE_NTGUI */
4689 #endif /* HAVE_X_WINDOWS */
4692 Destroy_Image (ximg
, prev
);
4699 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4700 created with CreateDIBSection, with the pointer to the bit values
4701 stored in ximg->data. */
4703 static void XPutPixel (ximg
, x
, y
, color
)
4708 int width
= ximg
->info
.bmiHeader
.biWidth
;
4709 int height
= ximg
->info
.bmiHeader
.biHeight
;
4710 unsigned char * pixel
;
4712 /* True color images. */
4713 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4715 int rowbytes
= width
* 3;
4716 /* Ensure scanlines are aligned on 4 byte boundaries. */
4718 rowbytes
+= 4 - (rowbytes
% 4);
4720 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4721 /* Windows bitmaps are in BGR order. */
4722 *pixel
= GetBValue (color
);
4723 *(pixel
+ 1) = GetGValue (color
);
4724 *(pixel
+ 2) = GetRValue (color
);
4726 /* Monochrome images. */
4727 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4729 int rowbytes
= width
/ 8;
4730 /* Ensure scanlines are aligned on 4 byte boundaries. */
4732 rowbytes
+= 4 - (rowbytes
% 4);
4733 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4734 /* Filter out palette info. */
4735 if (color
& 0x00ffffff)
4736 *pixel
= *pixel
| (1 << x
% 8);
4738 *pixel
= *pixel
& ~(1 << x
% 8);
4741 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4744 #endif /* HAVE_NTGUI */
4746 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4747 RGB members are set. F is the frame on which this all happens.
4748 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4751 x_from_xcolors (f
, img
, colors
)
4761 init_color_table ();
4763 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4766 for (y
= 0; y
< img
->height
; ++y
)
4767 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4769 unsigned long pixel
;
4770 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4771 XPutPixel (oimg
, x
, y
, pixel
);
4775 x_clear_image_1 (f
, img
, 1, 0, 1);
4777 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4778 x_destroy_x_image (oimg
);
4779 img
->pixmap
= pixmap
;
4780 #ifdef COLOR_TABLE_SUPPORT
4781 img
->colors
= colors_in_color_table (&img
->ncolors
);
4782 free_color_table ();
4783 #endif /* COLOR_TABLE_SUPPORT */
4787 /* On frame F, perform edge-detection on image IMG.
4789 MATRIX is a nine-element array specifying the transformation
4790 matrix. See emboss_matrix for an example.
4792 COLOR_ADJUST is a color adjustment added to each pixel of the
4796 x_detect_edges (f
, img
, matrix
, color_adjust
)
4799 int matrix
[9], color_adjust
;
4801 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4805 for (i
= sum
= 0; i
< 9; ++i
)
4806 sum
+= abs (matrix
[i
]);
4808 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4810 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4812 for (y
= 0; y
< img
->height
; ++y
)
4814 p
= COLOR (new, 0, y
);
4815 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4816 p
= COLOR (new, img
->width
- 1, y
);
4817 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4820 for (x
= 1; x
< img
->width
- 1; ++x
)
4822 p
= COLOR (new, x
, 0);
4823 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4824 p
= COLOR (new, x
, img
->height
- 1);
4825 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4828 for (y
= 1; y
< img
->height
- 1; ++y
)
4830 p
= COLOR (new, 1, y
);
4832 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4834 int r
, g
, b
, y1
, x1
;
4837 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4838 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4841 XColor
*t
= COLOR (colors
, x1
, y1
);
4842 r
+= matrix
[i
] * t
->red
;
4843 g
+= matrix
[i
] * t
->green
;
4844 b
+= matrix
[i
] * t
->blue
;
4847 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4848 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4849 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4850 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4855 x_from_xcolors (f
, img
, new);
4861 /* Perform the pre-defined `emboss' edge-detection on image IMG
4869 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4873 /* Transform image IMG which is used on frame F with a Laplace
4874 edge-detection algorithm. The result is an image that can be used
4875 to draw disabled buttons, for example. */
4882 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4886 /* Perform edge-detection on image IMG on frame F, with specified
4887 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4889 MATRIX must be either
4891 - a list of at least 9 numbers in row-major form
4892 - a vector of at least 9 numbers
4894 COLOR_ADJUST nil means use a default; otherwise it must be a
4898 x_edge_detection (f
, img
, matrix
, color_adjust
)
4901 Lisp_Object matrix
, color_adjust
;
4909 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4910 ++i
, matrix
= XCDR (matrix
))
4911 trans
[i
] = XFLOATINT (XCAR (matrix
));
4913 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4915 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4916 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4919 if (NILP (color_adjust
))
4920 color_adjust
= make_number (0xffff / 2);
4922 if (i
== 9 && NUMBERP (color_adjust
))
4923 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4927 /* Transform image IMG on frame F so that it looks disabled. */
4930 x_disable_image (f
, img
)
4934 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4936 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4938 int n_planes
= dpyinfo
->n_planes
;
4939 #endif /* HAVE_NTGUI */
4943 /* Color (or grayscale). Convert to gray, and equalize. Just
4944 drawing such images with a stipple can look very odd, so
4945 we're using this method instead. */
4946 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4948 const int h
= 15000;
4949 const int l
= 30000;
4951 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4955 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4956 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4957 p
->red
= p
->green
= p
->blue
= i2
;
4960 x_from_xcolors (f
, img
, colors
);
4963 /* Draw a cross over the disabled image, if we must or if we
4965 if (n_planes
< 2 || cross_disabled_images
)
4968 Display
*dpy
= FRAME_X_DISPLAY (f
);
4972 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4973 #define MaskForeground(f) PIX_MASK_DRAW (f)
4975 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4976 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4979 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4980 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4981 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4982 img
->width
- 1, img
->height
- 1);
4983 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4989 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4990 XSetForeground (dpy
, gc
, MaskForeground (f
));
4991 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4992 img
->width
- 1, img
->height
- 1);
4993 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5001 hdc
= get_frame_dc (f
);
5002 bmpdc
= CreateCompatibleDC (hdc
);
5003 release_frame_dc (f
, hdc
);
5005 prev
= SelectObject (bmpdc
, img
->pixmap
);
5007 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5008 MoveToEx (bmpdc
, 0, 0, NULL
);
5009 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5010 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5011 LineTo (bmpdc
, img
->width
- 1, 0);
5015 SelectObject (bmpdc
, img
->mask
);
5016 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5017 MoveToEx (bmpdc
, 0, 0, NULL
);
5018 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5019 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5020 LineTo (bmpdc
, img
->width
- 1, 0);
5022 SelectObject (bmpdc
, prev
);
5024 #endif /* HAVE_NTGUI */
5029 /* Build a mask for image IMG which is used on frame F. FILE is the
5030 name of an image file, for error messages. HOW determines how to
5031 determine the background color of IMG. If it is a list '(R G B)',
5032 with R, G, and B being integers >= 0, take that as the color of the
5033 background. Otherwise, determine the background color of IMG
5034 heuristically. Value is non-zero if successful. */
5037 x_build_heuristic_mask (f
, img
, how
)
5042 XImagePtr_or_DC ximg
;
5050 #endif /* HAVE_NTGUI */
5051 int x
, y
, rc
, use_img_background
;
5052 unsigned long bg
= 0;
5056 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5057 img
->mask
= NO_PIXMAP
;
5058 img
->background_transparent_valid
= 0;
5062 /* Create an image and pixmap serving as mask. */
5063 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5064 &mask_img
, &img
->mask
);
5068 /* Get the X image of IMG->pixmap. */
5069 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5070 img
->width
, img
->height
,
5073 /* Create the bit array serving as mask. */
5074 row_width
= (img
->width
+ 7) / 8;
5075 mask_img
= xmalloc (row_width
* img
->height
);
5076 bzero (mask_img
, row_width
* img
->height
);
5078 /* Create a memory device context for IMG->pixmap. */
5079 frame_dc
= get_frame_dc (f
);
5080 ximg
= CreateCompatibleDC (frame_dc
);
5081 release_frame_dc (f
, frame_dc
);
5082 prev
= SelectObject (ximg
, img
->pixmap
);
5083 #endif /* HAVE_NTGUI */
5085 /* Determine the background color of ximg. If HOW is `(R G B)'
5086 take that as color. Otherwise, use the image's background color. */
5087 use_img_background
= 1;
5093 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5095 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5099 if (i
== 3 && NILP (how
))
5101 char color_name
[30];
5102 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5105 0x00ffffff & /* Filter out palette info. */
5106 #endif /* HAVE_NTGUI */
5107 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5108 use_img_background
= 0;
5112 if (use_img_background
)
5113 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
5115 /* Set all bits in mask_img to 1 whose color in ximg is different
5116 from the background color bg. */
5118 for (y
= 0; y
< img
->height
; ++y
)
5119 for (x
= 0; x
< img
->width
; ++x
)
5120 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5121 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
5123 /* Fill in the background_transparent field while we have the mask handy. */
5124 image_background_transparent (img
, f
, mask_img
);
5126 /* Put mask_img into img->mask. */
5127 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5128 x_destroy_x_image (mask_img
);
5131 for (y
= 0; y
< img
->height
; ++y
)
5132 for (x
= 0; x
< img
->width
; ++x
)
5134 COLORREF p
= GetPixel (ximg
, x
, y
);
5136 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5139 /* Create the mask image. */
5140 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5142 /* Fill in the background_transparent field while we have the mask handy. */
5143 SelectObject (ximg
, img
->mask
);
5144 image_background_transparent (img
, f
, ximg
);
5146 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5148 #endif /* HAVE_NTGUI */
5150 Destroy_Image (ximg
, prev
);
5156 /***********************************************************************
5157 PBM (mono, gray, color)
5158 ***********************************************************************/
5160 static int pbm_image_p
P_ ((Lisp_Object object
));
5161 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5162 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5164 /* The symbol `pbm' identifying images of this type. */
5168 /* Indices of image specification fields in gs_format, below. */
5170 enum pbm_keyword_index
5186 /* Vector of image_keyword structures describing the format
5187 of valid user-defined image specifications. */
5189 static struct image_keyword pbm_format
[PBM_LAST
] =
5191 {":type", IMAGE_SYMBOL_VALUE
, 1},
5192 {":file", IMAGE_STRING_VALUE
, 0},
5193 {":data", IMAGE_STRING_VALUE
, 0},
5194 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5195 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5196 {":relief", IMAGE_INTEGER_VALUE
, 0},
5197 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5198 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5199 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5200 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5201 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5204 /* Structure describing the image type `pbm'. */
5206 static struct image_type pbm_type
=
5216 /* Return non-zero if OBJECT is a valid PBM image specification. */
5219 pbm_image_p (object
)
5222 struct image_keyword fmt
[PBM_LAST
];
5224 bcopy (pbm_format
, fmt
, sizeof fmt
);
5226 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5229 /* Must specify either :data or :file. */
5230 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5234 /* Scan a decimal number from *S and return it. Advance *S while
5235 reading the number. END is the end of the string. Value is -1 at
5239 pbm_scan_number (s
, end
)
5240 unsigned char **s
, *end
;
5242 int c
= 0, val
= -1;
5246 /* Skip white-space. */
5247 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5252 /* Skip comment to end of line. */
5253 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5256 else if (isdigit (c
))
5258 /* Read decimal number. */
5260 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5261 val
= 10 * val
+ c
- '0';
5273 #if 0 /* Unused. ++kfs */
5275 /* Read FILE into memory. Value is a pointer to a buffer allocated
5276 with xmalloc holding FILE's contents. Value is null if an error
5277 occurred. *SIZE is set to the size of the file. */
5280 pbm_read_file (file
, size
)
5288 if (stat (SDATA (file
), &st
) == 0
5289 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5290 && (buf
= (char *) xmalloc (st
.st_size
),
5291 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5310 #endif /* HAVE_NTGUI */
5312 /* Load PBM image IMG for use on frame F. */
5320 int width
, height
, max_color_idx
= 0;
5322 Lisp_Object file
, specified_file
;
5323 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5324 struct gcpro gcpro1
;
5325 unsigned char *contents
= NULL
;
5326 unsigned char *end
, *p
;
5329 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5333 if (STRINGP (specified_file
))
5335 file
= x_find_image_file (specified_file
);
5336 if (!STRINGP (file
))
5338 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5343 contents
= slurp_file (SDATA (file
), &size
);
5344 if (contents
== NULL
)
5346 image_error ("Error reading `%s'", file
, Qnil
);
5352 end
= contents
+ size
;
5357 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5359 end
= p
+ SBYTES (data
);
5362 /* Check magic number. */
5363 if (end
- p
< 2 || *p
++ != 'P')
5365 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5375 raw_p
= 0, type
= PBM_MONO
;
5379 raw_p
= 0, type
= PBM_GRAY
;
5383 raw_p
= 0, type
= PBM_COLOR
;
5387 raw_p
= 1, type
= PBM_MONO
;
5391 raw_p
= 1, type
= PBM_GRAY
;
5395 raw_p
= 1, type
= PBM_COLOR
;
5399 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5403 /* Read width, height, maximum color-component. Characters
5404 starting with `#' up to the end of a line are ignored. */
5405 width
= pbm_scan_number (&p
, end
);
5406 height
= pbm_scan_number (&p
, end
);
5408 if (type
!= PBM_MONO
)
5410 max_color_idx
= pbm_scan_number (&p
, end
);
5411 if (raw_p
&& max_color_idx
> 255)
5412 max_color_idx
= 255;
5417 || (type
!= PBM_MONO
&& max_color_idx
< 0))
5420 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5421 &ximg
, &img
->pixmap
))
5424 /* Initialize the color hash table. */
5425 init_color_table ();
5427 if (type
== PBM_MONO
)
5430 struct image_keyword fmt
[PBM_LAST
];
5431 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5432 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5434 /* Parse the image specification. */
5435 bcopy (pbm_format
, fmt
, sizeof fmt
);
5436 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5438 /* Get foreground and background colors, maybe allocate colors. */
5439 if (fmt
[PBM_FOREGROUND
].count
5440 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5441 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5442 if (fmt
[PBM_BACKGROUND
].count
5443 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5445 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5446 img
->background
= bg
;
5447 img
->background_valid
= 1;
5450 for (y
= 0; y
< height
; ++y
)
5451 for (x
= 0; x
< width
; ++x
)
5461 g
= pbm_scan_number (&p
, end
);
5463 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5468 for (y
= 0; y
< height
; ++y
)
5469 for (x
= 0; x
< width
; ++x
)
5473 if (type
== PBM_GRAY
)
5474 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
5483 r
= pbm_scan_number (&p
, end
);
5484 g
= pbm_scan_number (&p
, end
);
5485 b
= pbm_scan_number (&p
, end
);
5488 if (r
< 0 || g
< 0 || b
< 0)
5490 x_destroy_x_image (ximg
);
5491 image_error ("Invalid pixel value in image `%s'",
5496 /* RGB values are now in the range 0..max_color_idx.
5497 Scale this to the range 0..0xffff supported by X. */
5498 r
= (double) r
* 65535 / max_color_idx
;
5499 g
= (double) g
* 65535 / max_color_idx
;
5500 b
= (double) b
* 65535 / max_color_idx
;
5501 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5505 #ifdef COLOR_TABLE_SUPPORT
5506 /* Store in IMG->colors the colors allocated for the image, and
5507 free the color table. */
5508 img
->colors
= colors_in_color_table (&img
->ncolors
);
5509 free_color_table ();
5510 #endif /* COLOR_TABLE_SUPPORT */
5513 img
->height
= height
;
5515 /* Maybe fill in the background field while we have ximg handy. */
5517 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5518 IMAGE_BACKGROUND (img
, f
, ximg
);
5520 /* Put the image into a pixmap. */
5521 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5522 x_destroy_x_image (ximg
);
5524 /* X and W32 versions did it here, MAC version above. ++kfs
5526 img->height = height; */
5534 /***********************************************************************
5536 ***********************************************************************/
5538 #if defined (HAVE_PNG) || defined (MAC_OS)
5540 /* Function prototypes. */
5542 static int png_image_p
P_ ((Lisp_Object object
));
5543 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5545 /* The symbol `png' identifying images of this type. */
5549 /* Indices of image specification fields in png_format, below. */
5551 enum png_keyword_index
5566 /* Vector of image_keyword structures describing the format
5567 of valid user-defined image specifications. */
5569 static struct image_keyword png_format
[PNG_LAST
] =
5571 {":type", IMAGE_SYMBOL_VALUE
, 1},
5572 {":data", IMAGE_STRING_VALUE
, 0},
5573 {":file", IMAGE_STRING_VALUE
, 0},
5574 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5575 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5576 {":relief", IMAGE_INTEGER_VALUE
, 0},
5577 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5578 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5579 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5580 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5583 /* Structure describing the image type `png'. */
5585 static struct image_type png_type
=
5594 /* Return non-zero if OBJECT is a valid PNG image specification. */
5597 png_image_p (object
)
5600 struct image_keyword fmt
[PNG_LAST
];
5601 bcopy (png_format
, fmt
, sizeof fmt
);
5603 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5606 /* Must specify either the :data or :file keyword. */
5607 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5610 #endif /* HAVE_PNG || MAC_OS */
5615 #if defined HAVE_LIBPNG_PNG_H
5616 # include <libpng/png.h>
5622 /* PNG library details. */
5624 DEF_IMGLIB_FN (png_get_io_ptr
);
5625 DEF_IMGLIB_FN (png_check_sig
);
5626 DEF_IMGLIB_FN (png_create_read_struct
);
5627 DEF_IMGLIB_FN (png_create_info_struct
);
5628 DEF_IMGLIB_FN (png_destroy_read_struct
);
5629 DEF_IMGLIB_FN (png_set_read_fn
);
5630 DEF_IMGLIB_FN (png_init_io
);
5631 DEF_IMGLIB_FN (png_set_sig_bytes
);
5632 DEF_IMGLIB_FN (png_read_info
);
5633 DEF_IMGLIB_FN (png_get_IHDR
);
5634 DEF_IMGLIB_FN (png_get_valid
);
5635 DEF_IMGLIB_FN (png_set_strip_16
);
5636 DEF_IMGLIB_FN (png_set_expand
);
5637 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5638 DEF_IMGLIB_FN (png_set_background
);
5639 DEF_IMGLIB_FN (png_get_bKGD
);
5640 DEF_IMGLIB_FN (png_read_update_info
);
5641 DEF_IMGLIB_FN (png_get_channels
);
5642 DEF_IMGLIB_FN (png_get_rowbytes
);
5643 DEF_IMGLIB_FN (png_read_image
);
5644 DEF_IMGLIB_FN (png_read_end
);
5645 DEF_IMGLIB_FN (png_error
);
5648 init_png_functions (Lisp_Object libraries
)
5652 /* Try loading libpng under probable names. */
5653 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5656 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5657 LOAD_IMGLIB_FN (library
, png_check_sig
);
5658 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5659 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5660 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5661 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5662 LOAD_IMGLIB_FN (library
, png_init_io
);
5663 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5664 LOAD_IMGLIB_FN (library
, png_read_info
);
5665 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5666 LOAD_IMGLIB_FN (library
, png_get_valid
);
5667 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5668 LOAD_IMGLIB_FN (library
, png_set_expand
);
5669 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5670 LOAD_IMGLIB_FN (library
, png_set_background
);
5671 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5672 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5673 LOAD_IMGLIB_FN (library
, png_get_channels
);
5674 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5675 LOAD_IMGLIB_FN (library
, png_read_image
);
5676 LOAD_IMGLIB_FN (library
, png_read_end
);
5677 LOAD_IMGLIB_FN (library
, png_error
);
5682 #define fn_png_get_io_ptr png_get_io_ptr
5683 #define fn_png_check_sig png_check_sig
5684 #define fn_png_create_read_struct png_create_read_struct
5685 #define fn_png_create_info_struct png_create_info_struct
5686 #define fn_png_destroy_read_struct png_destroy_read_struct
5687 #define fn_png_set_read_fn png_set_read_fn
5688 #define fn_png_init_io png_init_io
5689 #define fn_png_set_sig_bytes png_set_sig_bytes
5690 #define fn_png_read_info png_read_info
5691 #define fn_png_get_IHDR png_get_IHDR
5692 #define fn_png_get_valid png_get_valid
5693 #define fn_png_set_strip_16 png_set_strip_16
5694 #define fn_png_set_expand png_set_expand
5695 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5696 #define fn_png_set_background png_set_background
5697 #define fn_png_get_bKGD png_get_bKGD
5698 #define fn_png_read_update_info png_read_update_info
5699 #define fn_png_get_channels png_get_channels
5700 #define fn_png_get_rowbytes png_get_rowbytes
5701 #define fn_png_read_image png_read_image
5702 #define fn_png_read_end png_read_end
5703 #define fn_png_error png_error
5705 #endif /* HAVE_NTGUI */
5707 /* Error and warning handlers installed when the PNG library
5711 my_png_error (png_ptr
, msg
)
5712 png_struct
*png_ptr
;
5715 xassert (png_ptr
!= NULL
);
5716 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5717 longjmp (png_ptr
->jmpbuf
, 1);
5722 my_png_warning (png_ptr
, msg
)
5723 png_struct
*png_ptr
;
5726 xassert (png_ptr
!= NULL
);
5727 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5730 /* Memory source for PNG decoding. */
5732 struct png_memory_storage
5734 unsigned char *bytes
; /* The data */
5735 size_t len
; /* How big is it? */
5736 int index
; /* Where are we? */
5740 /* Function set as reader function when reading PNG image from memory.
5741 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5742 bytes from the input to DATA. */
5745 /* Work around a problem with MinGW builds of graphics libraries
5746 not honoring calling conventions. */
5747 #pragma optimize("g", off)
5751 png_read_from_memory (png_ptr
, data
, length
)
5752 png_structp png_ptr
;
5756 struct png_memory_storage
*tbr
5757 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5759 if (length
> tbr
->len
- tbr
->index
)
5760 fn_png_error (png_ptr
, "Read error");
5762 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5763 tbr
->index
= tbr
->index
+ length
;
5767 /* Restore normal optimization, as specified on the command line. */
5768 #pragma optimize("", on)
5771 /* Load PNG image IMG for use on frame F. Value is non-zero if
5779 Lisp_Object file
, specified_file
;
5780 Lisp_Object specified_data
;
5782 XImagePtr ximg
, mask_img
= NULL
;
5783 struct gcpro gcpro1
;
5784 png_struct
*png_ptr
= NULL
;
5785 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5786 FILE *volatile fp
= NULL
;
5788 png_byte
* volatile pixels
= NULL
;
5789 png_byte
** volatile rows
= NULL
;
5790 png_uint_32 width
, height
;
5791 int bit_depth
, color_type
, interlace_type
;
5793 png_uint_32 row_bytes
;
5795 double screen_gamma
;
5796 struct png_memory_storage tbr
; /* Data to be read */
5798 /* Find out what file to load. */
5799 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5800 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5804 if (NILP (specified_data
))
5806 file
= x_find_image_file (specified_file
);
5807 if (!STRINGP (file
))
5809 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5814 /* Open the image file. */
5815 fp
= fopen (SDATA (file
), "rb");
5818 image_error ("Cannot open image file `%s'", file
, Qnil
);
5824 /* Check PNG signature. */
5825 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5826 || !fn_png_check_sig (sig
, sizeof sig
))
5828 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5836 /* Read from memory. */
5837 tbr
.bytes
= SDATA (specified_data
);
5838 tbr
.len
= SBYTES (specified_data
);
5841 /* Check PNG signature. */
5842 if (tbr
.len
< sizeof sig
5843 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5845 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5850 /* Need to skip past the signature. */
5851 tbr
.bytes
+= sizeof (sig
);
5854 /* Initialize read and info structs for PNG lib. */
5855 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5856 my_png_error
, my_png_warning
);
5859 if (fp
) fclose (fp
);
5864 info_ptr
= fn_png_create_info_struct (png_ptr
);
5867 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5868 if (fp
) fclose (fp
);
5873 end_info
= fn_png_create_info_struct (png_ptr
);
5876 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5877 if (fp
) fclose (fp
);
5882 /* Set error jump-back. We come back here when the PNG library
5883 detects an error. */
5884 if (setjmp (png_ptr
->jmpbuf
))
5888 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5891 if (fp
) fclose (fp
);
5896 /* Read image info. */
5897 if (!NILP (specified_data
))
5898 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5900 fn_png_init_io (png_ptr
, fp
);
5902 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5903 fn_png_read_info (png_ptr
, info_ptr
);
5904 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5905 &interlace_type
, NULL
, NULL
);
5907 /* If image contains simply transparency data, we prefer to
5908 construct a clipping mask. */
5909 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5914 /* This function is easier to write if we only have to handle
5915 one data format: RGB or RGBA with 8 bits per channel. Let's
5916 transform other formats into that format. */
5918 /* Strip more than 8 bits per channel. */
5919 if (bit_depth
== 16)
5920 fn_png_set_strip_16 (png_ptr
);
5922 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5924 fn_png_set_expand (png_ptr
);
5926 /* Convert grayscale images to RGB. */
5927 if (color_type
== PNG_COLOR_TYPE_GRAY
5928 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5929 fn_png_set_gray_to_rgb (png_ptr
);
5931 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5933 #if 0 /* Avoid double gamma correction for PNG images. */
5934 { /* Tell the PNG lib to handle gamma correction for us. */
5937 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5938 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5939 /* The libpng documentation says this is right in this case. */
5940 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5943 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5944 /* Image contains gamma information. */
5945 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5947 /* Use the standard default for the image gamma. */
5948 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5952 /* Handle alpha channel by combining the image with a background
5953 color. Do this only if a real alpha channel is supplied. For
5954 simple transparency, we prefer a clipping mask. */
5957 png_color_16
*image_bg
;
5958 Lisp_Object specified_bg
5959 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5961 if (STRINGP (specified_bg
))
5962 /* The user specified `:background', use that. */
5964 /* W32 version incorrectly used COLORREF here!! ++kfs */
5966 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5968 png_color_16 user_bg
;
5970 bzero (&user_bg
, sizeof user_bg
);
5971 user_bg
.red
= color
.red
>> 8;
5972 user_bg
.green
= color
.green
>> 8;
5973 user_bg
.blue
= color
.blue
>> 8;
5975 fn_png_set_background (png_ptr
, &user_bg
,
5976 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5979 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5980 /* Image contains a background color with which to
5981 combine the image. */
5982 fn_png_set_background (png_ptr
, image_bg
,
5983 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5986 /* Image does not contain a background color with which
5987 to combine the image data via an alpha channel. Use
5988 the frame's background instead. */
5989 #ifdef HAVE_X_WINDOWS
5991 png_color_16 frame_background
;
5993 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5994 x_query_color (f
, &color
);
5996 bzero (&frame_background
, sizeof frame_background
);
5997 frame_background
.red
= color
.red
>> 8;
5998 frame_background
.green
= color
.green
>> 8;
5999 frame_background
.blue
= color
.blue
>> 8;
6000 #endif /* HAVE_X_WINDOWS */
6004 png_color_16 frame_background
;
6005 color
= FRAME_BACKGROUND_PIXEL (f
);
6006 #if 0 /* W32 TODO : Colormap support. */
6007 x_query_color (f
, &color
);
6009 bzero (&frame_background
, sizeof frame_background
);
6010 frame_background
.red
= GetRValue (color
);
6011 frame_background
.green
= GetGValue (color
);
6012 frame_background
.blue
= GetBValue (color
);
6013 #endif /* HAVE_NTGUI */
6016 unsigned long color
;
6017 png_color_16 frame_background
;
6018 color
= FRAME_BACKGROUND_PIXEL (f
);
6019 #if 0 /* MAC/W32 TODO : Colormap support. */
6020 x_query_color (f
, &color
);
6022 bzero (&frame_background
, sizeof frame_background
);
6023 frame_background
.red
= RED_FROM_ULONG (color
);
6024 frame_background
.green
= GREEN_FROM_ULONG (color
);
6025 frame_background
.blue
= BLUE_FROM_ULONG (color
);
6028 fn_png_set_background (png_ptr
, &frame_background
,
6029 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6033 /* Update info structure. */
6034 fn_png_read_update_info (png_ptr
, info_ptr
);
6036 /* Get number of channels. Valid values are 1 for grayscale images
6037 and images with a palette, 2 for grayscale images with transparency
6038 information (alpha channel), 3 for RGB images, and 4 for RGB
6039 images with alpha channel, i.e. RGBA. If conversions above were
6040 sufficient we should only have 3 or 4 channels here. */
6041 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6042 xassert (channels
== 3 || channels
== 4);
6044 /* Number of bytes needed for one row of the image. */
6045 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6047 /* Allocate memory for the image. */
6048 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6049 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6050 for (i
= 0; i
< height
; ++i
)
6051 rows
[i
] = pixels
+ i
* row_bytes
;
6053 /* Read the entire image. */
6054 fn_png_read_image (png_ptr
, rows
);
6055 fn_png_read_end (png_ptr
, info_ptr
);
6062 /* Create the X image and pixmap. */
6063 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6067 /* Create an image and pixmap serving as mask if the PNG image
6068 contains an alpha channel. */
6071 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6072 &mask_img
, &img
->mask
))
6074 x_destroy_x_image (ximg
);
6075 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6076 img
->pixmap
= NO_PIXMAP
;
6080 /* Fill the X image and mask from PNG data. */
6081 init_color_table ();
6083 for (y
= 0; y
< height
; ++y
)
6085 png_byte
*p
= rows
[y
];
6087 for (x
= 0; x
< width
; ++x
)
6094 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6095 /* An alpha channel, aka mask channel, associates variable
6096 transparency with an image. Where other image formats
6097 support binary transparency---fully transparent or fully
6098 opaque---PNG allows up to 254 levels of partial transparency.
6099 The PNG library implements partial transparency by combining
6100 the image with a specified background color.
6102 I'm not sure how to handle this here nicely: because the
6103 background on which the image is displayed may change, for
6104 real alpha channel support, it would be necessary to create
6105 a new image for each possible background.
6107 What I'm doing now is that a mask is created if we have
6108 boolean transparency information. Otherwise I'm using
6109 the frame's background color to combine the image with. */
6114 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
6120 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6121 /* Set IMG's background color from the PNG image, unless the user
6125 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6127 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6128 img
->background_valid
= 1;
6132 #ifdef COLOR_TABLE_SUPPORT
6133 /* Remember colors allocated for this image. */
6134 img
->colors
= colors_in_color_table (&img
->ncolors
);
6135 free_color_table ();
6136 #endif /* COLOR_TABLE_SUPPORT */
6139 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6144 img
->height
= height
;
6146 /* Maybe fill in the background field while we have ximg handy. */
6147 IMAGE_BACKGROUND (img
, f
, ximg
);
6149 /* Put the image into the pixmap, then free the X image and its buffer. */
6150 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6151 x_destroy_x_image (ximg
);
6153 /* Same for the mask. */
6156 /* Fill in the background_transparent field while we have the mask
6158 image_background_transparent (img
, f
, mask_img
);
6160 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6161 x_destroy_x_image (mask_img
);
6168 #else /* HAVE_PNG */
6177 if (MyCGImageCreateWithPNGDataProvider
)
6178 return image_load_quartz2d (f
, img
, 1);
6181 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
6185 #endif /* !HAVE_PNG */
6189 /***********************************************************************
6191 ***********************************************************************/
6193 #if defined (HAVE_JPEG) || defined (MAC_OS)
6195 static int jpeg_image_p
P_ ((Lisp_Object object
));
6196 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6198 /* The symbol `jpeg' identifying images of this type. */
6202 /* Indices of image specification fields in gs_format, below. */
6204 enum jpeg_keyword_index
6213 JPEG_HEURISTIC_MASK
,
6219 /* Vector of image_keyword structures describing the format
6220 of valid user-defined image specifications. */
6222 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6224 {":type", IMAGE_SYMBOL_VALUE
, 1},
6225 {":data", IMAGE_STRING_VALUE
, 0},
6226 {":file", IMAGE_STRING_VALUE
, 0},
6227 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6228 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6229 {":relief", IMAGE_INTEGER_VALUE
, 0},
6230 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6231 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6232 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6233 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6236 /* Structure describing the image type `jpeg'. */
6238 static struct image_type jpeg_type
=
6247 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6250 jpeg_image_p (object
)
6253 struct image_keyword fmt
[JPEG_LAST
];
6255 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6257 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6260 /* Must specify either the :data or :file keyword. */
6261 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6264 #endif /* HAVE_JPEG || MAC_OS */
6268 /* Work around a warning about HAVE_STDLIB_H being redefined in
6270 #ifdef HAVE_STDLIB_H
6271 #define HAVE_STDLIB_H_1
6272 #undef HAVE_STDLIB_H
6273 #endif /* HAVE_STLIB_H */
6275 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6276 /* jpeglib.h will define boolean differently depending on __WIN32__,
6277 so make sure it is defined. */
6281 #include <jpeglib.h>
6285 #ifdef HAVE_STLIB_H_1
6286 #define HAVE_STDLIB_H 1
6291 /* JPEG library details. */
6292 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6293 DEF_IMGLIB_FN (jpeg_start_decompress
);
6294 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6295 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6296 DEF_IMGLIB_FN (jpeg_read_header
);
6297 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6298 DEF_IMGLIB_FN (jpeg_stdio_src
);
6299 DEF_IMGLIB_FN (jpeg_std_error
);
6300 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6303 init_jpeg_functions (Lisp_Object libraries
)
6307 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6310 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6311 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6312 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6313 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6314 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
6315 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6316 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6317 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6318 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6322 /* Wrapper since we can't directly assign the function pointer
6323 to another function pointer that was declared more completely easily. */
6325 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
6326 j_decompress_ptr cinfo
;
6329 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6334 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6335 #define fn_jpeg_start_decompress jpeg_start_decompress
6336 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6337 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6338 #define fn_jpeg_read_header jpeg_read_header
6339 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6340 #define fn_jpeg_stdio_src jpeg_stdio_src
6341 #define fn_jpeg_std_error jpeg_std_error
6342 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6344 #endif /* HAVE_NTGUI */
6346 struct my_jpeg_error_mgr
6348 struct jpeg_error_mgr pub
;
6349 jmp_buf setjmp_buffer
;
6354 my_error_exit (cinfo
)
6357 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6358 longjmp (mgr
->setjmp_buffer
, 1);
6362 /* Init source method for JPEG data source manager. Called by
6363 jpeg_read_header() before any data is actually read. See
6364 libjpeg.doc from the JPEG lib distribution. */
6367 our_init_source (cinfo
)
6368 j_decompress_ptr cinfo
;
6373 /* Fill input buffer method for JPEG data source manager. Called
6374 whenever more data is needed. We read the whole image in one step,
6375 so this only adds a fake end of input marker at the end. */
6378 our_fill_input_buffer (cinfo
)
6379 j_decompress_ptr cinfo
;
6381 /* Insert a fake EOI marker. */
6382 struct jpeg_source_mgr
*src
= cinfo
->src
;
6383 static JOCTET buffer
[2];
6385 buffer
[0] = (JOCTET
) 0xFF;
6386 buffer
[1] = (JOCTET
) JPEG_EOI
;
6388 src
->next_input_byte
= buffer
;
6389 src
->bytes_in_buffer
= 2;
6394 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6395 is the JPEG data source manager. */
6398 our_skip_input_data (cinfo
, num_bytes
)
6399 j_decompress_ptr cinfo
;
6402 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6406 if (num_bytes
> src
->bytes_in_buffer
)
6407 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6409 src
->bytes_in_buffer
-= num_bytes
;
6410 src
->next_input_byte
+= num_bytes
;
6415 /* Method to terminate data source. Called by
6416 jpeg_finish_decompress() after all data has been processed. */
6419 our_term_source (cinfo
)
6420 j_decompress_ptr cinfo
;
6425 /* Set up the JPEG lib for reading an image from DATA which contains
6426 LEN bytes. CINFO is the decompression info structure created for
6427 reading the image. */
6430 jpeg_memory_src (cinfo
, data
, len
)
6431 j_decompress_ptr cinfo
;
6435 struct jpeg_source_mgr
*src
;
6437 if (cinfo
->src
== NULL
)
6439 /* First time for this JPEG object? */
6440 cinfo
->src
= (struct jpeg_source_mgr
*)
6441 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6442 sizeof (struct jpeg_source_mgr
));
6443 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6444 src
->next_input_byte
= data
;
6447 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6448 src
->init_source
= our_init_source
;
6449 src
->fill_input_buffer
= our_fill_input_buffer
;
6450 src
->skip_input_data
= our_skip_input_data
;
6451 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6452 src
->term_source
= our_term_source
;
6453 src
->bytes_in_buffer
= len
;
6454 src
->next_input_byte
= data
;
6458 /* Load image IMG for use on frame F. Patterned after example.c
6459 from the JPEG lib. */
6466 struct jpeg_decompress_struct cinfo
;
6467 struct my_jpeg_error_mgr mgr
;
6468 Lisp_Object file
, specified_file
;
6469 Lisp_Object specified_data
;
6470 FILE * volatile fp
= NULL
;
6472 int row_stride
, x
, y
;
6473 XImagePtr ximg
= NULL
;
6475 unsigned long *colors
;
6477 struct gcpro gcpro1
;
6479 /* Open the JPEG file. */
6480 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6481 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6485 if (NILP (specified_data
))
6487 file
= x_find_image_file (specified_file
);
6488 if (!STRINGP (file
))
6490 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6495 fp
= fopen (SDATA (file
), "rb");
6498 image_error ("Cannot open `%s'", file
, Qnil
);
6504 /* Customize libjpeg's error handling to call my_error_exit when an
6505 error is detected. This function will perform a longjmp. */
6506 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
6507 mgr
.pub
.error_exit
= my_error_exit
;
6509 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6513 /* Called from my_error_exit. Display a JPEG error. */
6514 char buffer
[JMSG_LENGTH_MAX
];
6515 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6516 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6517 build_string (buffer
));
6520 /* Close the input file and destroy the JPEG object. */
6522 fclose ((FILE *) fp
);
6523 fn_jpeg_destroy_decompress (&cinfo
);
6525 /* If we already have an XImage, free that. */
6526 x_destroy_x_image (ximg
);
6528 /* Free pixmap and colors. */
6529 x_clear_image (f
, img
);
6535 /* Create the JPEG decompression object. Let it read from fp.
6536 Read the JPEG image header. */
6537 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6539 if (NILP (specified_data
))
6540 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
6542 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6543 SBYTES (specified_data
));
6545 fn_jpeg_read_header (&cinfo
, 1);
6547 /* Customize decompression so that color quantization will be used.
6548 Start decompression. */
6549 cinfo
.quantize_colors
= 1;
6550 fn_jpeg_start_decompress (&cinfo
);
6551 width
= img
->width
= cinfo
.output_width
;
6552 height
= img
->height
= cinfo
.output_height
;
6554 /* Create X image and pixmap. */
6555 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6556 longjmp (mgr
.setjmp_buffer
, 2);
6558 /* Allocate colors. When color quantization is used,
6559 cinfo.actual_number_of_colors has been set with the number of
6560 colors generated, and cinfo.colormap is a two-dimensional array
6561 of color indices in the range 0..cinfo.actual_number_of_colors.
6562 No more than 255 colors will be generated. */
6566 if (cinfo
.out_color_components
> 2)
6567 ir
= 0, ig
= 1, ib
= 2;
6568 else if (cinfo
.out_color_components
> 1)
6569 ir
= 0, ig
= 1, ib
= 0;
6571 ir
= 0, ig
= 0, ib
= 0;
6573 /* Use the color table mechanism because it handles colors that
6574 cannot be allocated nicely. Such colors will be replaced with
6575 a default color, and we don't have to care about which colors
6576 can be freed safely, and which can't. */
6577 init_color_table ();
6578 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6581 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6583 /* Multiply RGB values with 255 because X expects RGB values
6584 in the range 0..0xffff. */
6585 int r
= cinfo
.colormap
[ir
][i
] << 8;
6586 int g
= cinfo
.colormap
[ig
][i
] << 8;
6587 int b
= cinfo
.colormap
[ib
][i
] << 8;
6588 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6591 #ifdef COLOR_TABLE_SUPPORT
6592 /* Remember those colors actually allocated. */
6593 img
->colors
= colors_in_color_table (&img
->ncolors
);
6594 free_color_table ();
6595 #endif /* COLOR_TABLE_SUPPORT */
6599 row_stride
= width
* cinfo
.output_components
;
6600 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6602 for (y
= 0; y
< height
; ++y
)
6604 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6605 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6606 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6610 fn_jpeg_finish_decompress (&cinfo
);
6611 fn_jpeg_destroy_decompress (&cinfo
);
6613 fclose ((FILE *) fp
);
6615 /* Maybe fill in the background field while we have ximg handy. */
6616 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6617 IMAGE_BACKGROUND (img
, f
, ximg
);
6619 /* Put the image into the pixmap. */
6620 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6621 x_destroy_x_image (ximg
);
6626 #else /* HAVE_JPEG */
6635 return image_load_quartz2d (f
, img
, 0);
6637 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6642 #endif /* !HAVE_JPEG */
6646 /***********************************************************************
6648 ***********************************************************************/
6650 #if defined (HAVE_TIFF) || defined (MAC_OS)
6652 static int tiff_image_p
P_ ((Lisp_Object object
));
6653 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6655 /* The symbol `tiff' identifying images of this type. */
6659 /* Indices of image specification fields in tiff_format, below. */
6661 enum tiff_keyword_index
6670 TIFF_HEURISTIC_MASK
,
6676 /* Vector of image_keyword structures describing the format
6677 of valid user-defined image specifications. */
6679 static struct image_keyword tiff_format
[TIFF_LAST
] =
6681 {":type", IMAGE_SYMBOL_VALUE
, 1},
6682 {":data", IMAGE_STRING_VALUE
, 0},
6683 {":file", IMAGE_STRING_VALUE
, 0},
6684 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6685 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6686 {":relief", IMAGE_INTEGER_VALUE
, 0},
6687 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6688 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6689 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6690 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6693 /* Structure describing the image type `tiff'. */
6695 static struct image_type tiff_type
=
6704 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6707 tiff_image_p (object
)
6710 struct image_keyword fmt
[TIFF_LAST
];
6711 bcopy (tiff_format
, fmt
, sizeof fmt
);
6713 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6716 /* Must specify either the :data or :file keyword. */
6717 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6720 #endif /* HAVE_TIFF || MAC_OS */
6728 /* TIFF library details. */
6729 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6730 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6731 DEF_IMGLIB_FN (TIFFOpen
);
6732 DEF_IMGLIB_FN (TIFFClientOpen
);
6733 DEF_IMGLIB_FN (TIFFGetField
);
6734 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6735 DEF_IMGLIB_FN (TIFFClose
);
6738 init_tiff_functions (Lisp_Object libraries
)
6742 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
6745 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6746 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6747 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6748 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6749 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6750 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6751 LOAD_IMGLIB_FN (library
, TIFFClose
);
6757 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6758 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6759 #define fn_TIFFOpen TIFFOpen
6760 #define fn_TIFFClientOpen TIFFClientOpen
6761 #define fn_TIFFGetField TIFFGetField
6762 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6763 #define fn_TIFFClose TIFFClose
6765 #endif /* HAVE_NTGUI */
6768 /* Reading from a memory buffer for TIFF images Based on the PNG
6769 memory source, but we have to provide a lot of extra functions.
6772 We really only need to implement read and seek, but I am not
6773 convinced that the TIFF library is smart enough not to destroy
6774 itself if we only hand it the function pointers we need to
6779 unsigned char *bytes
;
6786 tiff_read_from_memory (data
, buf
, size
)
6791 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6793 if (size
> src
->len
- src
->index
)
6795 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6801 tiff_write_from_memory (data
, buf
, size
)
6810 tiff_seek_in_memory (data
, off
, whence
)
6815 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6820 case SEEK_SET
: /* Go from beginning of source. */
6824 case SEEK_END
: /* Go from end of source. */
6825 idx
= src
->len
+ off
;
6828 case SEEK_CUR
: /* Go from current position. */
6829 idx
= src
->index
+ off
;
6832 default: /* Invalid `whence'. */
6836 if (idx
> src
->len
|| idx
< 0)
6844 tiff_close_memory (data
)
6852 tiff_mmap_memory (data
, pbase
, psize
)
6857 /* It is already _IN_ memory. */
6862 tiff_unmap_memory (data
, base
, size
)
6867 /* We don't need to do this. */
6871 tiff_size_of_memory (data
)
6874 return ((tiff_memory_source
*) data
)->len
;
6879 tiff_error_handler (title
, format
, ap
)
6880 const char *title
, *format
;
6886 len
= sprintf (buf
, "TIFF error: %s ", title
);
6887 vsprintf (buf
+ len
, format
, ap
);
6888 add_to_log (buf
, Qnil
, Qnil
);
6893 tiff_warning_handler (title
, format
, ap
)
6894 const char *title
, *format
;
6900 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6901 vsprintf (buf
+ len
, format
, ap
);
6902 add_to_log (buf
, Qnil
, Qnil
);
6906 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6914 Lisp_Object file
, specified_file
;
6915 Lisp_Object specified_data
;
6917 int width
, height
, x
, y
;
6921 struct gcpro gcpro1
;
6922 tiff_memory_source memsrc
;
6924 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6925 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6929 fn_TIFFSetErrorHandler (tiff_error_handler
);
6930 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6932 if (NILP (specified_data
))
6934 /* Read from a file */
6935 file
= x_find_image_file (specified_file
);
6936 if (!STRINGP (file
))
6938 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6943 /* Try to open the image file. */
6944 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6947 image_error ("Cannot open `%s'", file
, Qnil
);
6954 /* Memory source! */
6955 memsrc
.bytes
= SDATA (specified_data
);
6956 memsrc
.len
= SBYTES (specified_data
);
6959 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6960 (TIFFReadWriteProc
) tiff_read_from_memory
,
6961 (TIFFReadWriteProc
) tiff_write_from_memory
,
6962 tiff_seek_in_memory
,
6964 tiff_size_of_memory
,
6970 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6976 /* Get width and height of the image, and allocate a raster buffer
6977 of width x height 32-bit values. */
6978 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6979 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6980 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6982 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6983 fn_TIFFClose (tiff
);
6986 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6992 /* Create the X image and pixmap. */
6993 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7000 /* Initialize the color table. */
7001 init_color_table ();
7003 /* Process the pixel raster. Origin is in the lower-left corner. */
7004 for (y
= 0; y
< height
; ++y
)
7006 uint32
*row
= buf
+ y
* width
;
7008 for (x
= 0; x
< width
; ++x
)
7010 uint32 abgr
= row
[x
];
7011 int r
= TIFFGetR (abgr
) << 8;
7012 int g
= TIFFGetG (abgr
) << 8;
7013 int b
= TIFFGetB (abgr
) << 8;
7014 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7018 #ifdef COLOR_TABLE_SUPPORT
7019 /* Remember the colors allocated for the image. Free the color table. */
7020 img
->colors
= colors_in_color_table (&img
->ncolors
);
7021 free_color_table ();
7022 #endif /* COLOR_TABLE_SUPPORT */
7025 img
->height
= height
;
7027 /* Maybe fill in the background field while we have ximg handy. */
7028 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7029 IMAGE_BACKGROUND (img
, f
, ximg
);
7031 /* Put the image into the pixmap, then free the X image and its buffer. */
7032 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7033 x_destroy_x_image (ximg
);
7040 #else /* HAVE_TIFF */
7048 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
7052 #endif /* !HAVE_TIFF */
7056 /***********************************************************************
7058 ***********************************************************************/
7060 #if defined (HAVE_GIF) || defined (MAC_OS)
7062 static int gif_image_p
P_ ((Lisp_Object object
));
7063 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7065 /* The symbol `gif' identifying images of this type. */
7069 /* Indices of image specification fields in gif_format, below. */
7071 enum gif_keyword_index
7087 /* Vector of image_keyword structures describing the format
7088 of valid user-defined image specifications. */
7090 static struct image_keyword gif_format
[GIF_LAST
] =
7092 {":type", IMAGE_SYMBOL_VALUE
, 1},
7093 {":data", IMAGE_STRING_VALUE
, 0},
7094 {":file", IMAGE_STRING_VALUE
, 0},
7095 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7096 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7097 {":relief", IMAGE_INTEGER_VALUE
, 0},
7098 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7099 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7100 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7101 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7102 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7105 /* Structure describing the image type `gif'. */
7107 static struct image_type gif_type
=
7116 /* Return non-zero if OBJECT is a valid GIF image specification. */
7119 gif_image_p (object
)
7122 struct image_keyword fmt
[GIF_LAST
];
7123 bcopy (gif_format
, fmt
, sizeof fmt
);
7125 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7128 /* Must specify either the :data or :file keyword. */
7129 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7132 #endif /* HAVE_GIF || MAC_OS */
7136 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7137 /* avoid conflict with QuickdrawText.h */
7138 #define DrawText gif_DrawText
7139 #include <gif_lib.h>
7142 #else /* HAVE_NTGUI || MAC_OS */
7144 #include <gif_lib.h>
7146 #endif /* HAVE_NTGUI || MAC_OS */
7151 /* GIF library details. */
7152 DEF_IMGLIB_FN (DGifCloseFile
);
7153 DEF_IMGLIB_FN (DGifSlurp
);
7154 DEF_IMGLIB_FN (DGifOpen
);
7155 DEF_IMGLIB_FN (DGifOpenFileName
);
7158 init_gif_functions (Lisp_Object libraries
)
7162 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7165 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7166 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7167 LOAD_IMGLIB_FN (library
, DGifOpen
);
7168 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7174 #define fn_DGifCloseFile DGifCloseFile
7175 #define fn_DGifSlurp DGifSlurp
7176 #define fn_DGifOpen DGifOpen
7177 #define fn_DGifOpenFileName DGifOpenFileName
7179 #endif /* HAVE_NTGUI */
7181 /* Reading a GIF image from memory
7182 Based on the PNG memory stuff to a certain extent. */
7186 unsigned char *bytes
;
7192 /* Make the current memory source available to gif_read_from_memory.
7193 It's done this way because not all versions of libungif support
7194 a UserData field in the GifFileType structure. */
7195 static gif_memory_source
*current_gif_memory_src
;
7198 gif_read_from_memory (file
, buf
, len
)
7203 gif_memory_source
*src
= current_gif_memory_src
;
7205 if (len
> src
->len
- src
->index
)
7208 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7214 /* Load GIF image IMG for use on frame F. Value is non-zero if
7222 Lisp_Object file
, specified_file
;
7223 Lisp_Object specified_data
;
7224 int rc
, width
, height
, x
, y
, i
;
7226 ColorMapObject
*gif_color_map
;
7227 unsigned long pixel_colors
[256];
7229 struct gcpro gcpro1
;
7231 int ino
, image_left
, image_top
, image_width
, image_height
;
7232 gif_memory_source memsrc
;
7233 unsigned char *raster
;
7235 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7236 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7240 if (NILP (specified_data
))
7242 file
= x_find_image_file (specified_file
);
7243 if (!STRINGP (file
))
7245 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7250 /* Open the GIF file. */
7251 gif
= fn_DGifOpenFileName (SDATA (file
));
7254 image_error ("Cannot open `%s'", file
, Qnil
);
7261 /* Read from memory! */
7262 current_gif_memory_src
= &memsrc
;
7263 memsrc
.bytes
= SDATA (specified_data
);
7264 memsrc
.len
= SBYTES (specified_data
);
7267 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
7270 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7276 /* Read entire contents. */
7277 rc
= fn_DGifSlurp (gif
);
7278 if (rc
== GIF_ERROR
)
7280 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7281 fn_DGifCloseFile (gif
);
7286 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7287 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7288 if (ino
>= gif
->ImageCount
)
7290 image_error ("Invalid image number `%s' in image `%s'",
7292 fn_DGifCloseFile (gif
);
7297 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
7298 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
7300 /* Create the X image and pixmap. */
7301 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7303 fn_DGifCloseFile (gif
);
7308 /* Allocate colors. */
7309 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7311 gif_color_map
= gif
->SColorMap
;
7312 init_color_table ();
7313 bzero (pixel_colors
, sizeof pixel_colors
);
7315 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7317 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7318 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7319 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7320 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7323 #ifdef COLOR_TABLE_SUPPORT
7324 img
->colors
= colors_in_color_table (&img
->ncolors
);
7325 free_color_table ();
7326 #endif /* COLOR_TABLE_SUPPORT */
7328 /* Clear the part of the screen image that are not covered by
7329 the image from the GIF file. Full animated GIF support
7330 requires more than can be done here (see the gif89 spec,
7331 disposal methods). Let's simply assume that the part
7332 not covered by a sub-image is in the frame's background color. */
7333 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
7334 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
7335 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7336 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7338 for (y
= 0; y
< image_top
; ++y
)
7339 for (x
= 0; x
< width
; ++x
)
7340 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7342 for (y
= image_top
+ image_height
; y
< height
; ++y
)
7343 for (x
= 0; x
< width
; ++x
)
7344 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7346 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
7348 for (x
= 0; x
< image_left
; ++x
)
7349 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7350 for (x
= image_left
+ image_width
; x
< width
; ++x
)
7351 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7354 /* Read the GIF image into the X image. We use a local variable
7355 `raster' here because RasterBits below is a char *, and invites
7356 problems with bytes >= 0x80. */
7357 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7359 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7361 static int interlace_start
[] = {0, 4, 2, 1};
7362 static int interlace_increment
[] = {8, 8, 4, 2};
7364 int row
= interlace_start
[0];
7368 for (y
= 0; y
< image_height
; y
++)
7370 if (row
>= image_height
)
7372 row
= interlace_start
[++pass
];
7373 while (row
>= image_height
)
7374 row
= interlace_start
[++pass
];
7377 for (x
= 0; x
< image_width
; x
++)
7379 int i
= raster
[(y
* image_width
) + x
];
7380 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
7384 row
+= interlace_increment
[pass
];
7389 for (y
= 0; y
< image_height
; ++y
)
7390 for (x
= 0; x
< image_width
; ++x
)
7392 int i
= raster
[y
* image_width
+ x
];
7393 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
7397 fn_DGifCloseFile (gif
);
7399 /* Maybe fill in the background field while we have ximg handy. */
7400 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7401 IMAGE_BACKGROUND (img
, f
, ximg
);
7403 /* Put the image into the pixmap, then free the X image and its buffer. */
7404 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7405 x_destroy_x_image (ximg
);
7419 Lisp_Object specified_file
, file
;
7420 Lisp_Object specified_data
;
7422 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
7430 Lisp_Object specified_bg
;
7436 struct gcpro gcpro1
;
7441 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7442 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7444 if (NILP (specified_data
))
7446 /* Read from a file */
7450 err
= find_image_fsspec (specified_file
, &file
, &fss
);
7454 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7459 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
7460 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
7464 if (!graphic_p
&& !movie_p
)
7466 if (prefer_graphic_p
)
7467 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
7468 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
7471 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
7472 CloseMovieFile (refnum
);
7475 image_error ("Error reading `%s'", file
, Qnil
);
7481 /* Memory source! */
7483 long file_type_atom
[3];
7485 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
7488 image_error ("Cannot allocate data handle for `%s'",
7493 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
7494 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
7495 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
7496 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
7499 err
= PtrAndHand ("\p", dref
, 1);
7501 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
7504 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
7507 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
7508 &movie_p
, &prefer_graphic_p
, 0);
7512 if (!graphic_p
&& !movie_p
)
7514 if (prefer_graphic_p
)
7518 DisposeHandle (dref
);
7519 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
7523 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
7524 HandleDataHandlerSubType
);
7525 DisposeHandle (dref
);
7530 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7531 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7532 track
= GetMovieIndTrack (movie
, 1);
7533 media
= GetTrackMedia (track
);
7534 nsamples
= GetMediaSampleCount (media
);
7535 if (ino
>= nsamples
)
7537 image_error ("Invalid image number `%s' in image `%s'",
7542 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
7543 if (!STRINGP (specified_bg
) ||
7544 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
7546 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
7547 color
.red
= RED16_FROM_ULONG (color
.pixel
);
7548 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
7549 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
7551 GetMovieBox (movie
, &rect
);
7552 width
= img
->width
= rect
.right
- rect
.left
;
7553 height
= img
->height
= rect
.bottom
- rect
.top
;
7554 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7557 GetGWorld (&old_port
, &old_gdh
);
7558 SetGWorld (ximg
, NULL
);
7559 bg_color
.red
= color
.red
;
7560 bg_color
.green
= color
.green
;
7561 bg_color
.blue
= color
.blue
;
7562 RGBBackColor (&bg_color
);
7563 SetGWorld (old_port
, old_gdh
);
7564 SetMovieActive (movie
, 1);
7565 SetMovieGWorld (movie
, ximg
, NULL
);
7566 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7567 SetMovieTimeValue (movie
, time
);
7568 MoviesTask (movie
, 0L);
7569 DisposeTrackMedia (media
);
7570 DisposeMovieTrack (track
);
7571 DisposeMovie (movie
);
7574 /* Maybe fill in the background field while we have ximg handy. */
7575 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7576 IMAGE_BACKGROUND (img
, f
, ximg
);
7578 /* Put the image into the pixmap. */
7579 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7580 x_destroy_x_image (ximg
);
7584 image_error ("Cannot open `%s'", file
, Qnil
);
7587 DisposeTrackMedia (media
);
7589 DisposeMovieTrack (track
);
7591 DisposeMovie (movie
);
7598 #endif /* HAVE_GIF */
7602 /***********************************************************************
7604 ***********************************************************************/
7606 #ifdef HAVE_X_WINDOWS
7607 #define HAVE_GHOSTSCRIPT 1
7608 #endif /* HAVE_X_WINDOWS */
7610 /* The symbol `postscript' identifying images of this type. */
7612 Lisp_Object Qpostscript
;
7614 #ifdef HAVE_GHOSTSCRIPT
7616 static int gs_image_p
P_ ((Lisp_Object object
));
7617 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7618 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7620 /* Keyword symbols. */
7622 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7624 /* Indices of image specification fields in gs_format, below. */
7626 enum gs_keyword_index
7644 /* Vector of image_keyword structures describing the format
7645 of valid user-defined image specifications. */
7647 static struct image_keyword gs_format
[GS_LAST
] =
7649 {":type", IMAGE_SYMBOL_VALUE
, 1},
7650 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7651 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7652 {":file", IMAGE_STRING_VALUE
, 1},
7653 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7654 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7655 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7656 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7657 {":relief", IMAGE_INTEGER_VALUE
, 0},
7658 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7659 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7660 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7661 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7664 /* Structure describing the image type `ghostscript'. */
7666 static struct image_type gs_type
=
7676 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7679 gs_clear_image (f
, img
)
7683 /* IMG->data.ptr_val may contain a recorded colormap. */
7684 xfree (img
->data
.ptr_val
);
7685 x_clear_image (f
, img
);
7689 /* Return non-zero if OBJECT is a valid Ghostscript image
7696 struct image_keyword fmt
[GS_LAST
];
7700 bcopy (gs_format
, fmt
, sizeof fmt
);
7702 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7705 /* Bounding box must be a list or vector containing 4 integers. */
7706 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7709 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7710 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7715 else if (VECTORP (tem
))
7717 if (XVECTOR (tem
)->size
!= 4)
7719 for (i
= 0; i
< 4; ++i
)
7720 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7730 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7739 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7740 struct gcpro gcpro1
, gcpro2
;
7742 double in_width
, in_height
;
7743 Lisp_Object pixel_colors
= Qnil
;
7745 /* Compute pixel size of pixmap needed from the given size in the
7746 image specification. Sizes in the specification are in pt. 1 pt
7747 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7749 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7750 in_width
= XFASTINT (pt_width
) / 72.0;
7751 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7752 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7753 in_height
= XFASTINT (pt_height
) / 72.0;
7754 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7756 /* Create the pixmap. */
7757 xassert (img
->pixmap
== NO_PIXMAP
);
7759 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7761 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7762 img
->width
, img
->height
,
7763 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7768 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7772 /* Call the loader to fill the pixmap. It returns a process object
7773 if successful. We do not record_unwind_protect here because
7774 other places in redisplay like calling window scroll functions
7775 don't either. Let the Lisp loader use `unwind-protect' instead. */
7776 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7778 sprintf (buffer
, "%lu %lu",
7779 (unsigned long) FRAME_X_WINDOW (f
),
7780 (unsigned long) img
->pixmap
);
7781 window_and_pixmap_id
= build_string (buffer
);
7783 sprintf (buffer
, "%lu %lu",
7784 FRAME_FOREGROUND_PIXEL (f
),
7785 FRAME_BACKGROUND_PIXEL (f
));
7786 pixel_colors
= build_string (buffer
);
7788 XSETFRAME (frame
, f
);
7789 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7791 loader
= intern ("gs-load-image");
7793 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7794 make_number (img
->width
),
7795 make_number (img
->height
),
7796 window_and_pixmap_id
,
7799 return PROCESSP (img
->data
.lisp_val
);
7803 /* Kill the Ghostscript process that was started to fill PIXMAP on
7804 frame F. Called from XTread_socket when receiving an event
7805 telling Emacs that Ghostscript has finished drawing. */
7808 x_kill_gs_process (pixmap
, f
)
7812 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7816 /* Find the image containing PIXMAP. */
7817 for (i
= 0; i
< c
->used
; ++i
)
7818 if (c
->images
[i
]->pixmap
== pixmap
)
7821 /* Should someone in between have cleared the image cache, for
7822 instance, give up. */
7826 /* Kill the GS process. We should have found PIXMAP in the image
7827 cache and its image should contain a process object. */
7829 xassert (PROCESSP (img
->data
.lisp_val
));
7830 Fkill_process (img
->data
.lisp_val
, Qnil
);
7831 img
->data
.lisp_val
= Qnil
;
7833 #if defined (HAVE_X_WINDOWS)
7835 /* On displays with a mutable colormap, figure out the colors
7836 allocated for the image by looking at the pixels of an XImage for
7838 class = FRAME_X_VISUAL (f
)->class;
7839 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7845 /* Try to get an XImage for img->pixmep. */
7846 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7847 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7852 /* Initialize the color table. */
7853 init_color_table ();
7855 /* For each pixel of the image, look its color up in the
7856 color table. After having done so, the color table will
7857 contain an entry for each color used by the image. */
7858 for (y
= 0; y
< img
->height
; ++y
)
7859 for (x
= 0; x
< img
->width
; ++x
)
7861 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7862 lookup_pixel_color (f
, pixel
);
7865 /* Record colors in the image. Free color table and XImage. */
7866 #ifdef COLOR_TABLE_SUPPORT
7867 img
->colors
= colors_in_color_table (&img
->ncolors
);
7868 free_color_table ();
7870 XDestroyImage (ximg
);
7872 #if 0 /* This doesn't seem to be the case. If we free the colors
7873 here, we get a BadAccess later in x_clear_image when
7874 freeing the colors. */
7875 /* We have allocated colors once, but Ghostscript has also
7876 allocated colors on behalf of us. So, to get the
7877 reference counts right, free them once. */
7879 x_free_colors (f
, img
->colors
, img
->ncolors
);
7883 image_error ("Cannot get X image of `%s'; colors will not be freed",
7888 #endif /* HAVE_X_WINDOWS */
7890 /* Now that we have the pixmap, compute mask and transform the
7891 image if requested. */
7893 postprocess_image (f
, img
);
7897 #endif /* HAVE_GHOSTSCRIPT */
7900 /***********************************************************************
7902 ***********************************************************************/
7906 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7907 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7911 return valid_image_p (spec
) ? Qt
: Qnil
;
7915 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7921 if (valid_image_p (spec
))
7922 id
= lookup_image (SELECTED_FRAME (), spec
);
7925 return make_number (id
);
7928 #endif /* GLYPH_DEBUG != 0 */
7931 /***********************************************************************
7933 ***********************************************************************/
7936 /* Image types that rely on external libraries are loaded dynamically
7937 if the library is available. */
7938 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
7939 define_image_type (image_type, init_lib_fn (libraries))
7941 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
7942 define_image_type (image_type, 1)
7943 #endif /* HAVE_NTGUI */
7945 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
7946 doc
: /* Initialize image library implementing image type TYPE.
7947 Return non-nil if TYPE is a supported image type.
7949 Image types pbm and xbm are prebuilt; other types are loaded here.
7950 Libraries to load are specified in alist LIBRARIES (usually, the value
7951 of `image-library-alist', which see). */)
7953 Lisp_Object type
, libraries
;
7957 /* Don't try to reload the library. */
7958 tested
= Fassq (type
, Vimage_type_cache
);
7960 return XCDR (tested
);
7962 #if defined (HAVE_XPM) || defined (MAC_OS)
7963 if (EQ (type
, Qxpm
))
7964 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
7967 #if defined (HAVE_JPEG) || defined (MAC_OS)
7968 if (EQ (type
, Qjpeg
))
7969 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
7972 #if defined (HAVE_TIFF) || defined (MAC_OS)
7973 if (EQ (type
, Qtiff
))
7974 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
7977 #if defined (HAVE_GIF) || defined (MAC_OS)
7978 if (EQ (type
, Qgif
))
7979 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
7982 #if defined (HAVE_PNG) || defined (MAC_OS)
7983 if (EQ (type
, Qpng
))
7984 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
7987 #ifdef HAVE_GHOSTSCRIPT
7988 if (EQ (type
, Qpostscript
))
7989 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
7992 /* If the type is not recognized, avoid testing it ever again. */
7993 CACHE_IMAGE_TYPE (type
, Qnil
);
8000 /* Must be defined now becase we're going to update it below, while
8001 defining the supported image types. */
8002 DEFVAR_LISP ("image-types", &Vimage_types
,
8003 doc
: /* List of potentially supported image types.
8004 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
8005 To check whether it is really supported, use `image-type-available-p'. */);
8006 Vimage_types
= Qnil
;
8008 Vimage_type_cache
= Qnil
;
8009 staticpro (&Vimage_type_cache
);
8011 QCascent
= intern (":ascent");
8012 staticpro (&QCascent
);
8013 QCmargin
= intern (":margin");
8014 staticpro (&QCmargin
);
8015 QCrelief
= intern (":relief");
8016 staticpro (&QCrelief
);
8017 QCconversion
= intern (":conversion");
8018 staticpro (&QCconversion
);
8019 QCcolor_symbols
= intern (":color-symbols");
8020 staticpro (&QCcolor_symbols
);
8021 QCheuristic_mask
= intern (":heuristic-mask");
8022 staticpro (&QCheuristic_mask
);
8023 QCindex
= intern (":index");
8024 staticpro (&QCindex
);
8025 QCmatrix
= intern (":matrix");
8026 staticpro (&QCmatrix
);
8027 QCcolor_adjustment
= intern (":color-adjustment");
8028 staticpro (&QCcolor_adjustment
);
8029 QCmask
= intern (":mask");
8030 staticpro (&QCmask
);
8032 Qlaplace
= intern ("laplace");
8033 staticpro (&Qlaplace
);
8034 Qemboss
= intern ("emboss");
8035 staticpro (&Qemboss
);
8036 Qedge_detection
= intern ("edge-detection");
8037 staticpro (&Qedge_detection
);
8038 Qheuristic
= intern ("heuristic");
8039 staticpro (&Qheuristic
);
8041 Qpostscript
= intern ("postscript");
8042 staticpro (&Qpostscript
);
8043 #ifdef HAVE_GHOSTSCRIPT
8044 ADD_IMAGE_TYPE(Qpostscript
);
8045 QCloader
= intern (":loader");
8046 staticpro (&QCloader
);
8047 QCbounding_box
= intern (":bounding-box");
8048 staticpro (&QCbounding_box
);
8049 QCpt_width
= intern (":pt-width");
8050 staticpro (&QCpt_width
);
8051 QCpt_height
= intern (":pt-height");
8052 staticpro (&QCpt_height
);
8053 #endif /* HAVE_GHOSTSCRIPT */
8055 Qpbm
= intern ("pbm");
8057 ADD_IMAGE_TYPE(Qpbm
);
8059 Qxbm
= intern ("xbm");
8061 ADD_IMAGE_TYPE(Qxbm
);
8063 #if defined (HAVE_XPM) || defined (MAC_OS)
8064 Qxpm
= intern ("xpm");
8066 ADD_IMAGE_TYPE(Qxpm
);
8069 #if defined (HAVE_JPEG) || defined (MAC_OS)
8070 Qjpeg
= intern ("jpeg");
8072 ADD_IMAGE_TYPE(Qjpeg
);
8075 #if defined (HAVE_TIFF) || defined (MAC_OS)
8076 Qtiff
= intern ("tiff");
8078 ADD_IMAGE_TYPE(Qtiff
);
8081 #if defined (HAVE_GIF) || defined (MAC_OS)
8082 Qgif
= intern ("gif");
8084 ADD_IMAGE_TYPE(Qgif
);
8087 #if defined (HAVE_PNG) || defined (MAC_OS)
8088 Qpng
= intern ("png");
8090 ADD_IMAGE_TYPE(Qpng
);
8093 defsubr (&Sinit_image_library
);
8094 defsubr (&Sclear_image_cache
);
8095 defsubr (&Simage_size
);
8096 defsubr (&Simage_mask_p
);
8100 defsubr (&Slookup_image
);
8103 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8104 doc
: /* Non-nil means always draw a cross over disabled images.
8105 Disabled images are those having an `:conversion disabled' property.
8106 A cross is always drawn on black & white displays. */);
8107 cross_disabled_images
= 0;
8109 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8110 doc
: /* List of directories to search for window system bitmap files. */);
8111 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8113 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8114 doc
: /* Time after which cached images are removed from the cache.
8115 When an image has not been displayed this many seconds, remove it
8116 from the image cache. Value must be an integer or nil with nil
8117 meaning don't clear the cache. */);
8118 Vimage_cache_eviction_delay
= make_number (30 * 60);
8126 define_image_type (&xbm_type
, 1);
8127 define_image_type (&pbm_type
, 1);
8130 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8133 init_image_func_pointer ();
8138 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8139 (do not change this comment) */