1 /* Functions for image support on window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
38 #include "dispextern.h"
39 #include "blockinput.h"
46 #include <sys/types.h>
49 #define COLOR_TABLE_SUPPORT 1
51 typedef struct x_bitmap_record Bitmap_Record
;
52 typedef XImage
* XImagePtr
;
53 typedef XImagePtr XImagePtr_or_DC
;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
56 #define PNG_BG_COLOR_SHIFT 0
58 #define RGB_PIXEL_COLOR unsigned long
60 #define PIX_MASK_RETAIN(f) 0
61 #define PIX_MASK_DRAW(f) 1
62 #endif /* HAVE_X_WINDOWS */
68 /* W32_TODO : Color tables on W32. */
69 #undef COLOR_TABLE_SUPPORT
71 typedef struct w32_bitmap_record Bitmap_Record
;
72 typedef XImage
*XImagePtr
;
73 typedef HDC XImagePtr_or_DC
;
74 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
76 #define PNG_BG_COLOR_SHIFT 0
78 #define RGB_PIXEL_COLOR COLORREF
80 #define PIX_MASK_RETAIN(f) 0
81 #define PIX_MASK_DRAW(f) 1
83 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
84 #define x_defined_color w32_defined_color
85 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
86 #endif /* HAVE_NTGUI */
95 #include <QuickTime/QuickTime.h>
96 #else /* not MAC_OSX */
99 #include <TextUtils.h>
100 #endif /* not MAC_OSX */
102 /* MAC_TODO : Color tables on Mac. */
103 #undef COLOR_TABLE_SUPPORT
105 /* Mac equivalent of XImage. */
106 typedef Pixmap XImagePtr
;
107 #define ZPixmap 0 /* arbitrary */
108 typedef struct mac_bitmap_record Bitmap_Record
;
110 typedef XImagePtr XImagePtr_or_DC
;
111 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
113 #define PNG_BG_COLOR_SHIFT 8
115 #define RGB_PIXEL_COLOR unsigned long
117 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
118 #define x_defined_color mac_defined_color
119 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
120 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
121 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
126 /* Search path for bitmap files. */
128 Lisp_Object Vx_bitmap_file_path
;
131 static void x_disable_image
P_ ((struct frame
*, struct image
*));
132 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
135 static void init_color_table
P_ ((void));
136 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
137 #ifdef COLOR_TABLE_SUPPORT
138 static void free_color_table
P_ ((void));
139 static unsigned long *colors_in_color_table
P_ ((int *n
));
140 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
143 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
144 id, which is just an int that this section returns. Bitmaps are
145 reference counted so they can be shared among frames.
147 Bitmap indices are guaranteed to be > 0, so a negative number can
148 be used to indicate no bitmap.
150 If you use x_create_bitmap_from_data, then you must keep track of
151 the bitmaps yourself. That is, creating a bitmap from the same
152 data more than once will not be caught. */
157 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
158 Display
*display
; /* not used */
160 int x
, y
; /* not used */
161 unsigned int width
, height
; /* not used */
162 unsigned long plane_mask
; /* not used */
163 int format
; /* not used */
166 xassert (x
== 0 && y
== 0);
169 SetRect (&ri
, 0, 0, width
, height
);
170 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
172 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
175 LockPixels (GetGWorldPixMap (pixmap
));
181 XPutPixel (ximage
, x
, y
, pixel
)
188 SetGWorld (ximage
, NULL
);
190 color
.red
= RED16_FROM_ULONG (pixel
);
191 color
.green
= GREEN16_FROM_ULONG (pixel
);
192 color
.blue
= BLUE16_FROM_ULONG (pixel
);
193 SetCPixel (x
, y
, &color
);
197 XGetPixel (ximage
, x
, y
)
203 SetGWorld (ximage
, NULL
);
205 GetCPixel (x
, y
, &color
);
206 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
213 UnlockPixels (GetGWorldPixMap (ximg
));
218 /* Functions to access the contents of a bitmap, given an id. */
221 x_bitmap_height (f
, id
)
225 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
229 x_bitmap_width (f
, id
)
233 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
236 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
238 x_bitmap_pixmap (f
, id
)
242 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
246 #ifdef HAVE_X_WINDOWS
248 x_bitmap_mask (f
, id
)
252 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
256 /* Allocate a new bitmap record. Returns index of new record. */
259 x_allocate_bitmap_record (f
)
262 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
265 if (dpyinfo
->bitmaps
== NULL
)
267 dpyinfo
->bitmaps_size
= 10;
269 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
270 dpyinfo
->bitmaps_last
= 1;
274 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
275 return ++dpyinfo
->bitmaps_last
;
277 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
278 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
281 dpyinfo
->bitmaps_size
*= 2;
283 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
284 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
285 return ++dpyinfo
->bitmaps_last
;
288 /* Add one reference to the reference count of the bitmap with id ID. */
291 x_reference_bitmap (f
, id
)
295 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
298 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
301 x_create_bitmap_from_data (f
, bits
, width
, height
)
304 unsigned int width
, height
;
306 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
309 #ifdef HAVE_X_WINDOWS
311 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
312 bits
, width
, height
);
315 #endif /* HAVE_X_WINDOWS */
319 bitmap
= CreateBitmap (width
, height
,
320 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
321 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
325 #endif /* HAVE_NTGUI */
328 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
333 id
= x_allocate_bitmap_record (f
);
335 dpyinfo
->bitmaps
[id
- 1].bitmap_data
= (char *) xmalloc (height
* width
);
336 if (! dpyinfo
->bitmaps
[id
- 1].bitmap_data
)
338 bcopy (bits
, dpyinfo
->bitmaps
[id
- 1].bitmap_data
, height
* width
);
341 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
342 dpyinfo
->bitmaps
[id
- 1].height
= height
;
343 dpyinfo
->bitmaps
[id
- 1].width
= width
;
344 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
346 #ifdef HAVE_X_WINDOWS
347 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
348 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
349 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
350 #endif /* HAVE_X_WINDOWS */
353 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
354 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
355 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
356 #endif /* HAVE_NTGUI */
361 /* Create bitmap from file FILE for frame F. */
364 x_create_bitmap_from_file (f
, file
)
369 return -1; /* MAC_TODO : bitmap support */
373 return -1; /* W32_TODO : bitmap support */
374 #endif /* HAVE_NTGUI */
376 #ifdef HAVE_X_WINDOWS
377 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
378 unsigned int width
, height
;
380 int xhot
, yhot
, result
, id
;
385 /* Look for an existing bitmap with the same name. */
386 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
388 if (dpyinfo
->bitmaps
[id
].refcount
389 && dpyinfo
->bitmaps
[id
].file
390 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
392 ++dpyinfo
->bitmaps
[id
].refcount
;
397 /* Search bitmap-file-path for the file, if appropriate. */
398 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
403 filename
= (char *) SDATA (found
);
405 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
406 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
407 if (result
!= BitmapSuccess
)
410 id
= x_allocate_bitmap_record (f
);
411 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
412 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
413 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
414 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
415 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
416 dpyinfo
->bitmaps
[id
- 1].height
= height
;
417 dpyinfo
->bitmaps
[id
- 1].width
= width
;
418 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
421 #endif /* HAVE_X_WINDOWS */
427 Free_Bitmap_Record (dpyinfo
, bm
)
428 Display_Info
*dpyinfo
;
431 #ifdef HAVE_X_WINDOWS
432 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
434 XFreePixmap (dpyinfo
->display
, bm
->mask
);
435 #endif /* HAVE_X_WINDOWS */
438 DeleteObject (bm
->pixmap
);
439 #endif /* HAVE_NTGUI */
442 xfree (bm
->bitmap_data
); /* Added ++kfs */
443 bm
->bitmap_data
= NULL
;
453 /* Remove reference to bitmap with id number ID. */
456 x_destroy_bitmap (f
, id
)
460 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
464 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
466 if (--bm
->refcount
== 0)
469 Free_Bitmap_Record (dpyinfo
, bm
);
475 /* Free all the bitmaps for the display specified by DPYINFO. */
478 x_destroy_all_bitmaps (dpyinfo
)
479 Display_Info
*dpyinfo
;
482 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
484 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
485 if (bm
->refcount
> 0)
486 Free_Bitmap_Record (dpyinfo
, bm
);
488 dpyinfo
->bitmaps_last
= 0;
492 #ifdef HAVE_X_WINDOWS
494 /* Useful functions defined in the section
495 `Image type independent image structures' below. */
497 static unsigned long four_corners_best
P_ ((XImagePtr ximg
, unsigned long width
,
498 unsigned long height
));
500 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
501 int depth
, XImagePtr
*ximg
,
504 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
507 /* Create a mask of a bitmap. Note is this not a perfect mask.
508 It's nicer with some borders in this context */
511 x_create_bitmap_mask (f
, id
)
516 XImagePtr ximg
, mask_img
;
517 unsigned long width
, height
;
520 unsigned long x
, y
, xp
, xm
, yp
, ym
;
523 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
528 pixmap
= x_bitmap_pixmap (f
, id
);
529 width
= x_bitmap_width (f
, id
);
530 height
= x_bitmap_height (f
, id
);
533 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
542 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
547 XDestroyImage (ximg
);
551 bg
= four_corners_best (ximg
, width
, height
);
553 for (y
= 0; y
< ximg
->height
; ++y
)
555 for (x
= 0; x
< ximg
->width
; ++x
)
557 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
558 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
559 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
560 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
561 if (XGetPixel (ximg
, x
, y
) == bg
562 && XGetPixel (ximg
, x
, yp
) == bg
563 && XGetPixel (ximg
, x
, ym
) == bg
564 && XGetPixel (ximg
, xp
, y
) == bg
565 && XGetPixel (ximg
, xp
, yp
) == bg
566 && XGetPixel (ximg
, xp
, ym
) == bg
567 && XGetPixel (ximg
, xm
, y
) == bg
568 && XGetPixel (ximg
, xm
, yp
) == bg
569 && XGetPixel (ximg
, xm
, ym
) == bg
)
570 XPutPixel (mask_img
, x
, y
, 0);
572 XPutPixel (mask_img
, x
, y
, 1);
576 xassert (interrupt_input_blocked
);
577 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
578 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
580 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
582 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
583 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
585 XDestroyImage (ximg
);
586 x_destroy_x_image (mask_img
);
591 #endif /* HAVE_X_WINDOWS */
594 /***********************************************************************
596 ***********************************************************************/
598 /* Value is the number of elements of vector VECTOR. */
600 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
602 /* List of supported image types. Use define_image_type to add new
603 types. Use lookup_image_type to find a type for a given symbol. */
605 static struct image_type
*image_types
;
607 /* The symbol `xbm' which is used as the type symbol for XBM images. */
613 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
614 extern Lisp_Object QCdata
, QCtype
;
615 Lisp_Object QCascent
, QCmargin
, QCrelief
;
616 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
617 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
621 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
624 /* Time in seconds after which images should be removed from the cache
627 Lisp_Object Vimage_cache_eviction_delay
;
629 /* Function prototypes. */
631 static void define_image_type
P_ ((struct image_type
*type
));
632 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
633 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
634 static void x_laplace
P_ ((struct frame
*, struct image
*));
635 static void x_emboss
P_ ((struct frame
*, struct image
*));
636 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
640 /* Define a new image type from TYPE. This adds a copy of TYPE to
641 image_types and adds the symbol *TYPE->type to Vimage_types. */
644 define_image_type (type
)
645 struct image_type
*type
;
647 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
648 The initialized data segment is read-only. */
649 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
650 bcopy (type
, p
, sizeof *p
);
651 p
->next
= image_types
;
653 Vimage_types
= Fcons (*p
->type
, Vimage_types
);
657 /* Look up image type SYMBOL, and return a pointer to its image_type
658 structure. Value is null if SYMBOL is not a known image type. */
660 static INLINE
struct image_type
*
661 lookup_image_type (symbol
)
664 struct image_type
*type
;
666 for (type
= image_types
; type
; type
= type
->next
)
667 if (EQ (symbol
, *type
->type
))
674 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
675 valid image specification is a list whose car is the symbol
676 `image', and whose rest is a property list. The property list must
677 contain a value for key `:type'. That value must be the name of a
678 supported image type. The rest of the property list depends on the
682 valid_image_p (object
)
691 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
692 if (EQ (XCAR (tem
), QCtype
))
695 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
697 struct image_type
*type
;
698 type
= lookup_image_type (XCAR (tem
));
700 valid_p
= type
->valid_p (object
);
711 /* Log error message with format string FORMAT and argument ARG.
712 Signaling an error, e.g. when an image cannot be loaded, is not a
713 good idea because this would interrupt redisplay, and the error
714 message display would lead to another redisplay. This function
715 therefore simply displays a message. */
718 image_error (format
, arg1
, arg2
)
720 Lisp_Object arg1
, arg2
;
722 add_to_log (format
, arg1
, arg2
);
727 /***********************************************************************
729 ***********************************************************************/
731 enum image_value_type
733 IMAGE_DONT_CHECK_VALUE_TYPE
,
735 IMAGE_STRING_OR_NIL_VALUE
,
737 IMAGE_POSITIVE_INTEGER_VALUE
,
738 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
739 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
742 IMAGE_FUNCTION_VALUE
,
747 /* Structure used when parsing image specifications. */
751 /* Name of keyword. */
754 /* The type of value allowed. */
755 enum image_value_type type
;
757 /* Non-zero means key must be present. */
760 /* Used to recognize duplicate keywords in a property list. */
763 /* The value that was found. */
768 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
770 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
773 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
774 has the format (image KEYWORD VALUE ...). One of the keyword/
775 value pairs must be `:type TYPE'. KEYWORDS is a vector of
776 image_keywords structures of size NKEYWORDS describing other
777 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
780 parse_image_spec (spec
, keywords
, nkeywords
, type
)
782 struct image_keyword
*keywords
;
793 while (CONSP (plist
))
795 Lisp_Object key
, value
;
797 /* First element of a pair must be a symbol. */
799 plist
= XCDR (plist
);
803 /* There must follow a value. */
806 value
= XCAR (plist
);
807 plist
= XCDR (plist
);
809 /* Find key in KEYWORDS. Error if not found. */
810 for (i
= 0; i
< nkeywords
; ++i
)
811 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
817 /* Record that we recognized the keyword. If a keywords
818 was found more than once, it's an error. */
819 keywords
[i
].value
= value
;
822 if (keywords
[i
].count
> 1)
825 /* Check type of value against allowed type. */
826 switch (keywords
[i
].type
)
828 case IMAGE_STRING_VALUE
:
829 if (!STRINGP (value
))
833 case IMAGE_STRING_OR_NIL_VALUE
:
834 if (!STRINGP (value
) && !NILP (value
))
838 case IMAGE_SYMBOL_VALUE
:
839 if (!SYMBOLP (value
))
843 case IMAGE_POSITIVE_INTEGER_VALUE
:
844 if (!INTEGERP (value
) || XINT (value
) <= 0)
848 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
849 if (INTEGERP (value
) && XINT (value
) >= 0)
852 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
853 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
857 case IMAGE_ASCENT_VALUE
:
858 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
860 else if (INTEGERP (value
)
862 && XINT (value
) <= 100)
866 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
867 if (!INTEGERP (value
) || XINT (value
) < 0)
871 case IMAGE_DONT_CHECK_VALUE_TYPE
:
874 case IMAGE_FUNCTION_VALUE
:
875 value
= indirect_function (value
);
878 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
882 case IMAGE_NUMBER_VALUE
:
883 if (!INTEGERP (value
) && !FLOATP (value
))
887 case IMAGE_INTEGER_VALUE
:
888 if (!INTEGERP (value
))
892 case IMAGE_BOOL_VALUE
:
893 if (!NILP (value
) && !EQ (value
, Qt
))
902 if (EQ (key
, QCtype
) && !EQ (type
, value
))
906 /* Check that all mandatory fields are present. */
907 for (i
= 0; i
< nkeywords
; ++i
)
908 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
915 /* Return the value of KEY in image specification SPEC. Value is nil
916 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
917 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
920 image_spec_value (spec
, key
, found
)
921 Lisp_Object spec
, key
;
926 xassert (valid_image_p (spec
));
928 for (tail
= XCDR (spec
);
929 CONSP (tail
) && CONSP (XCDR (tail
));
930 tail
= XCDR (XCDR (tail
)))
932 if (EQ (XCAR (tail
), key
))
936 return XCAR (XCDR (tail
));
946 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
947 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
948 PIXELS non-nil means return the size in pixels, otherwise return the
949 size in canonical character units.
950 FRAME is the frame on which the image will be displayed. FRAME nil
951 or omitted means use the selected frame. */)
952 (spec
, pixels
, frame
)
953 Lisp_Object spec
, pixels
, frame
;
958 if (valid_image_p (spec
))
960 struct frame
*f
= check_x_frame (frame
);
961 int id
= lookup_image (f
, spec
);
962 struct image
*img
= IMAGE_FROM_ID (f
, id
);
963 int width
= img
->width
+ 2 * img
->hmargin
;
964 int height
= img
->height
+ 2 * img
->vmargin
;
967 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
968 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
970 size
= Fcons (make_number (width
), make_number (height
));
973 error ("Invalid image specification");
979 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
980 doc
: /* Return t if image SPEC has a mask bitmap.
981 FRAME is the frame on which the image will be displayed. FRAME nil
982 or omitted means use the selected frame. */)
984 Lisp_Object spec
, frame
;
989 if (valid_image_p (spec
))
991 struct frame
*f
= check_x_frame (frame
);
992 int id
= lookup_image (f
, spec
);
993 struct image
*img
= IMAGE_FROM_ID (f
, id
);
998 error ("Invalid image specification");
1004 /***********************************************************************
1005 Image type independent image structures
1006 ***********************************************************************/
1008 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1009 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1012 /* Allocate and return a new image structure for image specification
1013 SPEC. SPEC has a hash value of HASH. */
1015 static struct image
*
1016 make_image (spec
, hash
)
1020 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1022 xassert (valid_image_p (spec
));
1023 bzero (img
, sizeof *img
);
1024 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1025 xassert (img
->type
!= NULL
);
1027 img
->data
.lisp_val
= Qnil
;
1028 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1034 /* Free image IMG which was used on frame F, including its resources. */
1043 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1045 /* Remove IMG from the hash table of its cache. */
1047 img
->prev
->next
= img
->next
;
1049 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1052 img
->next
->prev
= img
->prev
;
1054 c
->images
[img
->id
] = NULL
;
1056 /* Free resources, then free IMG. */
1057 img
->type
->free (f
, img
);
1063 /* Prepare image IMG for display on frame F. Must be called before
1064 drawing an image. */
1067 prepare_image_for_display (f
, img
)
1073 /* We're about to display IMG, so set its timestamp to `now'. */
1075 img
->timestamp
= EMACS_SECS (t
);
1077 /* If IMG doesn't have a pixmap yet, load it now, using the image
1078 type dependent loader function. */
1079 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1080 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1084 /* Value is the number of pixels for the ascent of image IMG when
1085 drawn in face FACE. */
1088 image_ascent (img
, face
)
1092 int height
= img
->height
+ img
->vmargin
;
1095 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1100 /* W32 specific version. Why?. ++kfs */
1101 ascent
= height
/ 2 - (FONT_DESCENT(face
->font
)
1102 - FONT_BASE(face
->font
)) / 2;
1104 /* This expression is arranged so that if the image can't be
1105 exactly centered, it will be moved slightly up. This is
1106 because a typical font is `top-heavy' (due to the presence
1107 uppercase letters), so the image placement should err towards
1108 being top-heavy too. It also just generally looks better. */
1109 ascent
= (height
+ face
->font
->ascent
- face
->font
->descent
+ 1) / 2;
1110 #endif /* HAVE_NTGUI */
1113 ascent
= height
/ 2;
1116 ascent
= (int) (height
* img
->ascent
/ 100.0);
1122 /* Image background colors. */
1124 /* Find the "best" corner color of a bitmap.
1125 On W32, XIMG is assumed to a device context with the bitmap selected. */
1127 static RGB_PIXEL_COLOR
1128 four_corners_best (ximg
, width
, height
)
1129 XImagePtr_or_DC ximg
;
1130 unsigned long width
, height
;
1132 RGB_PIXEL_COLOR corners
[4], best
;
1135 /* Get the colors at the corners of ximg. */
1136 corners
[0] = GET_PIXEL (ximg
, 0, 0);
1137 corners
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1138 corners
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1139 corners
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1141 /* Choose the most frequently found color as background. */
1142 for (i
= best_count
= 0; i
< 4; ++i
)
1146 for (j
= n
= 0; j
< 4; ++j
)
1147 if (corners
[i
] == corners
[j
])
1151 best
= corners
[i
], best_count
= n
;
1157 /* Portability macros */
1161 #define Destroy_Image(img_dc, prev) \
1162 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1164 #define Free_Pixmap(display, pixmap) \
1165 DeleteObject (pixmap)
1169 #define Destroy_Image(ximg, dummy) \
1170 XDestroyImage (ximg)
1172 #define Free_Pixmap(display, pixmap) \
1173 XFreePixmap (display, pixmap)
1175 #endif /* HAVE_NTGUI */
1178 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1179 it is guessed heuristically. If non-zero, XIMG is an existing
1180 XImage object (or device context with the image selected on W32) to
1181 use for the heuristic. */
1184 image_background (img
, f
, ximg
)
1187 XImagePtr_or_DC ximg
;
1189 if (! img
->background_valid
)
1190 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1192 int free_ximg
= !ximg
;
1195 #endif /* HAVE_NTGUI */
1200 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1201 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1203 HDC frame_dc
= get_frame_dc (f
);
1204 ximg
= CreateCompatibleDC (frame_dc
);
1205 release_frame_dc (f
, frame_dc
);
1206 prev
= SelectObject (ximg
, img
->pixmap
);
1207 #endif /* !HAVE_NTGUI */
1210 img
->background
= four_corners_best (ximg
, img
->width
, img
->height
);
1213 Destroy_Image (ximg
, prev
);
1215 img
->background_valid
= 1;
1218 return img
->background
;
1221 /* Return the `background_transparent' field of IMG. If IMG doesn't
1222 have one yet, it is guessed heuristically. If non-zero, MASK is an
1223 existing XImage object to use for the heuristic. */
1226 image_background_transparent (img
, f
, mask
)
1229 XImagePtr_or_DC mask
;
1231 if (! img
->background_transparent_valid
)
1232 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1236 int free_mask
= !mask
;
1239 #endif /* HAVE_NTGUI */
1244 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1245 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1247 HDC frame_dc
= get_frame_dc (f
);
1248 mask
= CreateCompatibleDC (frame_dc
);
1249 release_frame_dc (f
, frame_dc
);
1250 prev
= SelectObject (mask
, img
->mask
);
1251 #endif /* HAVE_NTGUI */
1254 img
->background_transparent
1255 = (four_corners_best (mask
, img
->width
, img
->height
) == PIX_MASK_RETAIN (f
));
1258 Destroy_Image (mask
, prev
);
1261 img
->background_transparent
= 0;
1263 img
->background_transparent_valid
= 1;
1266 return img
->background_transparent
;
1270 /***********************************************************************
1271 Helper functions for X image types
1272 ***********************************************************************/
1274 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1276 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1277 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1279 Lisp_Object color_name
,
1280 unsigned long dflt
));
1283 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1284 free the pixmap if any. MASK_P non-zero means clear the mask
1285 pixmap if any. COLORS_P non-zero means free colors allocated for
1286 the image, if any. */
1289 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1292 int pixmap_p
, mask_p
, colors_p
;
1294 if (pixmap_p
&& img
->pixmap
)
1296 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1297 img
->pixmap
= NO_PIXMAP
;
1298 img
->background_valid
= 0;
1301 if (mask_p
&& img
->mask
)
1303 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1304 img
->mask
= NO_PIXMAP
;
1305 img
->background_transparent_valid
= 0;
1308 if (colors_p
&& img
->ncolors
)
1310 /* MAC_TODO: color table support. */
1311 /* W32_TODO: color table support. */
1312 #ifdef HAVE_X_WINDOWS
1313 x_free_colors (f
, img
->colors
, img
->ncolors
);
1314 #endif /* HAVE_X_WINDOWS */
1315 xfree (img
->colors
);
1321 /* Free X resources of image IMG which is used on frame F. */
1324 x_clear_image (f
, img
)
1329 x_clear_image_1 (f
, img
, 1, 1, 1);
1334 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1335 cannot be allocated, use DFLT. Add a newly allocated color to
1336 IMG->colors, so that it can be freed again. Value is the pixel
1339 static unsigned long
1340 x_alloc_image_color (f
, img
, color_name
, dflt
)
1343 Lisp_Object color_name
;
1347 unsigned long result
;
1349 xassert (STRINGP (color_name
));
1351 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1353 /* This isn't called frequently so we get away with simply
1354 reallocating the color vector to the needed size, here. */
1357 (unsigned long *) xrealloc (img
->colors
,
1358 img
->ncolors
* sizeof *img
->colors
);
1359 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1360 result
= color
.pixel
;
1370 /***********************************************************************
1372 ***********************************************************************/
1374 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1375 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1377 /* Return a new, initialized image cache that is allocated from the
1378 heap. Call free_image_cache to free an image cache. */
1380 struct image_cache
*
1383 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1386 bzero (c
, sizeof *c
);
1388 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1389 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1390 c
->buckets
= (struct image
**) xmalloc (size
);
1391 bzero (c
->buckets
, size
);
1396 /* Free image cache of frame F. Be aware that X frames share images
1400 free_image_cache (f
)
1403 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1408 /* Cache should not be referenced by any frame when freed. */
1409 xassert (c
->refcount
== 0);
1411 for (i
= 0; i
< c
->used
; ++i
)
1412 free_image (f
, c
->images
[i
]);
1416 FRAME_X_IMAGE_CACHE (f
) = NULL
;
1421 /* Clear image cache of frame F. FORCE_P non-zero means free all
1422 images. FORCE_P zero means clear only images that haven't been
1423 displayed for some time. Should be called from time to time to
1424 reduce the number of loaded images. If image-eviction-seconds is
1425 non-nil, this frees images in the cache which weren't displayed for
1426 at least that many seconds. */
1429 clear_image_cache (f
, force_p
)
1433 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1435 if (c
&& INTEGERP (Vimage_cache_eviction_delay
))
1442 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1444 /* Block input so that we won't be interrupted by a SIGIO
1445 while being in an inconsistent state. */
1448 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1450 struct image
*img
= c
->images
[i
];
1452 && (force_p
|| img
->timestamp
< old
))
1454 free_image (f
, img
);
1459 /* We may be clearing the image cache because, for example,
1460 Emacs was iconified for a longer period of time. In that
1461 case, current matrices may still contain references to
1462 images freed above. So, clear these matrices. */
1465 Lisp_Object tail
, frame
;
1467 FOR_EACH_FRAME (tail
, frame
)
1469 struct frame
*f
= XFRAME (frame
);
1470 if (FRAME_WINDOW_P (f
)
1471 && FRAME_X_IMAGE_CACHE (f
) == c
)
1472 clear_current_matrices (f
);
1475 ++windows_or_buffers_changed
;
1483 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1485 doc
: /* Clear the image cache of FRAME.
1486 FRAME nil or omitted means use the selected frame.
1487 FRAME t means clear the image caches of all frames. */)
1495 FOR_EACH_FRAME (tail
, frame
)
1496 if (FRAME_WINDOW_P (XFRAME (frame
)))
1497 clear_image_cache (XFRAME (frame
), 1);
1500 clear_image_cache (check_x_frame (frame
), 1);
1506 /* Compute masks and transform image IMG on frame F, as specified
1507 by the image's specification, */
1510 postprocess_image (f
, img
)
1514 /* Manipulation of the image's mask. */
1517 Lisp_Object conversion
, spec
;
1522 /* `:heuristic-mask t'
1524 means build a mask heuristically.
1525 `:heuristic-mask (R G B)'
1526 `:mask (heuristic (R G B))'
1527 means build a mask from color (R G B) in the
1530 means remove a mask, if any. */
1532 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1534 x_build_heuristic_mask (f
, img
, mask
);
1539 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1541 if (EQ (mask
, Qheuristic
))
1542 x_build_heuristic_mask (f
, img
, Qt
);
1543 else if (CONSP (mask
)
1544 && EQ (XCAR (mask
), Qheuristic
))
1546 if (CONSP (XCDR (mask
)))
1547 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1549 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1551 else if (NILP (mask
) && found_p
&& img
->mask
)
1553 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1554 img
->mask
= NO_PIXMAP
;
1559 /* Should we apply an image transformation algorithm? */
1560 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1561 if (EQ (conversion
, Qdisabled
))
1562 x_disable_image (f
, img
);
1563 else if (EQ (conversion
, Qlaplace
))
1565 else if (EQ (conversion
, Qemboss
))
1567 else if (CONSP (conversion
)
1568 && EQ (XCAR (conversion
), Qedge_detection
))
1571 tem
= XCDR (conversion
);
1573 x_edge_detection (f
, img
,
1574 Fplist_get (tem
, QCmatrix
),
1575 Fplist_get (tem
, QCcolor_adjustment
));
1581 /* Return the id of image with Lisp specification SPEC on frame F.
1582 SPEC must be a valid Lisp image specification (see valid_image_p). */
1585 lookup_image (f
, spec
)
1589 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1593 struct gcpro gcpro1
;
1596 /* F must be a window-system frame, and SPEC must be a valid image
1598 xassert (FRAME_WINDOW_P (f
));
1599 xassert (valid_image_p (spec
));
1603 /* Look up SPEC in the hash table of the image cache. */
1604 hash
= sxhash (spec
, 0);
1605 i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1607 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1608 if (img
->hash
== hash
&& !NILP (Fequal (img
->spec
, spec
)))
1611 /* If not found, create a new image and cache it. */
1614 extern Lisp_Object Qpostscript
;
1617 img
= make_image (spec
, hash
);
1618 cache_image (f
, img
);
1619 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1621 /* If we can't load the image, and we don't have a width and
1622 height, use some arbitrary width and height so that we can
1623 draw a rectangle for it. */
1624 if (img
->load_failed_p
)
1628 value
= image_spec_value (spec
, QCwidth
, NULL
);
1629 img
->width
= (INTEGERP (value
)
1630 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
1631 value
= image_spec_value (spec
, QCheight
, NULL
);
1632 img
->height
= (INTEGERP (value
)
1633 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
1637 /* Handle image type independent image attributes
1638 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1639 `:background COLOR'. */
1640 Lisp_Object ascent
, margin
, relief
, bg
;
1642 ascent
= image_spec_value (spec
, QCascent
, NULL
);
1643 if (INTEGERP (ascent
))
1644 img
->ascent
= XFASTINT (ascent
);
1645 else if (EQ (ascent
, Qcenter
))
1646 img
->ascent
= CENTERED_IMAGE_ASCENT
;
1648 margin
= image_spec_value (spec
, QCmargin
, NULL
);
1649 if (INTEGERP (margin
) && XINT (margin
) >= 0)
1650 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
1651 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
1652 && INTEGERP (XCDR (margin
)))
1654 if (XINT (XCAR (margin
)) > 0)
1655 img
->hmargin
= XFASTINT (XCAR (margin
));
1656 if (XINT (XCDR (margin
)) > 0)
1657 img
->vmargin
= XFASTINT (XCDR (margin
));
1660 relief
= image_spec_value (spec
, QCrelief
, NULL
);
1661 if (INTEGERP (relief
))
1663 img
->relief
= XINT (relief
);
1664 img
->hmargin
+= abs (img
->relief
);
1665 img
->vmargin
+= abs (img
->relief
);
1668 if (! img
->background_valid
)
1670 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
1674 = x_alloc_image_color (f
, img
, bg
,
1675 FRAME_BACKGROUND_PIXEL (f
));
1676 img
->background_valid
= 1;
1680 /* Do image transformations and compute masks, unless we
1681 don't have the image yet. */
1682 if (!EQ (*img
->type
->type
, Qpostscript
))
1683 postprocess_image (f
, img
);
1689 /* We're using IMG, so set its timestamp to `now'. */
1690 EMACS_GET_TIME (now
);
1691 img
->timestamp
= EMACS_SECS (now
);
1695 /* Value is the image id. */
1700 /* Cache image IMG in the image cache of frame F. */
1703 cache_image (f
, img
)
1707 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1710 /* Find a free slot in c->images. */
1711 for (i
= 0; i
< c
->used
; ++i
)
1712 if (c
->images
[i
] == NULL
)
1715 /* If no free slot found, maybe enlarge c->images. */
1716 if (i
== c
->used
&& c
->used
== c
->size
)
1719 c
->images
= (struct image
**) xrealloc (c
->images
,
1720 c
->size
* sizeof *c
->images
);
1723 /* Add IMG to c->images, and assign IMG an id. */
1729 /* Add IMG to the cache's hash table. */
1730 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1731 img
->next
= c
->buckets
[i
];
1733 img
->next
->prev
= img
;
1735 c
->buckets
[i
] = img
;
1739 /* Call FN on every image in the image cache of frame F. Used to mark
1740 Lisp Objects in the image cache. */
1743 forall_images_in_image_cache (f
, fn
)
1745 void (*fn
) P_ ((struct image
*img
));
1747 if (FRAME_LIVE_P (f
) && FRAME_WINDOW_P (f
))
1749 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
1753 for (i
= 0; i
< c
->used
; ++i
)
1762 /***********************************************************************
1763 X / MAC / W32 support code
1764 ***********************************************************************/
1768 /* Macro for defining functions that will be loaded from image DLLs. */
1769 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1771 /* Macro for loading those image functions from the library. */
1772 #define LOAD_IMGLIB_FN(lib,func) { \
1773 fn_##func = (void *) GetProcAddress (lib, #func); \
1774 if (!fn_##func) return 0; \
1777 #endif /* HAVE_NTGUI */
1779 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
1780 XImagePtr
*, Pixmap
*));
1781 static void x_destroy_x_image
P_ ((XImagePtr
));
1782 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
1785 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1786 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1787 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1788 via xmalloc. Print error messages via image_error if an error
1789 occurs. Value is non-zero if successful.
1791 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1792 should indicate the bit depth of the image. */
1795 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
1797 int width
, height
, depth
;
1801 #ifdef HAVE_X_WINDOWS
1802 Display
*display
= FRAME_X_DISPLAY (f
);
1803 Window window
= FRAME_X_WINDOW (f
);
1804 Screen
*screen
= FRAME_X_SCREEN (f
);
1806 xassert (interrupt_input_blocked
);
1809 depth
= DefaultDepthOfScreen (screen
);
1810 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
1811 depth
, ZPixmap
, 0, NULL
, width
, height
,
1812 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
1815 image_error ("Unable to allocate X image", Qnil
, Qnil
);
1819 /* Allocate image raster. */
1820 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
1822 /* Allocate a pixmap of the same size. */
1823 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1824 if (*pixmap
== NO_PIXMAP
)
1826 x_destroy_x_image (*ximg
);
1828 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1833 #endif /* HAVE_X_WINDOWS */
1837 BITMAPINFOHEADER
*header
;
1839 int scanline_width_bits
;
1841 int palette_colors
= 0;
1846 if (depth
!= 1 && depth
!= 4 && depth
!= 8
1847 && depth
!= 16 && depth
!= 24 && depth
!= 32)
1849 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
1853 scanline_width_bits
= width
* depth
;
1854 remainder
= scanline_width_bits
% 32;
1857 scanline_width_bits
+= 32 - remainder
;
1859 /* Bitmaps with a depth less than 16 need a palette. */
1860 /* BITMAPINFO structure already contains the first RGBQUAD. */
1862 palette_colors
= 1 << depth
- 1;
1864 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
1867 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
1871 header
= &((*ximg
)->info
.bmiHeader
);
1872 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
1873 header
->biSize
= sizeof (*header
);
1874 header
->biWidth
= width
;
1875 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
1876 header
->biPlanes
= 1;
1877 header
->biBitCount
= depth
;
1878 header
->biCompression
= BI_RGB
;
1879 header
->biClrUsed
= palette_colors
;
1881 /* TODO: fill in palette. */
1884 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
1885 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
1886 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
1887 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
1888 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
1889 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
1890 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
1891 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
1894 hdc
= get_frame_dc (f
);
1896 /* Create a DIBSection and raster array for the bitmap,
1897 and store its handle in *pixmap. */
1898 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
1899 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
1900 &((*ximg
)->data
), NULL
, 0);
1902 /* Realize display palette and garbage all frames. */
1903 release_frame_dc (f
, hdc
);
1905 if (*pixmap
== NULL
)
1907 DWORD err
= GetLastError();
1908 Lisp_Object errcode
;
1909 /* All system errors are < 10000, so the following is safe. */
1910 XSETINT (errcode
, (int) err
);
1911 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
1912 x_destroy_x_image (*ximg
);
1918 #endif /* HAVE_NTGUI */
1921 Display
*display
= FRAME_X_DISPLAY (f
);
1922 Window window
= FRAME_X_WINDOW (f
);
1924 xassert (interrupt_input_blocked
);
1926 /* Allocate a pixmap of the same size. */
1927 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
1928 if (*pixmap
== NO_PIXMAP
)
1930 x_destroy_x_image (*ximg
);
1932 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
1936 LockPixels (GetGWorldPixMap (*pixmap
));
1944 /* Destroy XImage XIMG. Free XIMG->data. */
1947 x_destroy_x_image (ximg
)
1950 xassert (interrupt_input_blocked
);
1953 #ifdef HAVE_X_WINDOWS
1956 XDestroyImage (ximg
);
1957 #endif /* HAVE_X_WINDOWS */
1959 /* Data will be freed by DestroyObject. */
1962 #endif /* HAVE_NTGUI */
1964 XDestroyImage (ximg
);
1970 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
1971 are width and height of both the image and pixmap. */
1974 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
1980 #ifdef HAVE_X_WINDOWS
1983 xassert (interrupt_input_blocked
);
1984 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
1985 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
1986 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1987 #endif /* HAVE_X_WINDOWS */
1990 #if 0 /* I don't think this is necessary looking at where it is used. */
1991 HDC hdc
= get_frame_dc (f
);
1992 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
1993 release_frame_dc (f
, hdc
);
1995 #endif /* HAVE_NTGUI */
1998 xassert (ximg
== pixmap
);
2003 /***********************************************************************
2005 ***********************************************************************/
2007 static Lisp_Object x_find_image_file
P_ ((Lisp_Object
));
2008 static unsigned char *slurp_file
P_ ((char *, int *));
2011 /* Find image file FILE. Look in data-directory, then
2012 x-bitmap-file-path. Value is the full name of the file found, or
2013 nil if not found. */
2016 x_find_image_file (file
)
2019 Lisp_Object file_found
, search_path
;
2020 struct gcpro gcpro1
, gcpro2
;
2024 search_path
= Fcons (Vdata_directory
, Vx_bitmap_file_path
);
2025 GCPRO2 (file_found
, search_path
);
2027 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2028 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2040 /* Read FILE into memory. Value is a pointer to a buffer allocated
2041 with xmalloc holding FILE's contents. Value is null if an error
2042 occurred. *SIZE is set to the size of the file. */
2044 static unsigned char *
2045 slurp_file (file
, size
)
2050 unsigned char *buf
= NULL
;
2053 if (stat (file
, &st
) == 0
2054 && (fp
= fopen (file
, "rb")) != NULL
2055 && (buf
= (char *) xmalloc (st
.st_size
),
2056 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2079 /***********************************************************************
2080 MAC Image Load Functions
2081 ***********************************************************************/
2083 static int image_load_quicktime
P_ ((struct frame
*, struct image
*img
,
2086 static int image_load_quartz2d
P_ ((struct frame
*, struct image
*img
, int));
2090 find_image_fsspec (specified_file
, file
, fss
)
2091 Lisp_Object specified_file
, *file
;
2094 #if TARGET_API_MAC_CARBON
2097 Str255 mac_pathname
;
2101 *file
= x_find_image_file (specified_file
);
2102 if (!STRINGP (*file
))
2103 return fnfErr
; /* file or directory not found;
2104 incomplete pathname */
2105 /* Try to open the image file. */
2106 #if TARGET_API_MAC_CARBON
2107 err
= FSPathMakeRef (SDATA (*file
), &fsr
, NULL
);
2109 err
= FSGetCatalogInfo (&fsr
, kFSCatInfoNone
, NULL
, NULL
, fss
, NULL
);
2111 if (posix_to_mac_pathname (SDATA (*file
), mac_pathname
, MAXPATHLEN
+1) == 0)
2113 c2pstr (mac_pathname
);
2114 err
= FSMakeFSSpec (0, 0, mac_pathname
, fss
);
2120 image_load_qt_1 (f
, img
, type
, fss
, dh
)
2128 GraphicsImportComponent gi
;
2131 short draw_all_pixels
;
2132 Lisp_Object specified_bg
;
2137 err
= OpenADefaultComponent (GraphicsImporterComponentType
,
2141 image_error ("Cannot get importer component for `%s'", img
->spec
, Qnil
);
2146 /* read from file system spec */
2147 err
= GraphicsImportSetDataFile (gi
, fss
);
2150 image_error ("Cannot set fsspec to graphics importer for '%s'",
2157 /* read from data handle */
2158 err
= GraphicsImportSetDataHandle (gi
, dh
);
2161 image_error ("Cannot set data handle to graphics importer for `%s'",
2166 err
= GraphicsImportGetNaturalBounds (gi
, &rect
);
2169 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2172 width
= img
->width
= rect
.right
- rect
.left
;
2173 height
= img
->height
= rect
.bottom
- rect
.top
;
2174 err
= GraphicsImportDoesDrawAllPixels (gi
, &draw_all_pixels
);
2176 /* Don't check the error code here. It may have an undocumented
2180 image_error ("Error reading `%s'", img
->spec
, Qnil
);
2184 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2186 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2187 if (!STRINGP (specified_bg
) ||
2188 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2190 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2191 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2192 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2193 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2197 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2199 if (draw_all_pixels
!= graphicsImporterDrawsAllPixels
)
2201 SetGWorld (ximg
, NULL
);
2202 bg_color
.red
= color
.red
;
2203 bg_color
.green
= color
.green
;
2204 bg_color
.blue
= color
.blue
;
2205 RGBBackColor (&bg_color
);
2206 #if TARGET_API_MAC_CARBON
2207 GetPortBounds (ximg
, &rect
);
2210 EraseRect (&(ximg
->portRect
));
2213 GraphicsImportSetGWorld (gi
, ximg
, NULL
);
2214 GraphicsImportDraw (gi
);
2215 CloseComponent (gi
);
2217 /* Maybe fill in the background field while we have ximg handy. */
2218 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2219 IMAGE_BACKGROUND (img
, f
, ximg
);
2221 /* Put the image into the pixmap. */
2222 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2223 x_destroy_x_image (ximg
);
2227 CloseComponent (gi
);
2232 /* Load an image using the QuickTime Graphics Importer.
2233 Note: The alpha channel does not work for PNG images. */
2235 image_load_quicktime (f
, img
, type
)
2240 Lisp_Object specified_file
;
2241 Lisp_Object specified_data
;
2244 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2245 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2247 if (NILP (specified_data
))
2249 /* Read from a file */
2253 err
= find_image_fsspec (specified_file
, &file
, &fss
);
2257 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2259 image_error ("Cannot open `%s'", file
, Qnil
);
2262 return image_load_qt_1 (f
, img
, type
, &fss
, NULL
);
2266 /* Memory source! */
2270 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
2273 image_error ("Cannot allocate data handle for `%s'",
2277 success_p
= image_load_qt_1 (f
, img
, type
, NULL
, dh
);
2285 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2286 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2287 So don't use this function directly but determine at runtime
2288 whether it exists. */
2289 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType
)
2290 (CGDataProviderRef
, const float [], bool, CGColorRenderingIntent
);
2291 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider
;
2295 init_image_func_pointer ()
2297 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2299 MyCGImageCreateWithPNGDataProvider
2300 = (CGImageCreateWithPNGDataProviderProcType
)
2301 NSAddressOfSymbol (NSLookupAndBindSymbol
2302 ("_CGImageCreateWithPNGDataProvider"));
2305 MyCGImageCreateWithPNGDataProvider
= NULL
;
2310 image_load_quartz2d (f
, img
, png_p
)
2315 Lisp_Object file
, specified_file
;
2316 Lisp_Object specified_data
, specified_bg
;
2317 struct gcpro gcpro1
;
2318 CGDataProviderRef source
;
2322 XImagePtr ximg
= NULL
;
2323 CGContextRef context
;
2326 /* Open the file. */
2327 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
2328 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
2333 if (NILP (specified_data
))
2338 file
= x_find_image_file (specified_file
);
2339 if (!STRINGP (file
))
2341 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
2345 path
= CFStringCreateWithCString (NULL
, SDATA (file
),
2346 kCFStringEncodingUTF8
);
2347 url
= CFURLCreateWithFileSystemPath (NULL
, path
,
2348 kCFURLPOSIXPathStyle
, 0);
2350 source
= CGDataProviderCreateWithURL (url
);
2354 source
= CGDataProviderCreateWithData (NULL
, SDATA (specified_data
),
2355 SBYTES (specified_data
), NULL
);
2358 image
= (*MyCGImageCreateWithPNGDataProvider
) (source
, NULL
, FALSE
,
2359 kCGRenderingIntentDefault
);
2361 image
= CGImageCreateWithJPEGDataProvider (source
, NULL
, FALSE
,
2362 kCGRenderingIntentDefault
);
2364 CGDataProviderRelease (source
);
2368 image_error ("Error reading image `%s'", img
->spec
, Qnil
);
2374 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2375 if (!STRINGP (specified_bg
) ||
2376 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
2378 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
2379 color
.red
= RED16_FROM_ULONG (color
.pixel
);
2380 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
2381 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
2384 width
= img
->width
= CGImageGetWidth (image
);
2385 height
= img
->height
= CGImageGetHeight (image
);
2386 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
2388 CGImageRelease (image
);
2392 rectangle
= CGRectMake (0, 0, width
, height
);
2393 QDBeginCGContext (ximg
, &context
);
2396 CGContextSetRGBFillColor (context
, color
.red
/ 65535.0,
2397 color
.green
/ 65535.0,
2398 color
.blue
/ 65535.0, 1.0);
2399 CGContextFillRect (context
, rectangle
);
2401 CGContextDrawImage (context
, rectangle
, image
);
2402 QDEndCGContext (ximg
, &context
);
2403 CGImageRelease (image
);
2405 /* Maybe fill in the background field while we have ximg handy. */
2406 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
2407 IMAGE_BACKGROUND (img
, f
, ximg
);
2409 /* Put the image into the pixmap. */
2410 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
2411 x_destroy_x_image (ximg
);
2420 /***********************************************************************
2422 ***********************************************************************/
2424 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2425 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2426 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2427 unsigned char *, unsigned char *));
2428 static int xbm_image_p
P_ ((Lisp_Object object
));
2429 static int xbm_read_bitmap_data
P_ ((unsigned char *, unsigned char *,
2430 int *, int *, unsigned char **));
2431 static int xbm_file_p
P_ ((Lisp_Object
));
2434 /* Indices of image specification fields in xbm_format, below. */
2436 enum xbm_keyword_index
2454 /* Vector of image_keyword structures describing the format
2455 of valid XBM image specifications. */
2457 static struct image_keyword xbm_format
[XBM_LAST
] =
2459 {":type", IMAGE_SYMBOL_VALUE
, 1},
2460 {":file", IMAGE_STRING_VALUE
, 0},
2461 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2462 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2463 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2464 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2465 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2466 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2467 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2468 {":relief", IMAGE_INTEGER_VALUE
, 0},
2469 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2470 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2471 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2474 /* Structure describing the image type XBM. */
2476 static struct image_type xbm_type
=
2485 /* Tokens returned from xbm_scan. */
2494 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2495 A valid specification is a list starting with the symbol `image'
2496 The rest of the list is a property list which must contain an
2499 If the specification specifies a file to load, it must contain
2500 an entry `:file FILENAME' where FILENAME is a string.
2502 If the specification is for a bitmap loaded from memory it must
2503 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2504 WIDTH and HEIGHT are integers > 0. DATA may be:
2506 1. a string large enough to hold the bitmap data, i.e. it must
2507 have a size >= (WIDTH + 7) / 8 * HEIGHT
2509 2. a bool-vector of size >= WIDTH * HEIGHT
2511 3. a vector of strings or bool-vectors, one for each line of the
2514 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2515 may not be specified in this case because they are defined in the
2518 Both the file and data forms may contain the additional entries
2519 `:background COLOR' and `:foreground COLOR'. If not present,
2520 foreground and background of the frame on which the image is
2521 displayed is used. */
2524 xbm_image_p (object
)
2527 struct image_keyword kw
[XBM_LAST
];
2529 bcopy (xbm_format
, kw
, sizeof kw
);
2530 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2533 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2535 if (kw
[XBM_FILE
].count
)
2537 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2540 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2542 /* In-memory XBM file. */
2543 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2551 /* Entries for `:width', `:height' and `:data' must be present. */
2552 if (!kw
[XBM_WIDTH
].count
2553 || !kw
[XBM_HEIGHT
].count
2554 || !kw
[XBM_DATA
].count
)
2557 data
= kw
[XBM_DATA
].value
;
2558 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2559 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2561 /* Check type of data, and width and height against contents of
2567 /* Number of elements of the vector must be >= height. */
2568 if (XVECTOR (data
)->size
< height
)
2571 /* Each string or bool-vector in data must be large enough
2572 for one line of the image. */
2573 for (i
= 0; i
< height
; ++i
)
2575 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2580 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2583 else if (BOOL_VECTOR_P (elt
))
2585 if (XBOOL_VECTOR (elt
)->size
< width
)
2592 else if (STRINGP (data
))
2595 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2598 else if (BOOL_VECTOR_P (data
))
2600 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2611 /* Scan a bitmap file. FP is the stream to read from. Value is
2612 either an enumerator from enum xbm_token, or a character for a
2613 single-character token, or 0 at end of file. If scanning an
2614 identifier, store the lexeme of the identifier in SVAL. If
2615 scanning a number, store its value in *IVAL. */
2618 xbm_scan (s
, end
, sval
, ival
)
2619 unsigned char **s
, *end
;
2627 /* Skip white space. */
2628 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2633 else if (isdigit (c
))
2635 int value
= 0, digit
;
2637 if (c
== '0' && *s
< end
)
2640 if (c
== 'x' || c
== 'X')
2647 else if (c
>= 'a' && c
<= 'f')
2648 digit
= c
- 'a' + 10;
2649 else if (c
>= 'A' && c
<= 'F')
2650 digit
= c
- 'A' + 10;
2653 value
= 16 * value
+ digit
;
2656 else if (isdigit (c
))
2660 && (c
= *(*s
)++, isdigit (c
)))
2661 value
= 8 * value
+ c
- '0';
2668 && (c
= *(*s
)++, isdigit (c
)))
2669 value
= 10 * value
+ c
- '0';
2677 else if (isalpha (c
) || c
== '_')
2681 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2688 else if (c
== '/' && **s
== '*')
2690 /* C-style comment. */
2692 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2706 /* Create a Windows bitmap from X bitmap data. */
2708 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2710 static unsigned char swap_nibble
[16]
2711 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2712 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2713 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2714 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2716 unsigned char *bits
, *p
;
2719 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2720 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2721 bits
= (unsigned char *) alloca (height
* w2
);
2722 bzero (bits
, height
* w2
);
2723 for (i
= 0; i
< height
; i
++)
2726 for (j
= 0; j
< w1
; j
++)
2728 /* Bitswap XBM bytes to match how Windows does things. */
2729 unsigned char c
= *data
++;
2730 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2731 | (swap_nibble
[(c
>>4) & 0xf]));
2734 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2739 static void convert_mono_to_color_image (f
, img
, foreground
, background
)
2742 COLORREF foreground
, background
;
2744 HDC hdc
, old_img_dc
, new_img_dc
;
2745 HGDIOBJ old_prev
, new_prev
;
2748 hdc
= get_frame_dc (f
);
2749 old_img_dc
= CreateCompatibleDC (hdc
);
2750 new_img_dc
= CreateCompatibleDC (hdc
);
2751 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2752 release_frame_dc (f
, hdc
);
2753 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2754 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2755 SetTextColor (new_img_dc
, foreground
);
2756 SetBkColor (new_img_dc
, background
);
2758 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2761 SelectObject (old_img_dc
, old_prev
);
2762 SelectObject (new_img_dc
, new_prev
);
2763 DeleteDC (old_img_dc
);
2764 DeleteDC (new_img_dc
);
2765 DeleteObject (img
->pixmap
);
2766 if (new_pixmap
== 0)
2767 fprintf (stderr
, "Failed to convert image to color.\n");
2769 img
->pixmap
= new_pixmap
;
2772 #define XBM_BIT_SHUFFLE(b) (~(b))
2776 #define XBM_BIT_SHUFFLE(b) (b)
2778 #endif /* HAVE_NTGUI */
2782 Create_Pixmap_From_Bitmap_Data(f
, img
, data
, fg
, bg
, non_default_colors
)
2786 RGB_PIXEL_COLOR fg
, bg
;
2787 int non_default_colors
;
2791 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2793 /* If colors were specified, transfer the bitmap to a color one. */
2794 if (non_default_colors
)
2795 convert_mono_to_color_image (f
, img
, fg
, bg
);
2798 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2801 img
->width
, img
->height
,
2803 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2804 #endif /* HAVE_NTGUI */
2809 /* Replacement for XReadBitmapFileData which isn't available under old
2810 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2811 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2812 the image. Return in *DATA the bitmap data allocated with xmalloc.
2813 Value is non-zero if successful. DATA null means just test if
2814 CONTENTS looks like an in-memory XBM file. */
2817 xbm_read_bitmap_data (contents
, end
, width
, height
, data
)
2818 unsigned char *contents
, *end
;
2819 int *width
, *height
;
2820 unsigned char **data
;
2822 unsigned char *s
= contents
;
2823 char buffer
[BUFSIZ
];
2826 int bytes_per_line
, i
, nbytes
;
2832 LA1 = xbm_scan (&s, end, buffer, &value)
2834 #define expect(TOKEN) \
2835 if (LA1 != (TOKEN)) \
2840 #define expect_ident(IDENT) \
2841 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2846 *width
= *height
= -1;
2849 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2851 /* Parse defines for width, height and hot-spots. */
2855 expect_ident ("define");
2856 expect (XBM_TK_IDENT
);
2858 if (LA1
== XBM_TK_NUMBER
);
2860 char *p
= strrchr (buffer
, '_');
2861 p
= p
? p
+ 1 : buffer
;
2862 if (strcmp (p
, "width") == 0)
2864 else if (strcmp (p
, "height") == 0)
2867 expect (XBM_TK_NUMBER
);
2870 if (*width
< 0 || *height
< 0)
2872 else if (data
== NULL
)
2875 /* Parse bits. Must start with `static'. */
2876 expect_ident ("static");
2877 if (LA1
== XBM_TK_IDENT
)
2879 if (strcmp (buffer
, "unsigned") == 0)
2882 expect_ident ("char");
2884 else if (strcmp (buffer
, "short") == 0)
2888 if (*width
% 16 && *width
% 16 < 9)
2891 else if (strcmp (buffer
, "char") == 0)
2899 expect (XBM_TK_IDENT
);
2905 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
2906 nbytes
= bytes_per_line
* *height
;
2907 p
= *data
= (char *) xmalloc (nbytes
);
2911 for (i
= 0; i
< nbytes
; i
+= 2)
2914 expect (XBM_TK_NUMBER
);
2916 *p
++ = XBM_BIT_SHUFFLE (val
);
2917 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
2918 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
2920 if (LA1
== ',' || LA1
== '}')
2928 for (i
= 0; i
< nbytes
; ++i
)
2931 expect (XBM_TK_NUMBER
);
2933 *p
++ = XBM_BIT_SHUFFLE (val
);
2935 if (LA1
== ',' || LA1
== '}')
2960 /* Load XBM image IMG which will be displayed on frame F from buffer
2961 CONTENTS. END is the end of the buffer. Value is non-zero if
2965 xbm_load_image (f
, img
, contents
, end
)
2968 unsigned char *contents
, *end
;
2971 unsigned char *data
;
2974 rc
= xbm_read_bitmap_data (contents
, end
, &img
->width
, &img
->height
, &data
);
2977 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
2978 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
2979 int non_default_colors
= 0;
2982 xassert (img
->width
> 0 && img
->height
> 0);
2984 /* Get foreground and background colors, maybe allocate colors. */
2985 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
2988 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
2989 non_default_colors
= 1;
2991 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2994 background
= x_alloc_image_color (f
, img
, value
, background
);
2995 img
->background
= background
;
2996 img
->background_valid
= 1;
2997 non_default_colors
= 1;
3000 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3001 foreground
, background
,
3002 non_default_colors
);
3005 if (img
->pixmap
== NO_PIXMAP
)
3007 x_clear_image (f
, img
);
3008 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3014 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3020 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3027 return (STRINGP (data
)
3028 && xbm_read_bitmap_data (SDATA (data
),
3035 /* Fill image IMG which is used on frame F with pixmap data. Value is
3036 non-zero if successful. */
3044 Lisp_Object file_name
;
3046 xassert (xbm_image_p (img
->spec
));
3048 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3049 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3050 if (STRINGP (file_name
))
3053 unsigned char *contents
;
3055 struct gcpro gcpro1
;
3057 file
= x_find_image_file (file_name
);
3059 if (!STRINGP (file
))
3061 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3066 contents
= slurp_file (SDATA (file
), &size
);
3067 if (contents
== NULL
)
3069 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3074 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3079 struct image_keyword fmt
[XBM_LAST
];
3081 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3082 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3083 int non_default_colors
= 0;
3086 int in_memory_file_p
= 0;
3088 /* See if data looks like an in-memory XBM file. */
3089 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3090 in_memory_file_p
= xbm_file_p (data
);
3092 /* Parse the image specification. */
3093 bcopy (xbm_format
, fmt
, sizeof fmt
);
3094 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3097 /* Get specified width, and height. */
3098 if (!in_memory_file_p
)
3100 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3101 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3102 xassert (img
->width
> 0 && img
->height
> 0);
3105 /* Get foreground and background colors, maybe allocate colors. */
3106 if (fmt
[XBM_FOREGROUND
].count
3107 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3109 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3111 non_default_colors
= 1;
3114 if (fmt
[XBM_BACKGROUND
].count
3115 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3117 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3119 non_default_colors
= 1;
3122 if (in_memory_file_p
)
3123 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3132 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3134 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3135 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3137 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3139 bcopy (SDATA (line
), p
, nbytes
);
3141 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3144 else if (STRINGP (data
))
3145 bits
= SDATA (data
);
3147 bits
= XBOOL_VECTOR (data
)->data
;
3149 /* Create the pixmap. */
3151 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3152 foreground
, background
,
3153 non_default_colors
);
3158 image_error ("Unable to create pixmap for XBM image `%s'",
3160 x_clear_image (f
, img
);
3170 /***********************************************************************
3172 ***********************************************************************/
3176 static int xpm_image_p
P_ ((Lisp_Object object
));
3177 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3178 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3181 /* Indicate to xpm.h that we don't have Xlib. */
3183 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3184 #define XColor xpm_XColor
3185 #define XImage xpm_XImage
3186 #define PIXEL_ALREADY_TYPEDEFED
3187 #include "X11/xpm.h"
3191 #undef PIXEL_ALREADY_TYPEDEFED
3193 #include "X11/xpm.h"
3194 #endif /* HAVE_NTGUI */
3196 /* The symbol `xpm' identifying XPM-format images. */
3200 /* Indices of image specification fields in xpm_format, below. */
3202 enum xpm_keyword_index
3218 /* Vector of image_keyword structures describing the format
3219 of valid XPM image specifications. */
3221 static struct image_keyword xpm_format
[XPM_LAST
] =
3223 {":type", IMAGE_SYMBOL_VALUE
, 1},
3224 {":file", IMAGE_STRING_VALUE
, 0},
3225 {":data", IMAGE_STRING_VALUE
, 0},
3226 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3227 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3228 {":relief", IMAGE_INTEGER_VALUE
, 0},
3229 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3230 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3231 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3232 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3233 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3236 /* Structure describing the image type XPM. */
3238 static struct image_type xpm_type
=
3247 #ifdef HAVE_X_WINDOWS
3249 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3250 functions for allocating image colors. Our own functions handle
3251 color allocation failures more gracefully than the ones on the XPM
3254 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3255 #define ALLOC_XPM_COLORS
3257 #endif /* HAVE_X_WINDOWS */
3259 #ifdef ALLOC_XPM_COLORS
3261 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3262 static void xpm_free_color_cache
P_ ((void));
3263 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3264 static int xpm_color_bucket
P_ ((char *));
3265 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3268 /* An entry in a hash table used to cache color definitions of named
3269 colors. This cache is necessary to speed up XPM image loading in
3270 case we do color allocations ourselves. Without it, we would need
3271 a call to XParseColor per pixel in the image. */
3273 struct xpm_cached_color
3275 /* Next in collision chain. */
3276 struct xpm_cached_color
*next
;
3278 /* Color definition (RGB and pixel color). */
3285 /* The hash table used for the color cache, and its bucket vector
3288 #define XPM_COLOR_CACHE_BUCKETS 1001
3289 struct xpm_cached_color
**xpm_color_cache
;
3291 /* Initialize the color cache. */
3294 xpm_init_color_cache (f
, attrs
)
3296 XpmAttributes
*attrs
;
3298 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3299 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3300 memset (xpm_color_cache
, 0, nbytes
);
3301 init_color_table ();
3303 if (attrs
->valuemask
& XpmColorSymbols
)
3308 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3309 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3310 attrs
->colorsymbols
[i
].value
, &color
))
3312 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3314 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3319 /* Free the color cache. */
3322 xpm_free_color_cache ()
3324 struct xpm_cached_color
*p
, *next
;
3327 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3328 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3334 xfree (xpm_color_cache
);
3335 xpm_color_cache
= NULL
;
3336 free_color_table ();
3339 /* Return the bucket index for color named COLOR_NAME in the color
3343 xpm_color_bucket (color_name
)
3349 for (s
= color_name
; *s
; ++s
)
3351 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3355 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3356 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3359 static struct xpm_cached_color
*
3360 xpm_cache_color (f
, color_name
, color
, bucket
)
3367 struct xpm_cached_color
*p
;
3370 bucket
= xpm_color_bucket (color_name
);
3372 nbytes
= sizeof *p
+ strlen (color_name
);
3373 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3374 strcpy (p
->name
, color_name
);
3376 p
->next
= xpm_color_cache
[bucket
];
3377 xpm_color_cache
[bucket
] = p
;
3381 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3382 return the cached definition in *COLOR. Otherwise, make a new
3383 entry in the cache and allocate the color. Value is zero if color
3384 allocation failed. */
3387 xpm_lookup_color (f
, color_name
, color
)
3392 struct xpm_cached_color
*p
;
3393 int h
= xpm_color_bucket (color_name
);
3395 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3396 if (strcmp (p
->name
, color_name
) == 0)
3401 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3404 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3406 p
= xpm_cache_color (f
, color_name
, color
, h
);
3408 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3409 with transparency, and it's useful. */
3410 else if (strcmp ("opaque", color_name
) == 0)
3412 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3413 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3414 p
= xpm_cache_color (f
, color_name
, color
, h
);
3421 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3422 CLOSURE is a pointer to the frame on which we allocate the
3423 color. Return in *COLOR the allocated color. Value is non-zero
3427 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3434 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3438 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3439 is a pointer to the frame on which we allocate the color. Value is
3440 non-zero if successful. */
3443 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3453 #endif /* ALLOC_XPM_COLORS */
3458 /* XPM library details. */
3460 DEF_IMGLIB_FN (XpmFreeAttributes
);
3461 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3462 DEF_IMGLIB_FN (XpmReadFileToImage
);
3463 DEF_IMGLIB_FN (XImageFree
);
3467 init_xpm_functions (void)
3471 if (!(library
= LoadLibrary ("libXpm.dll")))
3474 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3475 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3476 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3477 LOAD_IMGLIB_FN (library
, XImageFree
);
3481 #endif /* HAVE_NTGUI */
3484 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3485 for XPM images. Such a list must consist of conses whose car and
3489 xpm_valid_color_symbols_p (color_symbols
)
3490 Lisp_Object color_symbols
;
3492 while (CONSP (color_symbols
))
3494 Lisp_Object sym
= XCAR (color_symbols
);
3496 || !STRINGP (XCAR (sym
))
3497 || !STRINGP (XCDR (sym
)))
3499 color_symbols
= XCDR (color_symbols
);
3502 return NILP (color_symbols
);
3506 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3509 xpm_image_p (object
)
3512 struct image_keyword fmt
[XPM_LAST
];
3513 bcopy (xpm_format
, fmt
, sizeof fmt
);
3514 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3515 /* Either `:file' or `:data' must be present. */
3516 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3517 /* Either no `:color-symbols' or it's a list of conses
3518 whose car and cdr are strings. */
3519 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3520 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3524 /* Load image IMG which will be displayed on frame F. Value is
3525 non-zero if successful. */
3533 XpmAttributes attrs
;
3534 Lisp_Object specified_file
, color_symbols
;
3537 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3538 #endif /* HAVE_NTGUI */
3540 /* Configure the XPM lib. Use the visual of frame F. Allocate
3541 close colors. Return colors allocated. */
3542 bzero (&attrs
, sizeof attrs
);
3545 attrs
.visual
= FRAME_X_VISUAL (f
);
3546 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3547 attrs
.valuemask
|= XpmVisual
;
3548 attrs
.valuemask
|= XpmColormap
;
3549 #endif /* HAVE_NTGUI */
3551 #ifdef ALLOC_XPM_COLORS
3552 /* Allocate colors with our own functions which handle
3553 failing color allocation more gracefully. */
3554 attrs
.color_closure
= f
;
3555 attrs
.alloc_color
= xpm_alloc_color
;
3556 attrs
.free_colors
= xpm_free_colors
;
3557 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3558 #else /* not ALLOC_XPM_COLORS */
3559 /* Let the XPM lib allocate colors. */
3560 attrs
.valuemask
|= XpmReturnAllocPixels
;
3561 #ifdef XpmAllocCloseColors
3562 attrs
.alloc_close_colors
= 1;
3563 attrs
.valuemask
|= XpmAllocCloseColors
;
3564 #else /* not XpmAllocCloseColors */
3565 attrs
.closeness
= 600;
3566 attrs
.valuemask
|= XpmCloseness
;
3567 #endif /* not XpmAllocCloseColors */
3568 #endif /* ALLOC_XPM_COLORS */
3570 /* If image specification contains symbolic color definitions, add
3571 these to `attrs'. */
3572 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3573 if (CONSP (color_symbols
))
3576 XpmColorSymbol
*xpm_syms
;
3579 attrs
.valuemask
|= XpmColorSymbols
;
3581 /* Count number of symbols. */
3582 attrs
.numsymbols
= 0;
3583 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3586 /* Allocate an XpmColorSymbol array. */
3587 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3588 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3589 bzero (xpm_syms
, size
);
3590 attrs
.colorsymbols
= xpm_syms
;
3592 /* Fill the color symbol array. */
3593 for (tail
= color_symbols
, i
= 0;
3595 ++i
, tail
= XCDR (tail
))
3597 Lisp_Object name
= XCAR (XCAR (tail
));
3598 Lisp_Object color
= XCDR (XCAR (tail
));
3599 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3600 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3601 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3602 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3606 /* Create a pixmap for the image, either from a file, or from a
3607 string buffer containing data in the same format as an XPM file. */
3608 #ifdef ALLOC_XPM_COLORS
3609 xpm_init_color_cache (f
, &attrs
);
3612 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3616 HDC frame_dc
= get_frame_dc (f
);
3617 hdc
= CreateCompatibleDC (frame_dc
);
3618 release_frame_dc (f
, frame_dc
);
3620 #endif /* HAVE_NTGUI */
3622 if (STRINGP (specified_file
))
3624 Lisp_Object file
= x_find_image_file (specified_file
);
3625 if (!STRINGP (file
))
3627 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3632 /* XpmReadFileToPixmap is not available in the Windows port of
3633 libxpm. But XpmReadFileToImage almost does what we want. */
3634 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3635 &xpm_image
, &xpm_mask
,
3638 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3639 SDATA (file
), &img
->pixmap
, &img
->mask
,
3641 #endif /* HAVE_NTGUI */
3645 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3647 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3648 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3649 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3650 &xpm_image
, &xpm_mask
,
3653 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3655 &img
->pixmap
, &img
->mask
,
3657 #endif /* HAVE_NTGUI */
3660 if (rc
== XpmSuccess
)
3662 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3663 img
->colors
= colors_in_color_table (&img
->ncolors
);
3664 #else /* not ALLOC_XPM_COLORS */
3668 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3669 plus some duplicate attributes. */
3670 if (xpm_image
&& xpm_image
->bitmap
)
3672 img
->pixmap
= xpm_image
->bitmap
;
3673 /* XImageFree in libXpm frees XImage struct without destroying
3674 the bitmap, which is what we want. */
3675 fn_XImageFree (xpm_image
);
3677 if (xpm_mask
&& xpm_mask
->bitmap
)
3679 /* The mask appears to be inverted compared with what we expect.
3680 TODO: invert our expectations. See other places where we
3681 have to invert bits because our idea of masks is backwards. */
3683 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3685 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3686 SelectObject (hdc
, old_obj
);
3688 img
->mask
= xpm_mask
->bitmap
;
3689 fn_XImageFree (xpm_mask
);
3694 #endif /* HAVE_NTGUI */
3696 /* Remember allocated colors. */
3697 img
->ncolors
= attrs
.nalloc_pixels
;
3698 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3699 * sizeof *img
->colors
);
3700 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3702 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3703 #ifdef DEBUG_X_COLORS
3704 register_color (img
->colors
[i
]);
3707 #endif /* not ALLOC_XPM_COLORS */
3709 img
->width
= attrs
.width
;
3710 img
->height
= attrs
.height
;
3711 xassert (img
->width
> 0 && img
->height
> 0);
3713 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3715 fn_XpmFreeAttributes (&attrs
);
3717 XpmFreeAttributes (&attrs
);
3718 #endif /* HAVE_NTGUI */
3724 #endif /* HAVE_NTGUI */
3729 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3732 case XpmFileInvalid
:
3733 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3737 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3740 case XpmColorFailed
:
3741 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3745 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3750 #ifdef ALLOC_XPM_COLORS
3751 xpm_free_color_cache ();
3753 return rc
== XpmSuccess
;
3756 #endif /* HAVE_XPM */
3759 /***********************************************************************
3761 ***********************************************************************/
3763 #ifdef COLOR_TABLE_SUPPORT
3765 /* An entry in the color table mapping an RGB color to a pixel color. */
3770 unsigned long pixel
;
3772 /* Next in color table collision list. */
3773 struct ct_color
*next
;
3776 /* The bucket vector size to use. Must be prime. */
3780 /* Value is a hash of the RGB color given by R, G, and B. */
3782 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
3784 /* The color hash table. */
3786 struct ct_color
**ct_table
;
3788 /* Number of entries in the color table. */
3790 int ct_colors_allocated
;
3792 /* Initialize the color table. */
3797 int size
= CT_SIZE
* sizeof (*ct_table
);
3798 ct_table
= (struct ct_color
**) xmalloc (size
);
3799 bzero (ct_table
, size
);
3800 ct_colors_allocated
= 0;
3804 /* Free memory associated with the color table. */
3810 struct ct_color
*p
, *next
;
3812 for (i
= 0; i
< CT_SIZE
; ++i
)
3813 for (p
= ct_table
[i
]; p
; p
= next
)
3824 /* Value is a pixel color for RGB color R, G, B on frame F. If an
3825 entry for that color already is in the color table, return the
3826 pixel color of that entry. Otherwise, allocate a new color for R,
3827 G, B, and make an entry in the color table. */
3829 static unsigned long
3830 lookup_rgb_color (f
, r
, g
, b
)
3834 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
3835 int i
= hash
% CT_SIZE
;
3837 Display_Info
*dpyinfo
;
3839 /* Handle TrueColor visuals specially, which improves performance by
3840 two orders of magnitude. Freeing colors on TrueColor visuals is
3841 a nop, and pixel colors specify RGB values directly. See also
3842 the Xlib spec, chapter 3.1. */
3843 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3844 if (dpyinfo
->red_bits
> 0)
3846 unsigned long pr
, pg
, pb
;
3848 /* Apply gamma-correction like normal color allocation does. */
3852 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
3853 gamma_correct (f
, &color
);
3854 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
3857 /* Scale down RGB values to the visual's bits per RGB, and shift
3858 them to the right position in the pixel color. Note that the
3859 original RGB values are 16-bit values, as usual in X. */
3860 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
3861 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
3862 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
3864 /* Assemble the pixel color. */
3865 return pr
| pg
| pb
;
3868 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3869 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
3875 #ifdef HAVE_X_WINDOWS
3884 cmap
= FRAME_X_COLORMAP (f
);
3885 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3888 ++ct_colors_allocated
;
3889 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3893 p
->pixel
= color
.pixel
;
3894 p
->next
= ct_table
[i
];
3898 return FRAME_FOREGROUND_PIXEL (f
);
3903 color
= PALETTERGB (r
, g
, b
);
3905 color
= RGB_TO_ULONG (r
, g
, b
);
3906 #endif /* HAVE_NTGUI */
3907 ++ct_colors_allocated
;
3908 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3913 p
->next
= ct_table
[i
];
3915 #endif /* HAVE_X_WINDOWS */
3923 /* Look up pixel color PIXEL which is used on frame F in the color
3924 table. If not already present, allocate it. Value is PIXEL. */
3926 static unsigned long
3927 lookup_pixel_color (f
, pixel
)
3929 unsigned long pixel
;
3931 int i
= pixel
% CT_SIZE
;
3934 for (p
= ct_table
[i
]; p
; p
= p
->next
)
3935 if (p
->pixel
== pixel
)
3944 #ifdef HAVE_X_WINDOWS
3945 cmap
= FRAME_X_COLORMAP (f
);
3946 color
.pixel
= pixel
;
3947 x_query_color (f
, &color
);
3948 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3951 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3952 color
.pixel
= pixel
;
3953 XQueryColor (NULL
, cmap
, &color
);
3954 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
3956 #endif /* HAVE_X_WINDOWS */
3960 ++ct_colors_allocated
;
3962 p
= (struct ct_color
*) xmalloc (sizeof *p
);
3967 p
->next
= ct_table
[i
];
3971 return FRAME_FOREGROUND_PIXEL (f
);
3977 /* Value is a vector of all pixel colors contained in the color table,
3978 allocated via xmalloc. Set *N to the number of colors. */
3980 static unsigned long *
3981 colors_in_color_table (n
)
3986 unsigned long *colors
;
3988 if (ct_colors_allocated
== 0)
3995 colors
= (unsigned long *) xmalloc (ct_colors_allocated
3997 *n
= ct_colors_allocated
;
3999 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4000 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4001 colors
[j
++] = p
->pixel
;
4007 #else /* COLOR_TABLE_SUPPORT */
4009 static unsigned long
4010 lookup_rgb_color (f
, r
, g
, b
)
4014 unsigned long pixel
;
4017 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4018 gamma_correct (f
, &pixel
);
4022 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4023 #endif /* HAVE_NTGUI */
4032 #endif /* COLOR_TABLE_SUPPORT */
4035 /***********************************************************************
4037 ***********************************************************************/
4039 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4040 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4041 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4044 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4045 #endif /* HAVE_NTGUI */
4047 /* Non-zero means draw a cross on images having `:conversion
4050 int cross_disabled_images
;
4052 /* Edge detection matrices for different edge-detection
4055 static int emboss_matrix
[9] = {
4057 2, -1, 0, /* y - 1 */
4059 0, 1, -2 /* y + 1 */
4062 static int laplace_matrix
[9] = {
4064 1, 0, 0, /* y - 1 */
4066 0, 0, -1 /* y + 1 */
4069 /* Value is the intensity of the color whose red/green/blue values
4072 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4075 /* On frame F, return an array of XColor structures describing image
4076 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4077 non-zero means also fill the red/green/blue members of the XColor
4078 structures. Value is a pointer to the array of XColors structures,
4079 allocated with xmalloc; it must be freed by the caller. */
4082 x_to_xcolors (f
, img
, rgb_p
)
4089 XImagePtr_or_DC ximg
;
4093 #endif /* HAVE_NTGUI */
4095 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4098 /* Get the X image IMG->pixmap. */
4099 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4100 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4102 /* Load the image into a memory device context. */
4103 hdc
= get_frame_dc (f
);
4104 ximg
= CreateCompatibleDC (hdc
);
4105 release_frame_dc (f
, hdc
);
4106 prev
= SelectObject (ximg
, img
->pixmap
);
4107 #endif /* HAVE_NTGUI */
4109 /* Fill the `pixel' members of the XColor array. I wished there
4110 were an easy and portable way to circumvent XGetPixel. */
4112 for (y
= 0; y
< img
->height
; ++y
)
4116 #ifdef HAVE_X_WINDOWS
4117 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4118 p
->pixel
= XGetPixel (ximg
, x
, y
);
4120 x_query_colors (f
, row
, img
->width
);
4124 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4126 /* W32_TODO: palette support needed here? */
4127 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4131 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4132 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4133 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4136 p
->red
= 256 * GetRValue (p
->pixel
);
4137 p
->green
= 256 * GetGValue (p
->pixel
);
4138 p
->blue
= 256 * GetBValue (p
->pixel
);
4139 #endif /* HAVE_NTGUI */
4142 #endif /* HAVE_X_WINDOWS */
4145 Destroy_Image (ximg
, prev
);
4152 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4153 created with CreateDIBSection, with the pointer to the bit values
4154 stored in ximg->data. */
4156 static void XPutPixel (ximg
, x
, y
, color
)
4161 int width
= ximg
->info
.bmiHeader
.biWidth
;
4162 int height
= ximg
->info
.bmiHeader
.biHeight
;
4163 unsigned char * pixel
;
4165 /* True color images. */
4166 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4168 int rowbytes
= width
* 3;
4169 /* Ensure scanlines are aligned on 4 byte boundaries. */
4171 rowbytes
+= 4 - (rowbytes
% 4);
4173 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4174 /* Windows bitmaps are in BGR order. */
4175 *pixel
= GetBValue (color
);
4176 *(pixel
+ 1) = GetGValue (color
);
4177 *(pixel
+ 2) = GetRValue (color
);
4179 /* Monochrome images. */
4180 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4182 int rowbytes
= width
/ 8;
4183 /* Ensure scanlines are aligned on 4 byte boundaries. */
4185 rowbytes
+= 4 - (rowbytes
% 4);
4186 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4187 /* Filter out palette info. */
4188 if (color
& 0x00ffffff)
4189 *pixel
= *pixel
| (1 << x
% 8);
4191 *pixel
= *pixel
& ~(1 << x
% 8);
4194 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4197 #endif /* HAVE_NTGUI */
4199 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4200 RGB members are set. F is the frame on which this all happens.
4201 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4204 x_from_xcolors (f
, img
, colors
)
4214 init_color_table ();
4216 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4219 for (y
= 0; y
< img
->height
; ++y
)
4220 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4222 unsigned long pixel
;
4223 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4224 XPutPixel (oimg
, x
, y
, pixel
);
4228 x_clear_image_1 (f
, img
, 1, 0, 1);
4230 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4231 x_destroy_x_image (oimg
);
4232 img
->pixmap
= pixmap
;
4233 #ifdef COLOR_TABLE_SUPPORT
4234 img
->colors
= colors_in_color_table (&img
->ncolors
);
4235 free_color_table ();
4236 #endif /* COLOR_TABLE_SUPPORT */
4240 /* On frame F, perform edge-detection on image IMG.
4242 MATRIX is a nine-element array specifying the transformation
4243 matrix. See emboss_matrix for an example.
4245 COLOR_ADJUST is a color adjustment added to each pixel of the
4249 x_detect_edges (f
, img
, matrix
, color_adjust
)
4252 int matrix
[9], color_adjust
;
4254 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4258 for (i
= sum
= 0; i
< 9; ++i
)
4259 sum
+= abs (matrix
[i
]);
4261 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4263 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4265 for (y
= 0; y
< img
->height
; ++y
)
4267 p
= COLOR (new, 0, y
);
4268 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4269 p
= COLOR (new, img
->width
- 1, y
);
4270 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4273 for (x
= 1; x
< img
->width
- 1; ++x
)
4275 p
= COLOR (new, x
, 0);
4276 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4277 p
= COLOR (new, x
, img
->height
- 1);
4278 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4281 for (y
= 1; y
< img
->height
- 1; ++y
)
4283 p
= COLOR (new, 1, y
);
4285 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4287 int r
, g
, b
, y1
, x1
;
4290 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4291 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4294 XColor
*t
= COLOR (colors
, x1
, y1
);
4295 r
+= matrix
[i
] * t
->red
;
4296 g
+= matrix
[i
] * t
->green
;
4297 b
+= matrix
[i
] * t
->blue
;
4300 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4301 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4302 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4303 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4308 x_from_xcolors (f
, img
, new);
4314 /* Perform the pre-defined `emboss' edge-detection on image IMG
4322 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4326 /* Transform image IMG which is used on frame F with a Laplace
4327 edge-detection algorithm. The result is an image that can be used
4328 to draw disabled buttons, for example. */
4335 x_detect_edges (f
, img
, laplace_matrix
, 45000);
4339 /* Perform edge-detection on image IMG on frame F, with specified
4340 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4342 MATRIX must be either
4344 - a list of at least 9 numbers in row-major form
4345 - a vector of at least 9 numbers
4347 COLOR_ADJUST nil means use a default; otherwise it must be a
4351 x_edge_detection (f
, img
, matrix
, color_adjust
)
4354 Lisp_Object matrix
, color_adjust
;
4362 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
4363 ++i
, matrix
= XCDR (matrix
))
4364 trans
[i
] = XFLOATINT (XCAR (matrix
));
4366 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
4368 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
4369 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
4372 if (NILP (color_adjust
))
4373 color_adjust
= make_number (0xffff / 2);
4375 if (i
== 9 && NUMBERP (color_adjust
))
4376 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
4380 /* Transform image IMG on frame F so that it looks disabled. */
4383 x_disable_image (f
, img
)
4387 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4389 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
4391 int n_planes
= dpyinfo
->n_planes
;
4392 #endif /* HAVE_NTGUI */
4396 /* Color (or grayscale). Convert to gray, and equalize. Just
4397 drawing such images with a stipple can look very odd, so
4398 we're using this method instead. */
4399 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4401 const int h
= 15000;
4402 const int l
= 30000;
4404 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
4408 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
4409 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
4410 p
->red
= p
->green
= p
->blue
= i2
;
4413 x_from_xcolors (f
, img
, colors
);
4416 /* Draw a cross over the disabled image, if we must or if we
4418 if (n_planes
< 2 || cross_disabled_images
)
4421 Display
*dpy
= FRAME_X_DISPLAY (f
);
4425 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4426 #define MaskForeground(f) PIX_MASK_DRAW (f)
4428 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4429 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4432 gc
= XCreateGC_pixmap (dpy
, img
->pixmap
);
4433 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
4434 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
4435 img
->width
- 1, img
->height
- 1);
4436 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
4442 gc
= XCreateGC_pixmap (dpy
, img
->mask
);
4443 XSetForeground (dpy
, gc
, MaskForeground (f
));
4444 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
4445 img
->width
- 1, img
->height
- 1);
4446 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
4454 hdc
= get_frame_dc (f
);
4455 bmpdc
= CreateCompatibleDC (hdc
);
4456 release_frame_dc (f
, hdc
);
4458 prev
= SelectObject (bmpdc
, img
->pixmap
);
4460 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
4461 MoveToEx (bmpdc
, 0, 0, NULL
);
4462 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4463 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4464 LineTo (bmpdc
, img
->width
- 1, 0);
4468 SelectObject (bmpdc
, img
->mask
);
4469 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
4470 MoveToEx (bmpdc
, 0, 0, NULL
);
4471 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
4472 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
4473 LineTo (bmpdc
, img
->width
- 1, 0);
4475 SelectObject (bmpdc
, prev
);
4477 #endif /* HAVE_NTGUI */
4482 /* Build a mask for image IMG which is used on frame F. FILE is the
4483 name of an image file, for error messages. HOW determines how to
4484 determine the background color of IMG. If it is a list '(R G B)',
4485 with R, G, and B being integers >= 0, take that as the color of the
4486 background. Otherwise, determine the background color of IMG
4487 heuristically. Value is non-zero if successful. */
4490 x_build_heuristic_mask (f
, img
, how
)
4495 XImagePtr_or_DC ximg
;
4503 #endif /* HAVE_NTGUI */
4504 int x
, y
, rc
, use_img_background
;
4505 unsigned long bg
= 0;
4509 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4510 img
->mask
= NO_PIXMAP
;
4511 img
->background_transparent_valid
= 0;
4515 /* Create an image and pixmap serving as mask. */
4516 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
4517 &mask_img
, &img
->mask
);
4521 /* Get the X image of IMG->pixmap. */
4522 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
4523 img
->width
, img
->height
,
4526 /* Create the bit array serving as mask. */
4527 row_width
= (img
->width
+ 7) / 8;
4528 mask_img
= xmalloc (row_width
* img
->height
);
4529 bzero (mask_img
, row_width
* img
->height
);
4531 /* Create a memory device context for IMG->pixmap. */
4532 frame_dc
= get_frame_dc (f
);
4533 ximg
= CreateCompatibleDC (frame_dc
);
4534 release_frame_dc (f
, frame_dc
);
4535 prev
= SelectObject (ximg
, img
->pixmap
);
4536 #endif /* HAVE_NTGUI */
4538 /* Determine the background color of ximg. If HOW is `(R G B)'
4539 take that as color. Otherwise, use the image's background color. */
4540 use_img_background
= 1;
4546 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
4548 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
4552 if (i
== 3 && NILP (how
))
4554 char color_name
[30];
4555 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
4558 0x00ffffff & /* Filter out palette info. */
4559 #endif /* HAVE_NTGUI */
4560 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
4561 use_img_background
= 0;
4565 if (use_img_background
)
4566 bg
= four_corners_best (ximg
, img
->width
, img
->height
);
4568 /* Set all bits in mask_img to 1 whose color in ximg is different
4569 from the background color bg. */
4571 for (y
= 0; y
< img
->height
; ++y
)
4572 for (x
= 0; x
< img
->width
; ++x
)
4573 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
4574 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
)));
4576 /* Fill in the background_transparent field while we have the mask handy. */
4577 image_background_transparent (img
, f
, mask_img
);
4579 /* Put mask_img into img->mask. */
4580 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
4581 x_destroy_x_image (mask_img
);
4584 for (y
= 0; y
< img
->height
; ++y
)
4585 for (x
= 0; x
< img
->width
; ++x
)
4587 COLORREF p
= GetPixel (ximg
, x
, y
);
4589 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
4592 /* Create the mask image. */
4593 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
4595 /* Fill in the background_transparent field while we have the mask handy. */
4596 SelectObject (ximg
, img
->mask
);
4597 image_background_transparent (img
, f
, ximg
);
4599 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4601 #endif /* HAVE_NTGUI */
4603 Destroy_Image (ximg
, prev
);
4609 /***********************************************************************
4610 PBM (mono, gray, color)
4611 ***********************************************************************/
4613 static int pbm_image_p
P_ ((Lisp_Object object
));
4614 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
4615 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
4617 /* The symbol `pbm' identifying images of this type. */
4621 /* Indices of image specification fields in gs_format, below. */
4623 enum pbm_keyword_index
4639 /* Vector of image_keyword structures describing the format
4640 of valid user-defined image specifications. */
4642 static struct image_keyword pbm_format
[PBM_LAST
] =
4644 {":type", IMAGE_SYMBOL_VALUE
, 1},
4645 {":file", IMAGE_STRING_VALUE
, 0},
4646 {":data", IMAGE_STRING_VALUE
, 0},
4647 {":ascent", IMAGE_ASCENT_VALUE
, 0},
4648 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
4649 {":relief", IMAGE_INTEGER_VALUE
, 0},
4650 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4651 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4652 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
4653 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
4654 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
4657 /* Structure describing the image type `pbm'. */
4659 static struct image_type pbm_type
=
4669 /* Return non-zero if OBJECT is a valid PBM image specification. */
4672 pbm_image_p (object
)
4675 struct image_keyword fmt
[PBM_LAST
];
4677 bcopy (pbm_format
, fmt
, sizeof fmt
);
4679 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
4682 /* Must specify either :data or :file. */
4683 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
4687 /* Scan a decimal number from *S and return it. Advance *S while
4688 reading the number. END is the end of the string. Value is -1 at
4692 pbm_scan_number (s
, end
)
4693 unsigned char **s
, *end
;
4695 int c
= 0, val
= -1;
4699 /* Skip white-space. */
4700 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4705 /* Skip comment to end of line. */
4706 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
4709 else if (isdigit (c
))
4711 /* Read decimal number. */
4713 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
4714 val
= 10 * val
+ c
- '0';
4726 #if 0 /* Unused. ++kfs */
4728 /* Read FILE into memory. Value is a pointer to a buffer allocated
4729 with xmalloc holding FILE's contents. Value is null if an error
4730 occurred. *SIZE is set to the size of the file. */
4733 pbm_read_file (file
, size
)
4741 if (stat (SDATA (file
), &st
) == 0
4742 && (fp
= fopen (SDATA (file
), "rb")) != NULL
4743 && (buf
= (char *) xmalloc (st
.st_size
),
4744 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
4763 #endif /* HAVE_NTGUI */
4765 /* Load PBM image IMG for use on frame F. */
4773 int width
, height
, max_color_idx
= 0;
4775 Lisp_Object file
, specified_file
;
4776 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
4777 struct gcpro gcpro1
;
4778 unsigned char *contents
= NULL
;
4779 unsigned char *end
, *p
;
4782 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
4786 if (STRINGP (specified_file
))
4788 file
= x_find_image_file (specified_file
);
4789 if (!STRINGP (file
))
4791 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
4796 contents
= slurp_file (SDATA (file
), &size
);
4797 if (contents
== NULL
)
4799 image_error ("Error reading `%s'", file
, Qnil
);
4805 end
= contents
+ size
;
4810 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4812 end
= p
+ SBYTES (data
);
4815 /* Check magic number. */
4816 if (end
- p
< 2 || *p
++ != 'P')
4818 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
4828 raw_p
= 0, type
= PBM_MONO
;
4832 raw_p
= 0, type
= PBM_GRAY
;
4836 raw_p
= 0, type
= PBM_COLOR
;
4840 raw_p
= 1, type
= PBM_MONO
;
4844 raw_p
= 1, type
= PBM_GRAY
;
4848 raw_p
= 1, type
= PBM_COLOR
;
4852 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
4856 /* Read width, height, maximum color-component. Characters
4857 starting with `#' up to the end of a line are ignored. */
4858 width
= pbm_scan_number (&p
, end
);
4859 height
= pbm_scan_number (&p
, end
);
4861 if (type
!= PBM_MONO
)
4863 max_color_idx
= pbm_scan_number (&p
, end
);
4864 if (raw_p
&& max_color_idx
> 255)
4865 max_color_idx
= 255;
4870 || (type
!= PBM_MONO
&& max_color_idx
< 0))
4873 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4874 &ximg
, &img
->pixmap
))
4877 /* Initialize the color hash table. */
4878 init_color_table ();
4880 if (type
== PBM_MONO
)
4883 struct image_keyword fmt
[PBM_LAST
];
4884 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
4885 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
4887 /* Parse the image specification. */
4888 bcopy (pbm_format
, fmt
, sizeof fmt
);
4889 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
4891 /* Get foreground and background colors, maybe allocate colors. */
4892 if (fmt
[PBM_FOREGROUND
].count
4893 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
4894 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
4895 if (fmt
[PBM_BACKGROUND
].count
4896 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
4898 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
4899 img
->background
= bg
;
4900 img
->background_valid
= 1;
4903 for (y
= 0; y
< height
; ++y
)
4904 for (x
= 0; x
< width
; ++x
)
4914 g
= pbm_scan_number (&p
, end
);
4916 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
4921 for (y
= 0; y
< height
; ++y
)
4922 for (x
= 0; x
< width
; ++x
)
4926 if (type
== PBM_GRAY
)
4927 r
= g
= b
= raw_p
? *p
++ : pbm_scan_number (&p
, end
);
4936 r
= pbm_scan_number (&p
, end
);
4937 g
= pbm_scan_number (&p
, end
);
4938 b
= pbm_scan_number (&p
, end
);
4941 if (r
< 0 || g
< 0 || b
< 0)
4943 x_destroy_x_image (ximg
);
4944 image_error ("Invalid pixel value in image `%s'",
4949 /* RGB values are now in the range 0..max_color_idx.
4950 Scale this to the range 0..0xffff supported by X. */
4951 r
= (double) r
* 65535 / max_color_idx
;
4952 g
= (double) g
* 65535 / max_color_idx
;
4953 b
= (double) b
* 65535 / max_color_idx
;
4954 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
4958 #ifdef COLOR_TABLE_SUPPORT
4959 /* Store in IMG->colors the colors allocated for the image, and
4960 free the color table. */
4961 img
->colors
= colors_in_color_table (&img
->ncolors
);
4962 free_color_table ();
4963 #endif /* COLOR_TABLE_SUPPORT */
4966 img
->height
= height
;
4968 /* Maybe fill in the background field while we have ximg handy. */
4970 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4971 IMAGE_BACKGROUND (img
, f
, ximg
);
4973 /* Put the image into a pixmap. */
4974 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4975 x_destroy_x_image (ximg
);
4977 /* X and W32 versions did it here, MAC version above. ++kfs
4979 img->height = height; */
4987 /***********************************************************************
4989 ***********************************************************************/
4991 #if defined (HAVE_PNG) || defined (MAC_OS)
4993 /* Function prototypes. */
4995 static int png_image_p
P_ ((Lisp_Object object
));
4996 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
4998 /* The symbol `png' identifying images of this type. */
5002 /* Indices of image specification fields in png_format, below. */
5004 enum png_keyword_index
5019 /* Vector of image_keyword structures describing the format
5020 of valid user-defined image specifications. */
5022 static struct image_keyword png_format
[PNG_LAST
] =
5024 {":type", IMAGE_SYMBOL_VALUE
, 1},
5025 {":data", IMAGE_STRING_VALUE
, 0},
5026 {":file", IMAGE_STRING_VALUE
, 0},
5027 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5028 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5029 {":relief", IMAGE_INTEGER_VALUE
, 0},
5030 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5031 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5032 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5033 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5036 /* Structure describing the image type `png'. */
5038 static struct image_type png_type
=
5047 /* Return non-zero if OBJECT is a valid PNG image specification. */
5050 png_image_p (object
)
5053 struct image_keyword fmt
[PNG_LAST
];
5054 bcopy (png_format
, fmt
, sizeof fmt
);
5056 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5059 /* Must specify either the :data or :file keyword. */
5060 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5063 #endif /* HAVE_PNG || MAC_OS */
5068 #if defined HAVE_LIBPNG_PNG_H
5069 # include <libpng/png.h>
5075 /* PNG library details. */
5077 DEF_IMGLIB_FN (png_get_io_ptr
);
5078 DEF_IMGLIB_FN (png_check_sig
);
5079 DEF_IMGLIB_FN (png_create_read_struct
);
5080 DEF_IMGLIB_FN (png_create_info_struct
);
5081 DEF_IMGLIB_FN (png_destroy_read_struct
);
5082 DEF_IMGLIB_FN (png_set_read_fn
);
5083 DEF_IMGLIB_FN (png_init_io
);
5084 DEF_IMGLIB_FN (png_set_sig_bytes
);
5085 DEF_IMGLIB_FN (png_read_info
);
5086 DEF_IMGLIB_FN (png_get_IHDR
);
5087 DEF_IMGLIB_FN (png_get_valid
);
5088 DEF_IMGLIB_FN (png_set_strip_16
);
5089 DEF_IMGLIB_FN (png_set_expand
);
5090 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5091 DEF_IMGLIB_FN (png_set_background
);
5092 DEF_IMGLIB_FN (png_get_bKGD
);
5093 DEF_IMGLIB_FN (png_read_update_info
);
5094 DEF_IMGLIB_FN (png_get_channels
);
5095 DEF_IMGLIB_FN (png_get_rowbytes
);
5096 DEF_IMGLIB_FN (png_read_image
);
5097 DEF_IMGLIB_FN (png_read_end
);
5098 DEF_IMGLIB_FN (png_error
);
5101 init_png_functions (void)
5105 /* Ensure zlib is loaded. Try debug version first. */
5106 if (!LoadLibrary ("zlibd.dll")
5107 && !LoadLibrary ("zlib.dll"))
5110 /* Try loading libpng under probable names. */
5111 if (!(library
= LoadLibrary ("libpng13d.dll"))
5112 && !(library
= LoadLibrary ("libpng13.dll"))
5113 && !(library
= LoadLibrary ("libpng12d.dll"))
5114 && !(library
= LoadLibrary ("libpng12.dll"))
5115 && !(library
= LoadLibrary ("libpng.dll")))
5118 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5119 LOAD_IMGLIB_FN (library
, png_check_sig
);
5120 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5121 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5122 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5123 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5124 LOAD_IMGLIB_FN (library
, png_init_io
);
5125 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5126 LOAD_IMGLIB_FN (library
, png_read_info
);
5127 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5128 LOAD_IMGLIB_FN (library
, png_get_valid
);
5129 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5130 LOAD_IMGLIB_FN (library
, png_set_expand
);
5131 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5132 LOAD_IMGLIB_FN (library
, png_set_background
);
5133 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5134 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5135 LOAD_IMGLIB_FN (library
, png_get_channels
);
5136 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5137 LOAD_IMGLIB_FN (library
, png_read_image
);
5138 LOAD_IMGLIB_FN (library
, png_read_end
);
5139 LOAD_IMGLIB_FN (library
, png_error
);
5144 #define fn_png_get_io_ptr png_get_io_ptr
5145 #define fn_png_check_sig png_check_sig
5146 #define fn_png_create_read_struct png_create_read_struct
5147 #define fn_png_create_info_struct png_create_info_struct
5148 #define fn_png_destroy_read_struct png_destroy_read_struct
5149 #define fn_png_set_read_fn png_set_read_fn
5150 #define fn_png_init_io png_init_io
5151 #define fn_png_set_sig_bytes png_set_sig_bytes
5152 #define fn_png_read_info png_read_info
5153 #define fn_png_get_IHDR png_get_IHDR
5154 #define fn_png_get_valid png_get_valid
5155 #define fn_png_set_strip_16 png_set_strip_16
5156 #define fn_png_set_expand png_set_expand
5157 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5158 #define fn_png_set_background png_set_background
5159 #define fn_png_get_bKGD png_get_bKGD
5160 #define fn_png_read_update_info png_read_update_info
5161 #define fn_png_get_channels png_get_channels
5162 #define fn_png_get_rowbytes png_get_rowbytes
5163 #define fn_png_read_image png_read_image
5164 #define fn_png_read_end png_read_end
5165 #define fn_png_error png_error
5167 #endif /* HAVE_NTGUI */
5169 /* Error and warning handlers installed when the PNG library
5173 my_png_error (png_ptr
, msg
)
5174 png_struct
*png_ptr
;
5177 xassert (png_ptr
!= NULL
);
5178 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5179 longjmp (png_ptr
->jmpbuf
, 1);
5184 my_png_warning (png_ptr
, msg
)
5185 png_struct
*png_ptr
;
5188 xassert (png_ptr
!= NULL
);
5189 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5192 /* Memory source for PNG decoding. */
5194 struct png_memory_storage
5196 unsigned char *bytes
; /* The data */
5197 size_t len
; /* How big is it? */
5198 int index
; /* Where are we? */
5202 /* Function set as reader function when reading PNG image from memory.
5203 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5204 bytes from the input to DATA. */
5207 png_read_from_memory (png_ptr
, data
, length
)
5208 png_structp png_ptr
;
5212 struct png_memory_storage
*tbr
5213 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5215 if (length
> tbr
->len
- tbr
->index
)
5216 fn_png_error (png_ptr
, "Read error");
5218 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5219 tbr
->index
= tbr
->index
+ length
;
5222 /* Load PNG image IMG for use on frame F. Value is non-zero if
5230 Lisp_Object file
, specified_file
;
5231 Lisp_Object specified_data
;
5233 XImagePtr ximg
, mask_img
= NULL
;
5234 struct gcpro gcpro1
;
5235 png_struct
*png_ptr
= NULL
;
5236 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5237 FILE *volatile fp
= NULL
;
5239 png_byte
* volatile pixels
= NULL
;
5240 png_byte
** volatile rows
= NULL
;
5241 png_uint_32 width
, height
;
5242 int bit_depth
, color_type
, interlace_type
;
5244 png_uint_32 row_bytes
;
5246 double screen_gamma
;
5247 struct png_memory_storage tbr
; /* Data to be read */
5249 /* Find out what file to load. */
5250 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5251 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5255 if (NILP (specified_data
))
5257 file
= x_find_image_file (specified_file
);
5258 if (!STRINGP (file
))
5260 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5265 /* Open the image file. */
5266 fp
= fopen (SDATA (file
), "rb");
5269 image_error ("Cannot open image file `%s'", file
, Qnil
);
5275 /* Check PNG signature. */
5276 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5277 || !fn_png_check_sig (sig
, sizeof sig
))
5279 image_error ("Not a PNG file: `%s'", file
, Qnil
);
5287 /* Read from memory. */
5288 tbr
.bytes
= SDATA (specified_data
);
5289 tbr
.len
= SBYTES (specified_data
);
5292 /* Check PNG signature. */
5293 if (tbr
.len
< sizeof sig
5294 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
5296 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
5301 /* Need to skip past the signature. */
5302 tbr
.bytes
+= sizeof (sig
);
5305 /* Initialize read and info structs for PNG lib. */
5306 png_ptr
= fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
, NULL
,
5307 my_png_error
, my_png_warning
);
5310 if (fp
) fclose (fp
);
5315 info_ptr
= fn_png_create_info_struct (png_ptr
);
5318 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
5319 if (fp
) fclose (fp
);
5324 end_info
= fn_png_create_info_struct (png_ptr
);
5327 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
5328 if (fp
) fclose (fp
);
5333 /* Set error jump-back. We come back here when the PNG library
5334 detects an error. */
5335 if (setjmp (png_ptr
->jmpbuf
))
5339 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5342 if (fp
) fclose (fp
);
5347 /* Read image info. */
5348 if (!NILP (specified_data
))
5349 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
5351 fn_png_init_io (png_ptr
, fp
);
5353 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
5354 fn_png_read_info (png_ptr
, info_ptr
);
5355 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
5356 &interlace_type
, NULL
, NULL
);
5358 /* If image contains simply transparency data, we prefer to
5359 construct a clipping mask. */
5360 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
5365 /* This function is easier to write if we only have to handle
5366 one data format: RGB or RGBA with 8 bits per channel. Let's
5367 transform other formats into that format. */
5369 /* Strip more than 8 bits per channel. */
5370 if (bit_depth
== 16)
5371 fn_png_set_strip_16 (png_ptr
);
5373 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5375 fn_png_set_expand (png_ptr
);
5377 /* Convert grayscale images to RGB. */
5378 if (color_type
== PNG_COLOR_TYPE_GRAY
5379 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5380 fn_png_set_gray_to_rgb (png_ptr
);
5382 screen_gamma
= (f
->gamma
? 1 / f
->gamma
/ 0.45455 : 2.2);
5384 #if 0 /* Avoid double gamma correction for PNG images. */
5385 { /* Tell the PNG lib to handle gamma correction for us. */
5388 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5389 if (png_get_sRGB (png_ptr
, info_ptr
, &intent
))
5390 /* The libpng documentation says this is right in this case. */
5391 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5394 if (png_get_gAMA (png_ptr
, info_ptr
, &image_gamma
))
5395 /* Image contains gamma information. */
5396 png_set_gamma (png_ptr
, screen_gamma
, image_gamma
);
5398 /* Use the standard default for the image gamma. */
5399 png_set_gamma (png_ptr
, screen_gamma
, 0.45455);
5403 /* Handle alpha channel by combining the image with a background
5404 color. Do this only if a real alpha channel is supplied. For
5405 simple transparency, we prefer a clipping mask. */
5408 png_color_16
*image_bg
;
5409 Lisp_Object specified_bg
5410 = image_spec_value (img
->spec
, QCbackground
, NULL
);
5412 if (STRINGP (specified_bg
))
5413 /* The user specified `:background', use that. */
5415 /* W32 version incorrectly used COLORREF here!! ++kfs */
5417 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
5419 png_color_16 user_bg
;
5421 bzero (&user_bg
, sizeof user_bg
);
5422 user_bg
.red
= color
.red
>> PNG_BG_COLOR_SHIFT
;
5423 user_bg
.green
= color
.green
>> PNG_BG_COLOR_SHIFT
;
5424 user_bg
.blue
= color
.blue
>> PNG_BG_COLOR_SHIFT
;
5426 fn_png_set_background (png_ptr
, &user_bg
,
5427 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5430 else if (fn_png_get_bKGD (png_ptr
, info_ptr
, &image_bg
))
5431 /* Image contains a background color with which to
5432 combine the image. */
5433 fn_png_set_background (png_ptr
, image_bg
,
5434 PNG_BACKGROUND_GAMMA_FILE
, 1, 1.0);
5437 /* Image does not contain a background color with which
5438 to combine the image data via an alpha channel. Use
5439 the frame's background instead. */
5440 #ifdef HAVE_X_WINDOWS
5442 png_color_16 frame_background
;
5444 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
5445 x_query_color (f
, &color
);
5447 bzero (&frame_background
, sizeof frame_background
);
5448 frame_background
.red
= color
.red
;
5449 frame_background
.green
= color
.green
;
5450 frame_background
.blue
= color
.blue
;
5451 #endif /* HAVE_X_WINDOWS */
5455 png_color_16 frame_background
;
5456 color
= FRAME_BACKGROUND_PIXEL (f
);
5457 #if 0 /* W32 TODO : Colormap support. */
5458 x_query_color (f
, &color
);
5460 bzero (&frame_background
, sizeof frame_background
);
5461 frame_background
.red
= 256 * GetRValue (color
);
5462 frame_background
.green
= 256 * GetGValue (color
);
5463 frame_background
.blue
= 256 * GetBValue (color
);
5464 #endif /* HAVE_NTGUI */
5467 unsigned long color
;
5468 png_color_16 frame_background
;
5469 color
= FRAME_BACKGROUND_PIXEL (f
);
5470 #if 0 /* MAC/W32 TODO : Colormap support. */
5471 x_query_color (f
, &color
);
5473 bzero (&frame_background
, sizeof frame_background
);
5474 frame_background
.red
= RED_FROM_ULONG (color
);
5475 frame_background
.green
= GREEN_FROM_ULONG (color
);
5476 frame_background
.blue
= BLUE_FROM_ULONG (color
);
5479 fn_png_set_background (png_ptr
, &frame_background
,
5480 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
5484 /* Update info structure. */
5485 fn_png_read_update_info (png_ptr
, info_ptr
);
5487 /* Get number of channels. Valid values are 1 for grayscale images
5488 and images with a palette, 2 for grayscale images with transparency
5489 information (alpha channel), 3 for RGB images, and 4 for RGB
5490 images with alpha channel, i.e. RGBA. If conversions above were
5491 sufficient we should only have 3 or 4 channels here. */
5492 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
5493 xassert (channels
== 3 || channels
== 4);
5495 /* Number of bytes needed for one row of the image. */
5496 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
5498 /* Allocate memory for the image. */
5499 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
5500 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
5501 for (i
= 0; i
< height
; ++i
)
5502 rows
[i
] = pixels
+ i
* row_bytes
;
5504 /* Read the entire image. */
5505 fn_png_read_image (png_ptr
, rows
);
5506 fn_png_read_end (png_ptr
, info_ptr
);
5513 /* Create the X image and pixmap. */
5514 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
5518 /* Create an image and pixmap serving as mask if the PNG image
5519 contains an alpha channel. */
5522 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
5523 &mask_img
, &img
->mask
))
5525 x_destroy_x_image (ximg
);
5526 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
5527 img
->pixmap
= NO_PIXMAP
;
5531 /* Fill the X image and mask from PNG data. */
5532 init_color_table ();
5534 for (y
= 0; y
< height
; ++y
)
5536 png_byte
*p
= rows
[y
];
5538 for (x
= 0; x
< width
; ++x
)
5545 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5546 /* An alpha channel, aka mask channel, associates variable
5547 transparency with an image. Where other image formats
5548 support binary transparency---fully transparent or fully
5549 opaque---PNG allows up to 254 levels of partial transparency.
5550 The PNG library implements partial transparency by combining
5551 the image with a specified background color.
5553 I'm not sure how to handle this here nicely: because the
5554 background on which the image is displayed may change, for
5555 real alpha channel support, it would be necessary to create
5556 a new image for each possible background.
5558 What I'm doing now is that a mask is created if we have
5559 boolean transparency information. Otherwise I'm using
5560 the frame's background color to combine the image with. */
5565 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW (f
) : PIX_MASK_RETAIN (f
));
5571 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5572 /* Set IMG's background color from the PNG image, unless the user
5576 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
5578 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
5579 img
->background_valid
= 1;
5583 #ifdef COLOR_TABLE_SUPPORT
5584 /* Remember colors allocated for this image. */
5585 img
->colors
= colors_in_color_table (&img
->ncolors
);
5586 free_color_table ();
5587 #endif /* COLOR_TABLE_SUPPORT */
5590 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
5595 img
->height
= height
;
5597 /* Maybe fill in the background field while we have ximg handy. */
5598 IMAGE_BACKGROUND (img
, f
, ximg
);
5600 /* Put the image into the pixmap, then free the X image and its buffer. */
5601 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5602 x_destroy_x_image (ximg
);
5604 /* Same for the mask. */
5607 /* Fill in the background_transparent field while we have the mask
5609 image_background_transparent (img
, f
, mask_img
);
5611 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5612 x_destroy_x_image (mask_img
);
5619 #else /* HAVE_PNG */
5628 if (MyCGImageCreateWithPNGDataProvider
)
5629 return image_load_quartz2d (f
, img
, 1);
5632 return image_load_quicktime (f
, img
, kQTFileTypePNG
);
5636 #endif /* !HAVE_PNG */
5640 /***********************************************************************
5642 ***********************************************************************/
5644 #if defined (HAVE_JPEG) || defined (MAC_OS)
5646 static int jpeg_image_p
P_ ((Lisp_Object object
));
5647 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
5649 /* The symbol `jpeg' identifying images of this type. */
5653 /* Indices of image specification fields in gs_format, below. */
5655 enum jpeg_keyword_index
5664 JPEG_HEURISTIC_MASK
,
5670 /* Vector of image_keyword structures describing the format
5671 of valid user-defined image specifications. */
5673 static struct image_keyword jpeg_format
[JPEG_LAST
] =
5675 {":type", IMAGE_SYMBOL_VALUE
, 1},
5676 {":data", IMAGE_STRING_VALUE
, 0},
5677 {":file", IMAGE_STRING_VALUE
, 0},
5678 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5679 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5680 {":relief", IMAGE_INTEGER_VALUE
, 0},
5681 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5682 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5683 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5684 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5687 /* Structure describing the image type `jpeg'. */
5689 static struct image_type jpeg_type
=
5698 /* Return non-zero if OBJECT is a valid JPEG image specification. */
5701 jpeg_image_p (object
)
5704 struct image_keyword fmt
[JPEG_LAST
];
5706 bcopy (jpeg_format
, fmt
, sizeof fmt
);
5708 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
5711 /* Must specify either the :data or :file keyword. */
5712 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
5715 #endif /* HAVE_JPEG || MAC_OS */
5719 /* Work around a warning about HAVE_STDLIB_H being redefined in
5721 #ifdef HAVE_STDLIB_H
5722 #define HAVE_STDLIB_H_1
5723 #undef HAVE_STDLIB_H
5724 #endif /* HAVE_STLIB_H */
5726 #include <jpeglib.h>
5730 #ifdef HAVE_STLIB_H_1
5731 #define HAVE_STDLIB_H 1
5736 /* JPEG library details. */
5737 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
5738 DEF_IMGLIB_FN (jpeg_start_decompress
);
5739 DEF_IMGLIB_FN (jpeg_finish_decompress
);
5740 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
5741 DEF_IMGLIB_FN (jpeg_read_header
);
5742 DEF_IMGLIB_FN (jpeg_read_scanlines
);
5743 DEF_IMGLIB_FN (jpeg_stdio_src
);
5744 DEF_IMGLIB_FN (jpeg_std_error
);
5745 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
5748 init_jpeg_functions (void)
5752 if (!(library
= LoadLibrary ("libjpeg.dll"))
5753 && !(library
= LoadLibrary ("jpeg-62.dll"))
5754 && !(library
= LoadLibrary ("jpeg.dll")))
5757 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
5758 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
5759 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
5760 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
5761 LOAD_IMGLIB_FN (library
, jpeg_stdio_src
);
5762 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
5763 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
5764 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
5765 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
5769 /* Wrapper since we can't directly assign the function pointer
5770 to another function pointer that was declared more completely easily. */
5772 jpeg_resync_to_restart_wrapper(cinfo
, desired
)
5773 j_decompress_ptr cinfo
;
5776 return fn_jpeg_resync_to_restart (cinfo
, desired
);
5781 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
5782 #define fn_jpeg_start_decompress jpeg_start_decompress
5783 #define fn_jpeg_finish_decompress jpeg_finish_decompress
5784 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
5785 #define fn_jpeg_read_header jpeg_read_header
5786 #define fn_jpeg_read_scanlines jpeg_read_scanlines
5787 #define fn_jpeg_stdio_src jpeg_stdio_src
5788 #define fn_jpeg_std_error jpeg_std_error
5789 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
5791 #endif /* HAVE_NTGUI */
5793 struct my_jpeg_error_mgr
5795 struct jpeg_error_mgr pub
;
5796 jmp_buf setjmp_buffer
;
5801 my_error_exit (cinfo
)
5804 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
5805 longjmp (mgr
->setjmp_buffer
, 1);
5809 /* Init source method for JPEG data source manager. Called by
5810 jpeg_read_header() before any data is actually read. See
5811 libjpeg.doc from the JPEG lib distribution. */
5814 our_init_source (cinfo
)
5815 j_decompress_ptr cinfo
;
5820 /* Fill input buffer method for JPEG data source manager. Called
5821 whenever more data is needed. We read the whole image in one step,
5822 so this only adds a fake end of input marker at the end. */
5825 our_fill_input_buffer (cinfo
)
5826 j_decompress_ptr cinfo
;
5828 /* Insert a fake EOI marker. */
5829 struct jpeg_source_mgr
*src
= cinfo
->src
;
5830 static JOCTET buffer
[2];
5832 buffer
[0] = (JOCTET
) 0xFF;
5833 buffer
[1] = (JOCTET
) JPEG_EOI
;
5835 src
->next_input_byte
= buffer
;
5836 src
->bytes_in_buffer
= 2;
5841 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
5842 is the JPEG data source manager. */
5845 our_skip_input_data (cinfo
, num_bytes
)
5846 j_decompress_ptr cinfo
;
5849 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5853 if (num_bytes
> src
->bytes_in_buffer
)
5854 ERREXIT (cinfo
, JERR_INPUT_EOF
);
5856 src
->bytes_in_buffer
-= num_bytes
;
5857 src
->next_input_byte
+= num_bytes
;
5862 /* Method to terminate data source. Called by
5863 jpeg_finish_decompress() after all data has been processed. */
5866 our_term_source (cinfo
)
5867 j_decompress_ptr cinfo
;
5872 /* Set up the JPEG lib for reading an image from DATA which contains
5873 LEN bytes. CINFO is the decompression info structure created for
5874 reading the image. */
5877 jpeg_memory_src (cinfo
, data
, len
)
5878 j_decompress_ptr cinfo
;
5882 struct jpeg_source_mgr
*src
;
5884 if (cinfo
->src
== NULL
)
5886 /* First time for this JPEG object? */
5887 cinfo
->src
= (struct jpeg_source_mgr
*)
5888 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
5889 sizeof (struct jpeg_source_mgr
));
5890 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5891 src
->next_input_byte
= data
;
5894 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
5895 src
->init_source
= our_init_source
;
5896 src
->fill_input_buffer
= our_fill_input_buffer
;
5897 src
->skip_input_data
= our_skip_input_data
;
5898 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
5899 src
->term_source
= our_term_source
;
5900 src
->bytes_in_buffer
= len
;
5901 src
->next_input_byte
= data
;
5905 /* Load image IMG for use on frame F. Patterned after example.c
5906 from the JPEG lib. */
5913 struct jpeg_decompress_struct cinfo
;
5914 struct my_jpeg_error_mgr mgr
;
5915 Lisp_Object file
, specified_file
;
5916 Lisp_Object specified_data
;
5917 FILE * volatile fp
= NULL
;
5919 int row_stride
, x
, y
;
5920 XImagePtr ximg
= NULL
;
5922 unsigned long *colors
;
5924 struct gcpro gcpro1
;
5926 /* Open the JPEG file. */
5927 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5928 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5932 if (NILP (specified_data
))
5934 file
= x_find_image_file (specified_file
);
5935 if (!STRINGP (file
))
5937 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5942 fp
= fopen (SDATA (file
), "rb");
5945 image_error ("Cannot open `%s'", file
, Qnil
);
5951 /* Customize libjpeg's error handling to call my_error_exit when an
5952 error is detected. This function will perform a longjmp. */
5953 cinfo
.err
= fn_jpeg_std_error (&mgr
.pub
);
5954 mgr
.pub
.error_exit
= my_error_exit
;
5956 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
5960 /* Called from my_error_exit. Display a JPEG error. */
5961 char buffer
[JMSG_LENGTH_MAX
];
5962 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
5963 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
5964 build_string (buffer
));
5967 /* Close the input file and destroy the JPEG object. */
5969 fclose ((FILE *) fp
);
5970 fn_jpeg_destroy_decompress (&cinfo
);
5972 /* If we already have an XImage, free that. */
5973 x_destroy_x_image (ximg
);
5975 /* Free pixmap and colors. */
5976 x_clear_image (f
, img
);
5982 /* Create the JPEG decompression object. Let it read from fp.
5983 Read the JPEG image header. */
5984 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
5986 if (NILP (specified_data
))
5987 fn_jpeg_stdio_src (&cinfo
, (FILE *) fp
);
5989 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
5990 SBYTES (specified_data
));
5992 fn_jpeg_read_header (&cinfo
, TRUE
);
5994 /* Customize decompression so that color quantization will be used.
5995 Start decompression. */
5996 cinfo
.quantize_colors
= TRUE
;
5997 fn_jpeg_start_decompress (&cinfo
);
5998 width
= img
->width
= cinfo
.output_width
;
5999 height
= img
->height
= cinfo
.output_height
;
6001 /* Create X image and pixmap. */
6002 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6003 longjmp (mgr
.setjmp_buffer
, 2);
6005 /* Allocate colors. When color quantization is used,
6006 cinfo.actual_number_of_colors has been set with the number of
6007 colors generated, and cinfo.colormap is a two-dimensional array
6008 of color indices in the range 0..cinfo.actual_number_of_colors.
6009 No more than 255 colors will be generated. */
6013 if (cinfo
.out_color_components
> 2)
6014 ir
= 0, ig
= 1, ib
= 2;
6015 else if (cinfo
.out_color_components
> 1)
6016 ir
= 0, ig
= 1, ib
= 0;
6018 ir
= 0, ig
= 0, ib
= 0;
6020 /* Use the color table mechanism because it handles colors that
6021 cannot be allocated nicely. Such colors will be replaced with
6022 a default color, and we don't have to care about which colors
6023 can be freed safely, and which can't. */
6024 init_color_table ();
6025 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6028 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6030 /* Multiply RGB values with 255 because X expects RGB values
6031 in the range 0..0xffff. */
6032 int r
= cinfo
.colormap
[ir
][i
] << 8;
6033 int g
= cinfo
.colormap
[ig
][i
] << 8;
6034 int b
= cinfo
.colormap
[ib
][i
] << 8;
6035 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6038 #ifdef COLOR_TABLE_SUPPORT
6039 /* Remember those colors actually allocated. */
6040 img
->colors
= colors_in_color_table (&img
->ncolors
);
6041 free_color_table ();
6042 #endif /* COLOR_TABLE_SUPPORT */
6046 row_stride
= width
* cinfo
.output_components
;
6047 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6049 for (y
= 0; y
< height
; ++y
)
6051 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6052 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6053 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6057 fn_jpeg_finish_decompress (&cinfo
);
6058 fn_jpeg_destroy_decompress (&cinfo
);
6060 fclose ((FILE *) fp
);
6062 /* Maybe fill in the background field while we have ximg handy. */
6063 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6064 IMAGE_BACKGROUND (img
, f
, ximg
);
6066 /* Put the image into the pixmap. */
6067 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6068 x_destroy_x_image (ximg
);
6073 #else /* HAVE_JPEG */
6082 return image_load_quartz2d (f
, img
, 0);
6084 return image_load_quicktime (f
, img
, kQTFileTypeJPEG
);
6089 #endif /* !HAVE_JPEG */
6093 /***********************************************************************
6095 ***********************************************************************/
6097 #if defined (HAVE_TIFF) || defined (MAC_OS)
6099 static int tiff_image_p
P_ ((Lisp_Object object
));
6100 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6102 /* The symbol `tiff' identifying images of this type. */
6106 /* Indices of image specification fields in tiff_format, below. */
6108 enum tiff_keyword_index
6117 TIFF_HEURISTIC_MASK
,
6123 /* Vector of image_keyword structures describing the format
6124 of valid user-defined image specifications. */
6126 static struct image_keyword tiff_format
[TIFF_LAST
] =
6128 {":type", IMAGE_SYMBOL_VALUE
, 1},
6129 {":data", IMAGE_STRING_VALUE
, 0},
6130 {":file", IMAGE_STRING_VALUE
, 0},
6131 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6132 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6133 {":relief", IMAGE_INTEGER_VALUE
, 0},
6134 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6135 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6136 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6137 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6140 /* Structure describing the image type `tiff'. */
6142 static struct image_type tiff_type
=
6151 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6154 tiff_image_p (object
)
6157 struct image_keyword fmt
[TIFF_LAST
];
6158 bcopy (tiff_format
, fmt
, sizeof fmt
);
6160 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6163 /* Must specify either the :data or :file keyword. */
6164 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6167 #endif /* HAVE_TIFF || MAC_OS */
6175 /* TIFF library details. */
6176 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6177 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6178 DEF_IMGLIB_FN (TIFFOpen
);
6179 DEF_IMGLIB_FN (TIFFClientOpen
);
6180 DEF_IMGLIB_FN (TIFFGetField
);
6181 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6182 DEF_IMGLIB_FN (TIFFClose
);
6185 init_tiff_functions (void)
6189 if (!(library
= LoadLibrary ("libtiff.dll")))
6192 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6193 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6194 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6195 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6196 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6197 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6198 LOAD_IMGLIB_FN (library
, TIFFClose
);
6204 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6205 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6206 #define fn_TIFFOpen TIFFOpen
6207 #define fn_TIFFClientOpen TIFFClientOpen
6208 #define fn_TIFFGetField TIFFGetField
6209 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6210 #define fn_TIFFClose TIFFClose
6212 #endif /* HAVE_NTGUI */
6215 /* Reading from a memory buffer for TIFF images Based on the PNG
6216 memory source, but we have to provide a lot of extra functions.
6219 We really only need to implement read and seek, but I am not
6220 convinced that the TIFF library is smart enough not to destroy
6221 itself if we only hand it the function pointers we need to
6226 unsigned char *bytes
;
6233 tiff_read_from_memory (data
, buf
, size
)
6238 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6240 if (size
> src
->len
- src
->index
)
6242 bcopy (src
->bytes
+ src
->index
, buf
, size
);
6248 tiff_write_from_memory (data
, buf
, size
)
6257 tiff_seek_in_memory (data
, off
, whence
)
6262 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
6267 case SEEK_SET
: /* Go from beginning of source. */
6271 case SEEK_END
: /* Go from end of source. */
6272 idx
= src
->len
+ off
;
6275 case SEEK_CUR
: /* Go from current position. */
6276 idx
= src
->index
+ off
;
6279 default: /* Invalid `whence'. */
6283 if (idx
> src
->len
|| idx
< 0)
6291 tiff_close_memory (data
)
6299 tiff_mmap_memory (data
, pbase
, psize
)
6304 /* It is already _IN_ memory. */
6309 tiff_unmap_memory (data
, base
, size
)
6314 /* We don't need to do this. */
6318 tiff_size_of_memory (data
)
6321 return ((tiff_memory_source
*) data
)->len
;
6326 tiff_error_handler (title
, format
, ap
)
6327 const char *title
, *format
;
6333 len
= sprintf (buf
, "TIFF error: %s ", title
);
6334 vsprintf (buf
+ len
, format
, ap
);
6335 add_to_log (buf
, Qnil
, Qnil
);
6340 tiff_warning_handler (title
, format
, ap
)
6341 const char *title
, *format
;
6347 len
= sprintf (buf
, "TIFF warning: %s ", title
);
6348 vsprintf (buf
+ len
, format
, ap
);
6349 add_to_log (buf
, Qnil
, Qnil
);
6353 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6361 Lisp_Object file
, specified_file
;
6362 Lisp_Object specified_data
;
6364 int width
, height
, x
, y
;
6368 struct gcpro gcpro1
;
6369 tiff_memory_source memsrc
;
6371 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6372 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6376 fn_TIFFSetErrorHandler (tiff_error_handler
);
6377 fn_TIFFSetWarningHandler (tiff_warning_handler
);
6379 if (NILP (specified_data
))
6381 /* Read from a file */
6382 file
= x_find_image_file (specified_file
);
6383 if (!STRINGP (file
))
6385 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6390 /* Try to open the image file. */
6391 tiff
= fn_TIFFOpen (SDATA (file
), "r");
6394 image_error ("Cannot open `%s'", file
, Qnil
);
6401 /* Memory source! */
6402 memsrc
.bytes
= SDATA (specified_data
);
6403 memsrc
.len
= SBYTES (specified_data
);
6406 tiff
= fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
6407 (TIFFReadWriteProc
) tiff_read_from_memory
,
6408 (TIFFReadWriteProc
) tiff_write_from_memory
,
6409 tiff_seek_in_memory
,
6411 tiff_size_of_memory
,
6417 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
6423 /* Get width and height of the image, and allocate a raster buffer
6424 of width x height 32-bit values. */
6425 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
6426 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
6427 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
6429 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
6430 fn_TIFFClose (tiff
);
6433 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
6439 /* Create the X image and pixmap. */
6440 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6447 /* Initialize the color table. */
6448 init_color_table ();
6450 /* Process the pixel raster. Origin is in the lower-left corner. */
6451 for (y
= 0; y
< height
; ++y
)
6453 uint32
*row
= buf
+ y
* width
;
6455 for (x
= 0; x
< width
; ++x
)
6457 uint32 abgr
= row
[x
];
6458 int r
= TIFFGetR (abgr
) << 8;
6459 int g
= TIFFGetG (abgr
) << 8;
6460 int b
= TIFFGetB (abgr
) << 8;
6461 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
6465 #ifdef COLOR_TABLE_SUPPORT
6466 /* Remember the colors allocated for the image. Free the color table. */
6467 img
->colors
= colors_in_color_table (&img
->ncolors
);
6468 free_color_table ();
6469 #endif /* COLOR_TABLE_SUPPORT */
6472 img
->height
= height
;
6474 /* Maybe fill in the background field while we have ximg handy. */
6475 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6476 IMAGE_BACKGROUND (img
, f
, ximg
);
6478 /* Put the image into the pixmap, then free the X image and its buffer. */
6479 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6480 x_destroy_x_image (ximg
);
6487 #else /* HAVE_TIFF */
6495 return image_load_quicktime (f
, img
, kQTFileTypeTIFF
);
6499 #endif /* !HAVE_TIFF */
6503 /***********************************************************************
6505 ***********************************************************************/
6507 #if defined (HAVE_GIF) || defined (MAC_OS)
6509 static int gif_image_p
P_ ((Lisp_Object object
));
6510 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
6512 /* The symbol `gif' identifying images of this type. */
6516 /* Indices of image specification fields in gif_format, below. */
6518 enum gif_keyword_index
6534 /* Vector of image_keyword structures describing the format
6535 of valid user-defined image specifications. */
6537 static struct image_keyword gif_format
[GIF_LAST
] =
6539 {":type", IMAGE_SYMBOL_VALUE
, 1},
6540 {":data", IMAGE_STRING_VALUE
, 0},
6541 {":file", IMAGE_STRING_VALUE
, 0},
6542 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6543 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6544 {":relief", IMAGE_INTEGER_VALUE
, 0},
6545 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6546 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6547 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6548 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
6549 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6552 /* Structure describing the image type `gif'. */
6554 static struct image_type gif_type
=
6563 /* Return non-zero if OBJECT is a valid GIF image specification. */
6566 gif_image_p (object
)
6569 struct image_keyword fmt
[GIF_LAST
];
6570 bcopy (gif_format
, fmt
, sizeof fmt
);
6572 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
6575 /* Must specify either the :data or :file keyword. */
6576 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
6579 #endif /* HAVE_GIF || MAC_OS */
6583 #if defined (HAVE_NTGUI) || defined (MAC_OS)
6584 /* avoid conflict with QuickdrawText.h */
6585 #define DrawText gif_DrawText
6586 #include <gif_lib.h>
6589 #else /* HAVE_NTGUI || MAC_OS */
6591 #include <gif_lib.h>
6593 #endif /* HAVE_NTGUI || MAC_OS */
6598 /* GIF library details. */
6599 DEF_IMGLIB_FN (DGifCloseFile
);
6600 DEF_IMGLIB_FN (DGifSlurp
);
6601 DEF_IMGLIB_FN (DGifOpen
);
6602 DEF_IMGLIB_FN (DGifOpenFileName
);
6605 init_gif_functions (void)
6609 if (!(library
= LoadLibrary ("libungif.dll")))
6612 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
6613 LOAD_IMGLIB_FN (library
, DGifSlurp
);
6614 LOAD_IMGLIB_FN (library
, DGifOpen
);
6615 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
6621 #define fn_DGifCloseFile DGifCloseFile
6622 #define fn_DGifSlurp DGifSlurp
6623 #define fn_DGifOpen DGifOpen
6624 #define fn_DGifOpenFileName DGifOpenFileName
6626 #endif /* HAVE_NTGUI */
6628 /* Reading a GIF image from memory
6629 Based on the PNG memory stuff to a certain extent. */
6633 unsigned char *bytes
;
6639 /* Make the current memory source available to gif_read_from_memory.
6640 It's done this way because not all versions of libungif support
6641 a UserData field in the GifFileType structure. */
6642 static gif_memory_source
*current_gif_memory_src
;
6645 gif_read_from_memory (file
, buf
, len
)
6650 gif_memory_source
*src
= current_gif_memory_src
;
6652 if (len
> src
->len
- src
->index
)
6655 bcopy (src
->bytes
+ src
->index
, buf
, len
);
6661 /* Load GIF image IMG for use on frame F. Value is non-zero if
6669 Lisp_Object file
, specified_file
;
6670 Lisp_Object specified_data
;
6671 int rc
, width
, height
, x
, y
, i
;
6673 ColorMapObject
*gif_color_map
;
6674 unsigned long pixel_colors
[256];
6676 struct gcpro gcpro1
;
6678 int ino
, image_left
, image_top
, image_width
, image_height
;
6679 gif_memory_source memsrc
;
6680 unsigned char *raster
;
6682 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6683 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6687 if (NILP (specified_data
))
6689 file
= x_find_image_file (specified_file
);
6690 if (!STRINGP (file
))
6692 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6697 /* Open the GIF file. */
6698 gif
= fn_DGifOpenFileName (SDATA (file
));
6701 image_error ("Cannot open `%s'", file
, Qnil
);
6708 /* Read from memory! */
6709 current_gif_memory_src
= &memsrc
;
6710 memsrc
.bytes
= SDATA (specified_data
);
6711 memsrc
.len
= SBYTES (specified_data
);
6714 gif
= fn_DGifOpen(&memsrc
, gif_read_from_memory
);
6717 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
6723 /* Read entire contents. */
6724 rc
= fn_DGifSlurp (gif
);
6725 if (rc
== GIF_ERROR
)
6727 image_error ("Error reading `%s'", img
->spec
, Qnil
);
6728 fn_DGifCloseFile (gif
);
6733 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
6734 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
6735 if (ino
>= gif
->ImageCount
)
6737 image_error ("Invalid image number `%s' in image `%s'",
6739 fn_DGifCloseFile (gif
);
6744 width
= img
->width
= max (gif
->SWidth
, gif
->Image
.Left
+ gif
->Image
.Width
);
6745 height
= img
->height
= max (gif
->SHeight
, gif
->Image
.Top
+ gif
->Image
.Height
);
6747 /* Create the X image and pixmap. */
6748 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6750 fn_DGifCloseFile (gif
);
6755 /* Allocate colors. */
6756 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
6758 gif_color_map
= gif
->SColorMap
;
6759 init_color_table ();
6760 bzero (pixel_colors
, sizeof pixel_colors
);
6762 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
6764 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
6765 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
6766 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
6767 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6770 #ifdef COLOR_TABLE_SUPPORT
6771 img
->colors
= colors_in_color_table (&img
->ncolors
);
6772 free_color_table ();
6773 #endif /* COLOR_TABLE_SUPPORT */
6775 /* Clear the part of the screen image that are not covered by
6776 the image from the GIF file. Full animated GIF support
6777 requires more than can be done here (see the gif89 spec,
6778 disposal methods). Let's simply assume that the part
6779 not covered by a sub-image is in the frame's background color. */
6780 image_top
= gif
->SavedImages
[ino
].ImageDesc
.Top
;
6781 image_left
= gif
->SavedImages
[ino
].ImageDesc
.Left
;
6782 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
6783 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
6785 for (y
= 0; y
< image_top
; ++y
)
6786 for (x
= 0; x
< width
; ++x
)
6787 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6789 for (y
= image_top
+ image_height
; y
< height
; ++y
)
6790 for (x
= 0; x
< width
; ++x
)
6791 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6793 for (y
= image_top
; y
< image_top
+ image_height
; ++y
)
6795 for (x
= 0; x
< image_left
; ++x
)
6796 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6797 for (x
= image_left
+ image_width
; x
< width
; ++x
)
6798 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
6801 /* Read the GIF image into the X image. We use a local variable
6802 `raster' here because RasterBits below is a char *, and invites
6803 problems with bytes >= 0x80. */
6804 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
6806 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
6808 static int interlace_start
[] = {0, 4, 2, 1};
6809 static int interlace_increment
[] = {8, 8, 4, 2};
6811 int row
= interlace_start
[0];
6815 for (y
= 0; y
< image_height
; y
++)
6817 if (row
>= image_height
)
6819 row
= interlace_start
[++pass
];
6820 while (row
>= image_height
)
6821 row
= interlace_start
[++pass
];
6824 for (x
= 0; x
< image_width
; x
++)
6826 int i
= raster
[(y
* image_width
) + x
];
6827 XPutPixel (ximg
, x
+ image_left
, row
+ image_top
,
6831 row
+= interlace_increment
[pass
];
6836 for (y
= 0; y
< image_height
; ++y
)
6837 for (x
= 0; x
< image_width
; ++x
)
6839 int i
= raster
[y
* image_width
+ x
];
6840 XPutPixel (ximg
, x
+ image_left
, y
+ image_top
, pixel_colors
[i
]);
6844 fn_DGifCloseFile (gif
);
6846 /* Maybe fill in the background field while we have ximg handy. */
6847 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6848 IMAGE_BACKGROUND (img
, f
, ximg
);
6850 /* Put the image into the pixmap, then free the X image and its buffer. */
6851 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6852 x_destroy_x_image (ximg
);
6866 Lisp_Object specified_file
, file
;
6867 Lisp_Object specified_data
;
6869 Boolean graphic_p
, movie_p
, prefer_graphic_p
;
6877 Lisp_Object specified_bg
;
6883 struct gcpro gcpro1
;
6886 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6887 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6889 if (NILP (specified_data
))
6891 /* Read from a file */
6895 err
= find_image_fsspec (specified_file
, &file
, &fss
);
6899 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6904 err
= CanQuickTimeOpenFile (&fss
, kQTFileTypeGIF
, 0,
6905 &graphic_p
, &movie_p
, &prefer_graphic_p
, 0);
6909 if (!graphic_p
&& !movie_p
)
6911 if (prefer_graphic_p
)
6912 return image_load_qt_1 (f
, img
, kQTFileTypeGIF
, &fss
, NULL
);
6913 err
= OpenMovieFile (&fss
, &refnum
, fsRdPerm
);
6916 err
= NewMovieFromFile (&movie
, refnum
, NULL
, NULL
, 0, NULL
);
6917 CloseMovieFile (refnum
);
6920 image_error ("Error reading `%s'", file
, Qnil
);
6926 /* Memory source! */
6928 long file_type_atom
[3];
6930 err
= PtrToHand (SDATA (specified_data
), &dh
, SBYTES (specified_data
));
6933 image_error ("Cannot allocate data handle for `%s'",
6938 file_type_atom
[0] = EndianU32_NtoB (sizeof (long) * 3);
6939 file_type_atom
[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType
);
6940 file_type_atom
[2] = EndianU32_NtoB (kQTFileTypeGIF
);
6941 err
= PtrToHand (&dh
, &dref
, sizeof (Handle
));
6944 err
= PtrAndHand ("\p", dref
, 1);
6946 err
= PtrAndHand (file_type_atom
, dref
, sizeof (long) * 3);
6949 image_error ("Cannot allocate handle data ref for `%s'", img
->spec
, Qnil
);
6952 err
= CanQuickTimeOpenDataRef (dref
, HandleDataHandlerSubType
, &graphic_p
,
6953 &movie_p
, &prefer_graphic_p
, 0);
6957 if (!graphic_p
&& !movie_p
)
6959 if (prefer_graphic_p
)
6963 DisposeHandle (dref
);
6964 success_p
= image_load_qt_1 (f
, img
, kQTFileTypeGIF
, NULL
, dh
);
6968 err
= NewMovieFromDataRef (&movie
, 0, NULL
, dref
,
6969 HandleDataHandlerSubType
);
6970 DisposeHandle (dref
);
6975 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
6976 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
6977 track
= GetMovieIndTrack (movie
, 1);
6978 media
= GetTrackMedia (track
);
6979 nsamples
= GetMediaSampleCount (media
);
6980 if (ino
>= nsamples
)
6982 image_error ("Invalid image number `%s' in image `%s'",
6987 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
6988 if (!STRINGP (specified_bg
) ||
6989 !mac_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6991 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6992 color
.red
= RED16_FROM_ULONG (color
.pixel
);
6993 color
.green
= GREEN16_FROM_ULONG (color
.pixel
);
6994 color
.blue
= BLUE16_FROM_ULONG (color
.pixel
);
6996 GetMovieBox (movie
, &rect
);
6997 width
= img
->width
= rect
.right
- rect
.left
;
6998 height
= img
->height
= rect
.bottom
- rect
.top
;
6999 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7002 SetGWorld (ximg
, NULL
);
7003 bg_color
.red
= color
.red
;
7004 bg_color
.green
= color
.green
;
7005 bg_color
.blue
= color
.blue
;
7006 RGBBackColor (&bg_color
);
7007 SetMovieActive (movie
, TRUE
);
7008 SetMovieGWorld (movie
, ximg
, NULL
);
7009 SampleNumToMediaTime (media
, ino
+ 1, &time
, NULL
);
7010 SetMovieTimeValue (movie
, time
);
7011 MoviesTask (movie
, 0L);
7012 DisposeTrackMedia (media
);
7013 DisposeMovieTrack (track
);
7014 DisposeMovie (movie
);
7017 /* Maybe fill in the background field while we have ximg handy. */
7018 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7019 IMAGE_BACKGROUND (img
, f
, ximg
);
7021 /* Put the image into the pixmap. */
7022 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7023 x_destroy_x_image (ximg
);
7027 image_error ("Cannot open `%s'", file
, Qnil
);
7030 DisposeTrackMedia (media
);
7032 DisposeMovieTrack (track
);
7034 DisposeMovie (movie
);
7041 #endif /* HAVE_GIF */
7045 /***********************************************************************
7047 ***********************************************************************/
7049 #ifdef HAVE_X_WINDOWS
7050 #define HAVE_GHOSTSCRIPT 1
7051 #endif /* HAVE_X_WINDOWS */
7053 /* The symbol `postscript' identifying images of this type. */
7055 Lisp_Object Qpostscript
;
7057 #ifdef HAVE_GHOSTSCRIPT
7059 static int gs_image_p
P_ ((Lisp_Object object
));
7060 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
7061 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7063 /* Keyword symbols. */
7065 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
7067 /* Indices of image specification fields in gs_format, below. */
7069 enum gs_keyword_index
7087 /* Vector of image_keyword structures describing the format
7088 of valid user-defined image specifications. */
7090 static struct image_keyword gs_format
[GS_LAST
] =
7092 {":type", IMAGE_SYMBOL_VALUE
, 1},
7093 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7094 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
7095 {":file", IMAGE_STRING_VALUE
, 1},
7096 {":loader", IMAGE_FUNCTION_VALUE
, 0},
7097 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
7098 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7099 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7100 {":relief", IMAGE_INTEGER_VALUE
, 0},
7101 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7102 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7103 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7104 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7107 /* Structure describing the image type `ghostscript'. */
7109 static struct image_type gs_type
=
7119 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7122 gs_clear_image (f
, img
)
7126 /* IMG->data.ptr_val may contain a recorded colormap. */
7127 xfree (img
->data
.ptr_val
);
7128 x_clear_image (f
, img
);
7132 /* Return non-zero if OBJECT is a valid Ghostscript image
7139 struct image_keyword fmt
[GS_LAST
];
7143 bcopy (gs_format
, fmt
, sizeof fmt
);
7145 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
7148 /* Bounding box must be a list or vector containing 4 integers. */
7149 tem
= fmt
[GS_BOUNDING_BOX
].value
;
7152 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
7153 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
7158 else if (VECTORP (tem
))
7160 if (XVECTOR (tem
)->size
!= 4)
7162 for (i
= 0; i
< 4; ++i
)
7163 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
7173 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7182 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
7183 struct gcpro gcpro1
, gcpro2
;
7185 double in_width
, in_height
;
7186 Lisp_Object pixel_colors
= Qnil
;
7188 /* Compute pixel size of pixmap needed from the given size in the
7189 image specification. Sizes in the specification are in pt. 1 pt
7190 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7192 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
7193 in_width
= XFASTINT (pt_width
) / 72.0;
7194 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
7195 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
7196 in_height
= XFASTINT (pt_height
) / 72.0;
7197 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
7199 /* Create the pixmap. */
7200 xassert (img
->pixmap
== NO_PIXMAP
);
7202 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7204 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7205 img
->width
, img
->height
,
7206 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
7211 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
7215 /* Call the loader to fill the pixmap. It returns a process object
7216 if successful. We do not record_unwind_protect here because
7217 other places in redisplay like calling window scroll functions
7218 don't either. Let the Lisp loader use `unwind-protect' instead. */
7219 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
7221 sprintf (buffer
, "%lu %lu",
7222 (unsigned long) FRAME_X_WINDOW (f
),
7223 (unsigned long) img
->pixmap
);
7224 window_and_pixmap_id
= build_string (buffer
);
7226 sprintf (buffer
, "%lu %lu",
7227 FRAME_FOREGROUND_PIXEL (f
),
7228 FRAME_BACKGROUND_PIXEL (f
));
7229 pixel_colors
= build_string (buffer
);
7231 XSETFRAME (frame
, f
);
7232 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
7234 loader
= intern ("gs-load-image");
7236 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
7237 make_number (img
->width
),
7238 make_number (img
->height
),
7239 window_and_pixmap_id
,
7242 return PROCESSP (img
->data
.lisp_val
);
7246 /* Kill the Ghostscript process that was started to fill PIXMAP on
7247 frame F. Called from XTread_socket when receiving an event
7248 telling Emacs that Ghostscript has finished drawing. */
7251 x_kill_gs_process (pixmap
, f
)
7255 struct image_cache
*c
= FRAME_X_IMAGE_CACHE (f
);
7259 /* Find the image containing PIXMAP. */
7260 for (i
= 0; i
< c
->used
; ++i
)
7261 if (c
->images
[i
]->pixmap
== pixmap
)
7264 /* Should someone in between have cleared the image cache, for
7265 instance, give up. */
7269 /* Kill the GS process. We should have found PIXMAP in the image
7270 cache and its image should contain a process object. */
7272 xassert (PROCESSP (img
->data
.lisp_val
));
7273 Fkill_process (img
->data
.lisp_val
, Qnil
);
7274 img
->data
.lisp_val
= Qnil
;
7276 #if defined (HAVE_X_WINDOWS)
7278 /* On displays with a mutable colormap, figure out the colors
7279 allocated for the image by looking at the pixels of an XImage for
7281 class = FRAME_X_VISUAL (f
)->class;
7282 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
7288 /* Try to get an XImage for img->pixmep. */
7289 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
7290 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
7295 /* Initialize the color table. */
7296 init_color_table ();
7298 /* For each pixel of the image, look its color up in the
7299 color table. After having done so, the color table will
7300 contain an entry for each color used by the image. */
7301 for (y
= 0; y
< img
->height
; ++y
)
7302 for (x
= 0; x
< img
->width
; ++x
)
7304 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
7305 lookup_pixel_color (f
, pixel
);
7308 /* Record colors in the image. Free color table and XImage. */
7309 #ifdef COLOR_TABLE_SUPPORT
7310 img
->colors
= colors_in_color_table (&img
->ncolors
);
7311 free_color_table ();
7313 XDestroyImage (ximg
);
7315 #if 0 /* This doesn't seem to be the case. If we free the colors
7316 here, we get a BadAccess later in x_clear_image when
7317 freeing the colors. */
7318 /* We have allocated colors once, but Ghostscript has also
7319 allocated colors on behalf of us. So, to get the
7320 reference counts right, free them once. */
7322 x_free_colors (f
, img
->colors
, img
->ncolors
);
7326 image_error ("Cannot get X image of `%s'; colors will not be freed",
7331 #endif /* HAVE_X_WINDOWS */
7333 /* Now that we have the pixmap, compute mask and transform the
7334 image if requested. */
7336 postprocess_image (f
, img
);
7340 #endif /* HAVE_GHOSTSCRIPT */
7343 /***********************************************************************
7345 ***********************************************************************/
7349 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
7350 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
7354 return valid_image_p (spec
) ? Qt
: Qnil
;
7358 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
7364 if (valid_image_p (spec
))
7365 id
= lookup_image (SELECTED_FRAME (), spec
);
7368 return make_number (id
);
7371 #endif /* GLYPH_DEBUG != 0 */
7374 /***********************************************************************
7376 ***********************************************************************/
7381 QCascent
= intern (":ascent");
7382 staticpro (&QCascent
);
7383 QCmargin
= intern (":margin");
7384 staticpro (&QCmargin
);
7385 QCrelief
= intern (":relief");
7386 staticpro (&QCrelief
);
7387 QCconversion
= intern (":conversion");
7388 staticpro (&QCconversion
);
7389 QCcolor_symbols
= intern (":color-symbols");
7390 staticpro (&QCcolor_symbols
);
7391 QCheuristic_mask
= intern (":heuristic-mask");
7392 staticpro (&QCheuristic_mask
);
7393 QCindex
= intern (":index");
7394 staticpro (&QCindex
);
7395 QCmatrix
= intern (":matrix");
7396 staticpro (&QCmatrix
);
7397 QCcolor_adjustment
= intern (":color-adjustment");
7398 staticpro (&QCcolor_adjustment
);
7399 QCmask
= intern (":mask");
7400 staticpro (&QCmask
);
7402 Qlaplace
= intern ("laplace");
7403 staticpro (&Qlaplace
);
7404 Qemboss
= intern ("emboss");
7405 staticpro (&Qemboss
);
7406 Qedge_detection
= intern ("edge-detection");
7407 staticpro (&Qedge_detection
);
7408 Qheuristic
= intern ("heuristic");
7409 staticpro (&Qheuristic
);
7410 Qcenter
= intern ("center");
7411 staticpro (&Qcenter
);
7413 Qpostscript
= intern ("postscript");
7414 staticpro (&Qpostscript
);
7415 #ifdef HAVE_GHOSTSCRIPT
7416 QCloader
= intern (":loader");
7417 staticpro (&QCloader
);
7418 QCbounding_box
= intern (":bounding-box");
7419 staticpro (&QCbounding_box
);
7420 QCpt_width
= intern (":pt-width");
7421 staticpro (&QCpt_width
);
7422 QCpt_height
= intern (":pt-height");
7423 staticpro (&QCpt_height
);
7424 #endif /* HAVE_GHOSTSCRIPT */
7426 Qpbm
= intern ("pbm");
7429 Qxbm
= intern ("xbm");
7433 Qxpm
= intern ("xpm");
7437 #if defined (HAVE_JPEG) || defined (MAC_OS)
7438 Qjpeg
= intern ("jpeg");
7442 #if defined (HAVE_TIFF) || defined (MAC_OS)
7443 Qtiff
= intern ("tiff");
7447 #if defined (HAVE_GIF) || defined (MAC_OS)
7448 Qgif
= intern ("gif");
7452 #if defined (HAVE_PNG) || defined (MAC_OS)
7453 Qpng
= intern ("png");
7457 defsubr (&Sclear_image_cache
);
7458 defsubr (&Simage_size
);
7459 defsubr (&Simage_mask_p
);
7463 defsubr (&Slookup_image
);
7466 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
7467 doc
: /* Non-nil means always draw a cross over disabled images.
7468 Disabled images are those having an `:conversion disabled' property.
7469 A cross is always drawn on black & white displays. */);
7470 cross_disabled_images
= 0;
7472 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
7473 doc
: /* List of directories to search for window system bitmap files. */);
7474 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
7476 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
7477 doc
: /* Time after which cached images are removed from the cache.
7478 When an image has not been displayed this many seconds, remove it
7479 from the image cache. Value must be an integer or nil with nil
7480 meaning don't clear the cache. */);
7481 Vimage_cache_eviction_delay
= make_number (30 * 60);
7486 /* Image types that rely on external libraries are loaded dynamically
7487 if the library is available. */
7488 #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn())
7490 #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */
7491 #endif /* HAVE_NTGUI */
7497 Vimage_types
= Qnil
;
7499 define_image_type (&xbm_type
);
7500 define_image_type (&pbm_type
);
7503 IF_LIB_AVAILABLE(init_xpm_functions
)
7504 define_image_type (&xpm_type
);
7507 #if defined (HAVE_JPEG) || defined (MAC_OS)
7508 IF_LIB_AVAILABLE(init_jpeg_functions
)
7509 define_image_type (&jpeg_type
);
7512 #if defined (HAVE_TIFF) || defined (MAC_OS)
7513 IF_LIB_AVAILABLE(init_tiff_functions
)
7514 define_image_type (&tiff_type
);
7517 #if defined (HAVE_GIF) || defined (MAC_OS)
7518 IF_LIB_AVAILABLE(init_gif_functions
)
7519 define_image_type (&gif_type
);
7522 #if defined (HAVE_PNG) || defined (MAC_OS)
7523 IF_LIB_AVAILABLE(init_png_functions
)
7524 define_image_type (&png_type
);
7527 #ifdef HAVE_GHOSTSCRIPT
7528 define_image_type (&gs_type
);
7532 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7535 init_image_func_pointer ();
7540 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
7541 (do not change this comment) */