1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
30 /* This makes the fields of a Display accessible, in Xlib header files. */
32 #define XLIB_ILLEGAL_ACCESS
37 #include "dispextern.h"
38 #include "blockinput.h"
41 #include "character.h"
43 #include "termhooks.h"
48 #include <sys/types.h>
51 #define COLOR_TABLE_SUPPORT 1
53 typedef struct x_bitmap_record Bitmap_Record
;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
57 #define RGB_PIXEL_COLOR unsigned long
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
70 typedef struct w32_bitmap_record Bitmap_Record
;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 /* Functions from w32term.c that depend on XColor (so can't go in w32term.h
84 without modifying lots of files). */
85 extern void x_query_colors (struct frame
*f
, XColor
*colors
, int ncolors
);
86 extern void x_query_color (struct frame
*f
, XColor
*color
);
87 #endif /* HAVE_NTGUI */
91 #include <sys/types.h>
94 #undef COLOR_TABLE_SUPPORT
96 typedef struct ns_bitmap_record Bitmap_Record
;
98 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
101 #define RGB_PIXEL_COLOR unsigned long
104 #define PIX_MASK_RETAIN 0
105 #define PIX_MASK_DRAW 1
107 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
108 #define x_defined_color(f, name, color_def, alloc) \
109 ns_defined_color (f, name, color_def, alloc, 0)
110 #define FRAME_X_SCREEN(f) 0
111 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
115 /* Search path for bitmap files. */
117 Lisp_Object Vx_bitmap_file_path
;
120 static void x_disable_image
P_ ((struct frame
*, struct image
*));
121 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
124 static void init_color_table
P_ ((void));
125 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
126 #ifdef COLOR_TABLE_SUPPORT
127 static void free_color_table
P_ ((void));
128 static unsigned long *colors_in_color_table
P_ ((int *n
));
129 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
132 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
133 id, which is just an int that this section returns. Bitmaps are
134 reference counted so they can be shared among frames.
136 Bitmap indices are guaranteed to be > 0, so a negative number can
137 be used to indicate no bitmap.
139 If you use x_create_bitmap_from_data, then you must keep track of
140 the bitmaps yourself. That is, creating a bitmap from the same
141 data more than once will not be caught. */
146 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
147 Display
*display
; /* not used */
149 int x
, y
; /* not used */
150 unsigned int width
, height
; /* not used */
151 unsigned long plane_mask
; /* not used */
152 int format
; /* not used */
154 #if !USE_MAC_IMAGE_IO
156 xassert (x
== 0 && y
== 0);
159 SetRect (&ri
, 0, 0, width
, height
);
160 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
162 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
165 LockPixels (GetGWorldPixMap (pixmap
));
172 XPutPixel (ximage
, x
, y
, pixel
)
178 if (ximage
->bits_per_pixel
== 32)
179 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
181 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
183 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
184 short depth
= GetPixDepth (pixmap
);
186 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
189 char *base_addr
= GetPixBaseAddr (pixmap
);
190 short row_bytes
= GetPixRowBytes (pixmap
);
192 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
198 char *base_addr
= GetPixBaseAddr (pixmap
);
199 short row_bytes
= GetPixRowBytes (pixmap
);
201 if (pixel
== PIX_MASK_DRAW
)
202 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
204 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
212 GetGWorld (&old_port
, &old_gdh
);
213 SetGWorld (ximage
, NULL
);
215 color
.red
= RED16_FROM_ULONG (pixel
);
216 color
.green
= GREEN16_FROM_ULONG (pixel
);
217 color
.blue
= BLUE16_FROM_ULONG (pixel
);
219 SetCPixel (x
, y
, &color
);
221 SetGWorld (old_port
, old_gdh
);
227 XGetPixel (ximage
, x
, y
)
232 if (ximage
->bits_per_pixel
== 32)
233 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
235 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
237 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
238 short depth
= GetPixDepth (pixmap
);
240 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
243 char *base_addr
= GetPixBaseAddr (pixmap
);
244 short row_bytes
= GetPixRowBytes (pixmap
);
246 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
252 char *base_addr
= GetPixBaseAddr (pixmap
);
253 short row_bytes
= GetPixRowBytes (pixmap
);
255 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
256 return PIX_MASK_DRAW
;
258 return PIX_MASK_RETAIN
;
266 GetGWorld (&old_port
, &old_gdh
);
267 SetGWorld (ximage
, NULL
);
269 GetCPixel (x
, y
, &color
);
271 SetGWorld (old_port
, old_gdh
);
272 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
281 #if !USE_MAC_IMAGE_IO
282 UnlockPixels (GetGWorldPixMap (ximg
));
289 mac_data_provider_release_data (info
, data
, size
)
294 xfree ((void *)data
);
299 mac_create_cg_image_from_image (f
, img
)
304 XImagePtr ximg
= img
->pixmap
;
305 CGDataProviderRef provider
;
311 unsigned long color
, alpha
;
313 for (y
= 0; y
< ximg
->height
; y
++)
314 for (x
= 0; x
< ximg
->width
; x
++)
316 color
= XGetPixel (ximg
, x
, y
);
317 alpha
= XGetPixel (img
->mask
, x
, y
);
318 XPutPixel (ximg
, x
, y
,
319 ARGB_TO_ULONG (alpha
,
320 RED_FROM_ULONG (color
)
321 * alpha
/ PIX_MASK_DRAW
,
322 GREEN_FROM_ULONG (color
)
323 * alpha
/ PIX_MASK_DRAW
,
324 BLUE_FROM_ULONG (color
)
325 * alpha
/ PIX_MASK_DRAW
));
327 xfree (img
->mask
->data
);
328 img
->mask
->data
= NULL
;
331 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
332 ximg
->bytes_per_line
* ximg
->height
,
333 mac_data_provider_release_data
);
335 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
336 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
337 ((img
->mask
? kCGImageAlphaPremultipliedFirst
338 : kCGImageAlphaNoneSkipFirst
)
339 | kCGBitmapByteOrder32Host
),
340 provider
, NULL
, 0, kCGRenderingIntentDefault
);
341 CGDataProviderRelease (provider
);
347 CGImageRef result
= NULL
;
354 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
355 img
->width
, img
->height
, 1);
362 GetGWorld (&old_port
, &old_gdh
);
363 SetGWorld (mask
, NULL
);
364 BackColor (blackColor
); /* Don't mask. */
365 SetRect (&r
, 0, 0, img
->width
, img
->height
);
367 SetGWorld (old_port
, old_gdh
);
372 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
373 GetGWorldPixMap (mask
), &result
);
374 if (mask
!= img
->mask
)
375 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
382 #endif /* USE_CG_DRAWING */
387 XGetImage (Display
*display
, Pixmap pixmap
, int x
, int y
,
388 unsigned int width
, unsigned int height
,
389 unsigned long plane_mask
, int format
)
391 /* TODO: not sure what this function is supposed to do.. */
392 ns_retain_object(pixmap
);
396 /* use with imgs created by ns_image_for_XPM */
398 XGetPixel (XImagePtr ximage
, int x
, int y
)
400 return ns_get_pixel(ximage
, x
, y
);
403 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
404 pixel is assumed to be in form RGB */
406 XPutPixel (XImagePtr ximage
, int x
, int y
, unsigned long pixel
)
408 ns_put_pixel(ximage
, x
, y
, pixel
);
413 /* Functions to access the contents of a bitmap, given an id. */
416 x_bitmap_height (f
, id
)
420 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
424 x_bitmap_width (f
, id
)
428 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
431 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
433 x_bitmap_pixmap (f
, id
)
437 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
441 #ifdef HAVE_X_WINDOWS
443 x_bitmap_mask (f
, id
)
447 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
451 /* Allocate a new bitmap record. Returns index of new record. */
454 x_allocate_bitmap_record (f
)
457 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
460 if (dpyinfo
->bitmaps
== NULL
)
462 dpyinfo
->bitmaps_size
= 10;
464 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
465 dpyinfo
->bitmaps_last
= 1;
469 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
470 return ++dpyinfo
->bitmaps_last
;
472 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
473 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
476 dpyinfo
->bitmaps_size
*= 2;
478 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
479 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
480 return ++dpyinfo
->bitmaps_last
;
483 /* Add one reference to the reference count of the bitmap with id ID. */
486 x_reference_bitmap (f
, id
)
490 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
493 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
496 x_create_bitmap_from_data (f
, bits
, width
, height
)
499 unsigned int width
, height
;
501 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
504 #ifdef HAVE_X_WINDOWS
506 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
507 bits
, width
, height
);
510 #endif /* HAVE_X_WINDOWS */
514 bitmap
= CreateBitmap (width
, height
,
515 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
516 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
520 #endif /* HAVE_NTGUI */
523 void *bitmap
= ns_image_from_XBM(bits
, width
, height
);
528 id
= x_allocate_bitmap_record (f
);
531 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
532 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
535 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
536 dpyinfo
->bitmaps
[id
- 1].height
= height
;
537 dpyinfo
->bitmaps
[id
- 1].width
= width
;
538 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
540 #ifdef HAVE_X_WINDOWS
541 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
542 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
543 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
544 #endif /* HAVE_X_WINDOWS */
547 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
548 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
549 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
550 #endif /* HAVE_NTGUI */
555 /* Create bitmap from file FILE for frame F. */
558 x_create_bitmap_from_file (f
, file
)
562 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
565 return -1; /* W32_TODO : bitmap support */
566 #endif /* HAVE_NTGUI */
570 void *bitmap
= ns_image_from_file(file
);
576 id
= x_allocate_bitmap_record (f
);
577 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
578 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
579 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
580 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
581 dpyinfo
->bitmaps
[id
- 1].height
= ns_image_width(bitmap
);
582 dpyinfo
->bitmaps
[id
- 1].width
= ns_image_height(bitmap
);
583 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
587 #ifdef HAVE_X_WINDOWS
588 unsigned int width
, height
;
590 int xhot
, yhot
, result
, id
;
595 /* Look for an existing bitmap with the same name. */
596 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
598 if (dpyinfo
->bitmaps
[id
].refcount
599 && dpyinfo
->bitmaps
[id
].file
600 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
602 ++dpyinfo
->bitmaps
[id
].refcount
;
607 /* Search bitmap-file-path for the file, if appropriate. */
608 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
613 filename
= (char *) SDATA (found
);
615 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
616 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
617 if (result
!= BitmapSuccess
)
620 id
= x_allocate_bitmap_record (f
);
621 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
622 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
623 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
624 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
625 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
626 dpyinfo
->bitmaps
[id
- 1].height
= height
;
627 dpyinfo
->bitmaps
[id
- 1].width
= width
;
628 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
631 #endif /* HAVE_X_WINDOWS */
637 free_bitmap_record (dpyinfo
, bm
)
638 Display_Info
*dpyinfo
;
641 #ifdef HAVE_X_WINDOWS
642 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
644 XFreePixmap (dpyinfo
->display
, bm
->mask
);
645 #endif /* HAVE_X_WINDOWS */
648 DeleteObject (bm
->pixmap
);
649 #endif /* HAVE_NTGUI */
652 ns_release_object(bm
->img
);
662 /* Remove reference to bitmap with id number ID. */
665 x_destroy_bitmap (f
, id
)
669 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
673 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
675 if (--bm
->refcount
== 0)
678 free_bitmap_record (dpyinfo
, bm
);
684 /* Free all the bitmaps for the display specified by DPYINFO. */
687 x_destroy_all_bitmaps (dpyinfo
)
688 Display_Info
*dpyinfo
;
691 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
693 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
694 if (bm
->refcount
> 0)
695 free_bitmap_record (dpyinfo
, bm
);
697 dpyinfo
->bitmaps_last
= 0;
701 #ifdef HAVE_X_WINDOWS
703 /* Useful functions defined in the section
704 `Image type independent image structures' below. */
706 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
709 unsigned long height
));
711 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
712 int depth
, XImagePtr
*ximg
,
715 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
718 /* Create a mask of a bitmap. Note is this not a perfect mask.
719 It's nicer with some borders in this context */
722 x_create_bitmap_mask (f
, id
)
727 XImagePtr ximg
, mask_img
;
728 unsigned long width
, height
;
731 unsigned long x
, y
, xp
, xm
, yp
, ym
;
734 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
739 pixmap
= x_bitmap_pixmap (f
, id
);
740 width
= x_bitmap_width (f
, id
);
741 height
= x_bitmap_height (f
, id
);
744 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
753 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
758 XDestroyImage (ximg
);
762 bg
= four_corners_best (ximg
, NULL
, width
, height
);
764 for (y
= 0; y
< ximg
->height
; ++y
)
766 for (x
= 0; x
< ximg
->width
; ++x
)
768 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
769 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
770 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
771 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
772 if (XGetPixel (ximg
, x
, y
) == bg
773 && XGetPixel (ximg
, x
, yp
) == bg
774 && XGetPixel (ximg
, x
, ym
) == bg
775 && XGetPixel (ximg
, xp
, y
) == bg
776 && XGetPixel (ximg
, xp
, yp
) == bg
777 && XGetPixel (ximg
, xp
, ym
) == bg
778 && XGetPixel (ximg
, xm
, y
) == bg
779 && XGetPixel (ximg
, xm
, yp
) == bg
780 && XGetPixel (ximg
, xm
, ym
) == bg
)
781 XPutPixel (mask_img
, x
, y
, 0);
783 XPutPixel (mask_img
, x
, y
, 1);
787 xassert (interrupt_input_blocked
);
788 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
789 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
791 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
793 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
794 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
796 XDestroyImage (ximg
);
797 x_destroy_x_image (mask_img
);
802 #endif /* HAVE_X_WINDOWS */
805 /***********************************************************************
807 ***********************************************************************/
809 /* Value is the number of elements of vector VECTOR. */
811 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
813 /* List of supported image types. Use define_image_type to add new
814 types. Use lookup_image_type to find a type for a given symbol. */
816 static struct image_type
*image_types
;
818 /* A list of symbols, one for each supported image type. */
820 Lisp_Object Vimage_types
;
822 /* An alist of image types and libraries that implement the type. */
824 Lisp_Object Vimage_library_alist
;
826 /* Cache for delayed-loading image types. */
828 static Lisp_Object Vimage_type_cache
;
830 /* The symbol `xbm' which is used as the type symbol for XBM images. */
836 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
837 extern Lisp_Object QCdata
, QCtype
;
838 extern Lisp_Object Qcenter
;
839 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
840 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
841 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
845 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
847 /* Time in seconds after which images should be removed from the cache
850 Lisp_Object Vimage_cache_eviction_delay
;
852 /* Function prototypes. */
854 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
855 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
856 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
857 static void x_laplace
P_ ((struct frame
*, struct image
*));
858 static void x_emboss
P_ ((struct frame
*, struct image
*));
859 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
862 #define CACHE_IMAGE_TYPE(type, status) \
863 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
865 #define ADD_IMAGE_TYPE(type) \
866 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
868 /* Define a new image type from TYPE. This adds a copy of TYPE to
869 image_types and caches the loading status of TYPE. */
872 define_image_type (type
, loaded
)
873 struct image_type
*type
;
882 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
883 The initialized data segment is read-only. */
884 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
885 bcopy (type
, p
, sizeof *p
);
886 p
->next
= image_types
;
891 CACHE_IMAGE_TYPE (*type
->type
, success
);
896 /* Look up image type SYMBOL, and return a pointer to its image_type
897 structure. Value is null if SYMBOL is not a known image type. */
899 static INLINE
struct image_type
*
900 lookup_image_type (symbol
)
903 struct image_type
*type
;
905 /* We must initialize the image-type if it hasn't been already. */
906 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
907 return 0; /* unimplemented */
909 for (type
= image_types
; type
; type
= type
->next
)
910 if (EQ (symbol
, *type
->type
))
917 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
918 valid image specification is a list whose car is the symbol
919 `image', and whose rest is a property list. The property list must
920 contain a value for key `:type'. That value must be the name of a
921 supported image type. The rest of the property list depends on the
925 valid_image_p (object
)
934 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
935 if (EQ (XCAR (tem
), QCtype
))
938 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
940 struct image_type
*type
;
941 type
= lookup_image_type (XCAR (tem
));
943 valid_p
= type
->valid_p (object
);
954 /* Log error message with format string FORMAT and argument ARG.
955 Signaling an error, e.g. when an image cannot be loaded, is not a
956 good idea because this would interrupt redisplay, and the error
957 message display would lead to another redisplay. This function
958 therefore simply displays a message. */
961 image_error (format
, arg1
, arg2
)
963 Lisp_Object arg1
, arg2
;
965 add_to_log (format
, arg1
, arg2
);
970 /***********************************************************************
972 ***********************************************************************/
974 enum image_value_type
976 IMAGE_DONT_CHECK_VALUE_TYPE
,
978 IMAGE_STRING_OR_NIL_VALUE
,
980 IMAGE_POSITIVE_INTEGER_VALUE
,
981 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
982 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
985 IMAGE_FUNCTION_VALUE
,
990 /* Structure used when parsing image specifications. */
994 /* Name of keyword. */
997 /* The type of value allowed. */
998 enum image_value_type type
;
1000 /* Non-zero means key must be present. */
1003 /* Used to recognize duplicate keywords in a property list. */
1006 /* The value that was found. */
1011 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
1013 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
1016 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1017 has the format (image KEYWORD VALUE ...). One of the keyword/
1018 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1019 image_keywords structures of size NKEYWORDS describing other
1020 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1023 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1025 struct image_keyword
*keywords
;
1035 plist
= XCDR (spec
);
1036 while (CONSP (plist
))
1038 Lisp_Object key
, value
;
1040 /* First element of a pair must be a symbol. */
1042 plist
= XCDR (plist
);
1046 /* There must follow a value. */
1049 value
= XCAR (plist
);
1050 plist
= XCDR (plist
);
1052 /* Find key in KEYWORDS. Error if not found. */
1053 for (i
= 0; i
< nkeywords
; ++i
)
1054 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1060 /* Record that we recognized the keyword. If a keywords
1061 was found more than once, it's an error. */
1062 keywords
[i
].value
= value
;
1063 ++keywords
[i
].count
;
1065 if (keywords
[i
].count
> 1)
1068 /* Check type of value against allowed type. */
1069 switch (keywords
[i
].type
)
1071 case IMAGE_STRING_VALUE
:
1072 if (!STRINGP (value
))
1076 case IMAGE_STRING_OR_NIL_VALUE
:
1077 if (!STRINGP (value
) && !NILP (value
))
1081 case IMAGE_SYMBOL_VALUE
:
1082 if (!SYMBOLP (value
))
1086 case IMAGE_POSITIVE_INTEGER_VALUE
:
1087 if (!INTEGERP (value
) || XINT (value
) <= 0)
1091 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1092 if (INTEGERP (value
) && XINT (value
) >= 0)
1095 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1096 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1100 case IMAGE_ASCENT_VALUE
:
1101 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1103 else if (INTEGERP (value
)
1104 && XINT (value
) >= 0
1105 && XINT (value
) <= 100)
1109 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1110 if (!INTEGERP (value
) || XINT (value
) < 0)
1114 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1117 case IMAGE_FUNCTION_VALUE
:
1118 value
= indirect_function (value
);
1120 || COMPILEDP (value
)
1121 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1125 case IMAGE_NUMBER_VALUE
:
1126 if (!INTEGERP (value
) && !FLOATP (value
))
1130 case IMAGE_INTEGER_VALUE
:
1131 if (!INTEGERP (value
))
1135 case IMAGE_BOOL_VALUE
:
1136 if (!NILP (value
) && !EQ (value
, Qt
))
1145 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1149 /* Check that all mandatory fields are present. */
1150 for (i
= 0; i
< nkeywords
; ++i
)
1151 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1154 return NILP (plist
);
1158 /* Return the value of KEY in image specification SPEC. Value is nil
1159 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1160 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1163 image_spec_value (spec
, key
, found
)
1164 Lisp_Object spec
, key
;
1169 xassert (valid_image_p (spec
));
1171 for (tail
= XCDR (spec
);
1172 CONSP (tail
) && CONSP (XCDR (tail
));
1173 tail
= XCDR (XCDR (tail
)))
1175 if (EQ (XCAR (tail
), key
))
1179 return XCAR (XCDR (tail
));
1189 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1190 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1191 PIXELS non-nil means return the size in pixels, otherwise return the
1192 size in canonical character units.
1193 FRAME is the frame on which the image will be displayed. FRAME nil
1194 or omitted means use the selected frame. */)
1195 (spec
, pixels
, frame
)
1196 Lisp_Object spec
, pixels
, frame
;
1201 if (valid_image_p (spec
))
1203 struct frame
*f
= check_x_frame (frame
);
1204 int id
= lookup_image (f
, spec
);
1205 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1206 int width
= img
->width
+ 2 * img
->hmargin
;
1207 int height
= img
->height
+ 2 * img
->vmargin
;
1210 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1211 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1213 size
= Fcons (make_number (width
), make_number (height
));
1216 error ("Invalid image specification");
1222 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1223 doc
: /* Return t if image SPEC has a mask bitmap.
1224 FRAME is the frame on which the image will be displayed. FRAME nil
1225 or omitted means use the selected frame. */)
1227 Lisp_Object spec
, frame
;
1232 if (valid_image_p (spec
))
1234 struct frame
*f
= check_x_frame (frame
);
1235 int id
= lookup_image (f
, spec
);
1236 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1241 error ("Invalid image specification");
1246 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1247 doc
: /* Return extension data for image SPEC.
1248 FRAME is the frame on which the image will be displayed. FRAME nil
1249 or omitted means use the selected frame. */)
1251 Lisp_Object spec
, frame
;
1256 if (valid_image_p (spec
))
1258 struct frame
*f
= check_x_frame (frame
);
1259 int id
= lookup_image (f
, spec
);
1260 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1261 ext
= img
->data
.lisp_val
;
1268 /***********************************************************************
1269 Image type independent image structures
1270 ***********************************************************************/
1272 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1273 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1274 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1276 #define MAX_IMAGE_SIZE 6.0
1277 Lisp_Object Vmax_image_size
;
1279 /* Allocate and return a new image structure for image specification
1280 SPEC. SPEC has a hash value of HASH. */
1282 static struct image
*
1283 make_image (spec
, hash
)
1287 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1288 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1290 xassert (valid_image_p (spec
));
1291 bzero (img
, sizeof *img
);
1292 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1293 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1294 xassert (img
->type
!= NULL
);
1296 img
->data
.lisp_val
= Qnil
;
1297 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1299 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1304 /* Free image IMG which was used on frame F, including its resources. */
1313 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1315 /* Remove IMG from the hash table of its cache. */
1317 img
->prev
->next
= img
->next
;
1319 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1322 img
->next
->prev
= img
->prev
;
1324 c
->images
[img
->id
] = NULL
;
1326 /* Free resources, then free IMG. */
1327 img
->type
->free (f
, img
);
1332 /* Return 1 if the given widths and heights are valid for display;
1333 otherwise, return 0. */
1336 check_image_size (f
, width
, height
)
1343 if (width
<= 0 || height
<= 0)
1346 if (INTEGERP (Vmax_image_size
))
1347 w
= h
= XINT (Vmax_image_size
);
1348 else if (FLOATP (Vmax_image_size
))
1352 w
= FRAME_PIXEL_WIDTH (f
);
1353 h
= FRAME_PIXEL_HEIGHT (f
);
1356 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1357 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1358 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1363 return (width
<= w
&& height
<= h
);
1366 /* Prepare image IMG for display on frame F. Must be called before
1367 drawing an image. */
1370 prepare_image_for_display (f
, img
)
1376 /* We're about to display IMG, so set its timestamp to `now'. */
1378 img
->timestamp
= EMACS_SECS (t
);
1380 /* If IMG doesn't have a pixmap yet, load it now, using the image
1381 type dependent loader function. */
1382 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1383 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1388 /* Value is the number of pixels for the ascent of image IMG when
1389 drawn in face FACE. */
1392 image_ascent (img
, face
, slice
)
1395 struct glyph_slice
*slice
;
1400 if (slice
->height
== img
->height
)
1401 height
= img
->height
+ img
->vmargin
;
1402 else if (slice
->y
== 0)
1403 height
= slice
->height
+ img
->vmargin
;
1405 height
= slice
->height
;
1407 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1412 /* W32 specific version. Why?. ++kfs */
1413 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1414 - FONT_BASE (face
->font
)) / 2;
1416 /* This expression is arranged so that if the image can't be
1417 exactly centered, it will be moved slightly up. This is
1418 because a typical font is `top-heavy' (due to the presence
1419 uppercase letters), so the image placement should err towards
1420 being top-heavy too. It also just generally looks better. */
1421 ascent
= (height
+ FONT_BASE(face
->font
)
1422 - FONT_DESCENT(face
->font
) + 1) / 2;
1423 #endif /* HAVE_NTGUI */
1426 ascent
= height
/ 2;
1429 ascent
= (int) (height
* img
->ascent
/ 100.0);
1435 /* Image background colors. */
1437 /* Find the "best" corner color of a bitmap.
1438 On W32, XIMG is assumed to a device context with the bitmap selected. */
1440 static RGB_PIXEL_COLOR
1441 four_corners_best (ximg
, corners
, width
, height
)
1442 XImagePtr_or_DC ximg
;
1444 unsigned long width
, height
;
1446 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1449 if (corners
&& corners
[BOT_CORNER
] >= 0)
1451 /* Get the colors at the corner_pixels of ximg. */
1452 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1453 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1454 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1455 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1459 /* Get the colors at the corner_pixels of ximg. */
1460 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1461 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1462 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1463 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1465 /* Choose the most frequently found color as background. */
1466 for (i
= best_count
= 0; i
< 4; ++i
)
1470 for (j
= n
= 0; j
< 4; ++j
)
1471 if (corner_pixels
[i
] == corner_pixels
[j
])
1475 best
= corner_pixels
[i
], best_count
= n
;
1481 /* Portability macros */
1485 #define Destroy_Image(img_dc, prev) \
1486 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1488 #define Free_Pixmap(display, pixmap) \
1489 DeleteObject (pixmap)
1491 #elif defined (HAVE_NS)
1493 #define Destroy_Image(ximg, dummy) \
1494 ns_release_object(ximg)
1496 #define Free_Pixmap(display, pixmap) \
1497 ns_release_object(pixmap)
1501 #define Destroy_Image(ximg, dummy) \
1502 XDestroyImage (ximg)
1504 #define Free_Pixmap(display, pixmap) \
1505 XFreePixmap (display, pixmap)
1507 #endif /* !HAVE_NTGUI && !HAVE_NS */
1510 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1511 it is guessed heuristically. If non-zero, XIMG is an existing
1512 XImage object (or device context with the image selected on W32) to
1513 use for the heuristic. */
1516 image_background (img
, f
, ximg
)
1519 XImagePtr_or_DC ximg
;
1521 if (! img
->background_valid
)
1522 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1524 int free_ximg
= !ximg
;
1527 #endif /* HAVE_NTGUI */
1532 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1533 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1535 HDC frame_dc
= get_frame_dc (f
);
1536 ximg
= CreateCompatibleDC (frame_dc
);
1537 release_frame_dc (f
, frame_dc
);
1538 prev
= SelectObject (ximg
, img
->pixmap
);
1539 #endif /* !HAVE_NTGUI */
1542 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1545 Destroy_Image (ximg
, prev
);
1547 img
->background_valid
= 1;
1550 return img
->background
;
1553 /* Return the `background_transparent' field of IMG. If IMG doesn't
1554 have one yet, it is guessed heuristically. If non-zero, MASK is an
1555 existing XImage object to use for the heuristic. */
1558 image_background_transparent (img
, f
, mask
)
1561 XImagePtr_or_DC mask
;
1563 if (! img
->background_transparent_valid
)
1564 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1568 int free_mask
= !mask
;
1571 #endif /* HAVE_NTGUI */
1576 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1577 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1579 HDC frame_dc
= get_frame_dc (f
);
1580 mask
= CreateCompatibleDC (frame_dc
);
1581 release_frame_dc (f
, frame_dc
);
1582 prev
= SelectObject (mask
, img
->mask
);
1583 #endif /* HAVE_NTGUI */
1586 img
->background_transparent
1587 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1590 Destroy_Image (mask
, prev
);
1593 img
->background_transparent
= 0;
1595 img
->background_transparent_valid
= 1;
1598 return img
->background_transparent
;
1602 /***********************************************************************
1603 Helper functions for X image types
1604 ***********************************************************************/
1606 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1608 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1609 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1611 Lisp_Object color_name
,
1612 unsigned long dflt
));
1615 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1616 free the pixmap if any. MASK_P non-zero means clear the mask
1617 pixmap if any. COLORS_P non-zero means free colors allocated for
1618 the image, if any. */
1621 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1624 int pixmap_p
, mask_p
, colors_p
;
1626 if (pixmap_p
&& img
->pixmap
)
1628 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1629 img
->pixmap
= NO_PIXMAP
;
1630 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1631 img
->background_valid
= 0;
1634 if (mask_p
&& img
->mask
)
1636 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1637 img
->mask
= NO_PIXMAP
;
1638 img
->background_transparent_valid
= 0;
1641 if (colors_p
&& img
->ncolors
)
1643 /* W32_TODO: color table support. */
1644 #ifdef HAVE_X_WINDOWS
1645 x_free_colors (f
, img
->colors
, img
->ncolors
);
1646 #endif /* HAVE_X_WINDOWS */
1647 xfree (img
->colors
);
1654 /* Free X resources of image IMG which is used on frame F. */
1657 x_clear_image (f
, img
)
1662 x_clear_image_1 (f
, img
, 1, 1, 1);
1667 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1668 cannot be allocated, use DFLT. Add a newly allocated color to
1669 IMG->colors, so that it can be freed again. Value is the pixel
1672 static unsigned long
1673 x_alloc_image_color (f
, img
, color_name
, dflt
)
1676 Lisp_Object color_name
;
1680 unsigned long result
;
1682 xassert (STRINGP (color_name
));
1684 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1686 /* This isn't called frequently so we get away with simply
1687 reallocating the color vector to the needed size, here. */
1690 (unsigned long *) xrealloc (img
->colors
,
1691 img
->ncolors
* sizeof *img
->colors
);
1692 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1693 result
= color
.pixel
;
1703 /***********************************************************************
1705 ***********************************************************************/
1707 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1708 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1709 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1711 /* Return a new, initialized image cache that is allocated from the
1712 heap. Call free_image_cache to free an image cache. */
1714 struct image_cache
*
1717 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1720 bzero (c
, sizeof *c
);
1722 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1723 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1724 c
->buckets
= (struct image
**) xmalloc (size
);
1725 bzero (c
->buckets
, size
);
1730 /* Find an image matching SPEC in the cache, and return it. If no
1731 image is found, return NULL. */
1732 static struct image
*
1733 search_image_cache (f
, spec
, hash
)
1739 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1740 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1742 if (!c
) return NULL
;
1744 /* If the image spec does not specify a background color, the cached
1745 image must have the same background color as the current frame.
1746 The foreground color must also match, for the sake of monochrome
1749 In fact, we could ignore the foreground color matching condition
1750 for color images, or if the image spec specifies :foreground;
1751 similarly we could ignore the background color matching condition
1752 for formats that don't use transparency (such as jpeg), or if the
1753 image spec specifies :background. However, the extra memory
1754 usage is probably negligible in practice, so we don't bother. */
1756 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1757 if (img
->hash
== hash
1758 && !NILP (Fequal (img
->spec
, spec
))
1759 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1760 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1766 /* Search frame F for an image with spec SPEC, and free it. */
1769 uncache_image (f
, spec
)
1773 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1775 free_image (f
, img
);
1779 /* Free image cache of frame F. Be aware that X frames share images
1783 free_image_cache (f
)
1786 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1791 /* Cache should not be referenced by any frame when freed. */
1792 xassert (c
->refcount
== 0);
1794 for (i
= 0; i
< c
->used
; ++i
)
1795 free_image (f
, c
->images
[i
]);
1799 FRAME_IMAGE_CACHE (f
) = NULL
;
1804 /* Clear image cache of frame F. FILTER=t means free all images.
1805 FILTER=nil means clear only images that haven't been
1806 displayed for some time.
1807 Else, only free the images which have FILTER in their `dependencies'.
1808 Should be called from time to time to reduce the number of loaded images.
1809 If image-cache-eviction-delay is non-nil, this frees images in the cache
1810 which weren't displayed for at least that many seconds. */
1813 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1815 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1817 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1824 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1826 /* Block input so that we won't be interrupted by a SIGIO
1827 while being in an inconsistent state. */
1830 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1832 struct image
*img
= c
->images
[i
];
1834 && (NILP (filter
) ? img
->timestamp
< old
1836 || !NILP (Fmember (filter
, img
->dependencies
)))))
1838 free_image (f
, img
);
1843 /* We may be clearing the image cache because, for example,
1844 Emacs was iconified for a longer period of time. In that
1845 case, current matrices may still contain references to
1846 images freed above. So, clear these matrices. */
1849 Lisp_Object tail
, frame
;
1851 FOR_EACH_FRAME (tail
, frame
)
1853 struct frame
*f
= XFRAME (frame
);
1854 if (FRAME_IMAGE_CACHE (f
) == c
)
1855 clear_current_matrices (f
);
1858 ++windows_or_buffers_changed
;
1866 clear_image_caches (Lisp_Object filter
)
1868 /* FIXME: We want to do
1869 * struct terminal *t;
1870 * for (t = terminal_list; t; t = t->next_terminal)
1871 * clear_image_cache (t, filter); */
1872 Lisp_Object tail
, frame
;
1873 FOR_EACH_FRAME (tail
, frame
)
1874 if (FRAME_WINDOW_P (XFRAME (frame
)))
1875 clear_image_cache (XFRAME (frame
), filter
);
1878 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1880 doc
: /* Clear the image cache.
1881 FILTER nil or a frame means clear all images in the selected frame.
1882 FILTER t means clear the image caches of all frames.
1883 Anything else, means only clear those images which refer to FILTER,
1884 which is then usually a filename. */)
1888 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1889 clear_image_caches (filter
);
1891 clear_image_cache (check_x_frame (filter
), Qt
);
1897 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1899 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1900 If SPEC specifies an image file, the displayed image is updated with
1901 the current contents of that file.
1902 FRAME nil or omitted means use the selected frame.
1903 FRAME t means refresh the image on all frames. */)
1905 Lisp_Object spec
, frame
;
1907 if (!valid_image_p (spec
))
1908 error ("Invalid image specification");
1913 FOR_EACH_FRAME (tail
, frame
)
1915 struct frame
*f
= XFRAME (frame
);
1916 if (FRAME_WINDOW_P (f
))
1917 uncache_image (f
, spec
);
1921 uncache_image (check_x_frame (frame
), spec
);
1927 /* Compute masks and transform image IMG on frame F, as specified
1928 by the image's specification, */
1931 postprocess_image (f
, img
)
1935 /* Manipulation of the image's mask. */
1938 Lisp_Object conversion
, spec
;
1943 /* `:heuristic-mask t'
1945 means build a mask heuristically.
1946 `:heuristic-mask (R G B)'
1947 `:mask (heuristic (R G B))'
1948 means build a mask from color (R G B) in the
1951 means remove a mask, if any. */
1953 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1955 x_build_heuristic_mask (f
, img
, mask
);
1960 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1962 if (EQ (mask
, Qheuristic
))
1963 x_build_heuristic_mask (f
, img
, Qt
);
1964 else if (CONSP (mask
)
1965 && EQ (XCAR (mask
), Qheuristic
))
1967 if (CONSP (XCDR (mask
)))
1968 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1970 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1972 else if (NILP (mask
) && found_p
&& img
->mask
)
1974 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1975 img
->mask
= NO_PIXMAP
;
1980 /* Should we apply an image transformation algorithm? */
1981 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1982 if (EQ (conversion
, Qdisabled
))
1983 x_disable_image (f
, img
);
1984 else if (EQ (conversion
, Qlaplace
))
1986 else if (EQ (conversion
, Qemboss
))
1988 else if (CONSP (conversion
)
1989 && EQ (XCAR (conversion
), Qedge_detection
))
1992 tem
= XCDR (conversion
);
1994 x_edge_detection (f
, img
,
1995 Fplist_get (tem
, QCmatrix
),
1996 Fplist_get (tem
, QCcolor_adjustment
));
2002 /* Return the id of image with Lisp specification SPEC on frame F.
2003 SPEC must be a valid Lisp image specification (see valid_image_p). */
2006 lookup_image (f
, spec
)
2010 struct image_cache
*c
;
2013 struct gcpro gcpro1
;
2016 /* F must be a window-system frame, and SPEC must be a valid image
2018 xassert (FRAME_WINDOW_P (f
));
2019 xassert (valid_image_p (spec
));
2021 c
= FRAME_IMAGE_CACHE (f
);
2025 /* Look up SPEC in the hash table of the image cache. */
2026 hash
= sxhash (spec
, 0);
2027 img
= search_image_cache (f
, spec
, hash
);
2028 if (img
&& img
->load_failed_p
)
2030 free_image (f
, img
);
2034 /* If not found, create a new image and cache it. */
2037 extern Lisp_Object Qpostscript
;
2040 img
= make_image (spec
, hash
);
2041 cache_image (f
, img
);
2042 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2043 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2044 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2046 /* If we can't load the image, and we don't have a width and
2047 height, use some arbitrary width and height so that we can
2048 draw a rectangle for it. */
2049 if (img
->load_failed_p
)
2053 value
= image_spec_value (spec
, QCwidth
, NULL
);
2054 img
->width
= (INTEGERP (value
)
2055 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2056 value
= image_spec_value (spec
, QCheight
, NULL
);
2057 img
->height
= (INTEGERP (value
)
2058 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2062 /* Handle image type independent image attributes
2063 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2064 `:background COLOR'. */
2065 Lisp_Object ascent
, margin
, relief
, bg
;
2067 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2068 if (INTEGERP (ascent
))
2069 img
->ascent
= XFASTINT (ascent
);
2070 else if (EQ (ascent
, Qcenter
))
2071 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2073 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2074 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2075 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2076 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2077 && INTEGERP (XCDR (margin
)))
2079 if (XINT (XCAR (margin
)) > 0)
2080 img
->hmargin
= XFASTINT (XCAR (margin
));
2081 if (XINT (XCDR (margin
)) > 0)
2082 img
->vmargin
= XFASTINT (XCDR (margin
));
2085 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2086 if (INTEGERP (relief
))
2088 img
->relief
= XINT (relief
);
2089 img
->hmargin
+= eabs (img
->relief
);
2090 img
->vmargin
+= eabs (img
->relief
);
2093 if (! img
->background_valid
)
2095 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2099 = x_alloc_image_color (f
, img
, bg
,
2100 FRAME_BACKGROUND_PIXEL (f
));
2101 img
->background_valid
= 1;
2105 /* Do image transformations and compute masks, unless we
2106 don't have the image yet. */
2107 if (!EQ (*img
->type
->type
, Qpostscript
))
2108 postprocess_image (f
, img
);
2114 /* We're using IMG, so set its timestamp to `now'. */
2115 EMACS_GET_TIME (now
);
2116 img
->timestamp
= EMACS_SECS (now
);
2120 /* Value is the image id. */
2125 /* Cache image IMG in the image cache of frame F. */
2128 cache_image (f
, img
)
2132 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2135 /* Find a free slot in c->images. */
2136 for (i
= 0; i
< c
->used
; ++i
)
2137 if (c
->images
[i
] == NULL
)
2140 /* If no free slot found, maybe enlarge c->images. */
2141 if (i
== c
->used
&& c
->used
== c
->size
)
2144 c
->images
= (struct image
**) xrealloc (c
->images
,
2145 c
->size
* sizeof *c
->images
);
2148 /* Add IMG to c->images, and assign IMG an id. */
2154 /* Add IMG to the cache's hash table. */
2155 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2156 img
->next
= c
->buckets
[i
];
2158 img
->next
->prev
= img
;
2160 c
->buckets
[i
] = img
;
2164 /* Call FN on every image in the image cache of frame F. Used to mark
2165 Lisp Objects in the image cache. */
2167 /* Mark Lisp objects in image IMG. */
2173 mark_object (img
->spec
);
2174 mark_object (img
->dependencies
);
2176 if (!NILP (img
->data
.lisp_val
))
2177 mark_object (img
->data
.lisp_val
);
2182 mark_image_cache (struct image_cache
*c
)
2187 for (i
= 0; i
< c
->used
; ++i
)
2189 mark_image (c
->images
[i
]);
2195 /***********************************************************************
2196 X / NS / W32 support code
2197 ***********************************************************************/
2201 /* Macro for defining functions that will be loaded from image DLLs. */
2202 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2204 /* Macro for loading those image functions from the library. */
2205 #define LOAD_IMGLIB_FN(lib,func) { \
2206 fn_##func = (void *) GetProcAddress (lib, #func); \
2207 if (!fn_##func) return 0; \
2210 /* Load a DLL implementing an image type.
2211 The `image-library-alist' variable associates a symbol,
2212 identifying an image type, to a list of possible filenames.
2213 The function returns NULL if no library could be loaded for
2214 the given image type, or if the library was previously loaded;
2215 else the handle of the DLL. */
2217 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2219 HMODULE library
= NULL
;
2221 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2223 Lisp_Object dlls
= Fassq (type
, libraries
);
2226 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2228 CHECK_STRING_CAR (dlls
);
2229 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2237 #endif /* HAVE_NTGUI */
2239 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2240 XImagePtr
*, Pixmap
*));
2241 static void x_destroy_x_image
P_ ((XImagePtr
));
2242 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2245 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2246 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2247 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2248 via xmalloc. Print error messages via image_error if an error
2249 occurs. Value is non-zero if successful.
2251 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2252 should indicate the bit depth of the image. */
2255 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2257 int width
, height
, depth
;
2261 #ifdef HAVE_X_WINDOWS
2262 Display
*display
= FRAME_X_DISPLAY (f
);
2263 Window window
= FRAME_X_WINDOW (f
);
2264 Screen
*screen
= FRAME_X_SCREEN (f
);
2266 xassert (interrupt_input_blocked
);
2269 depth
= DefaultDepthOfScreen (screen
);
2270 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2271 depth
, ZPixmap
, 0, NULL
, width
, height
,
2272 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2275 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2279 /* Allocate image raster. */
2280 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2282 /* Allocate a pixmap of the same size. */
2283 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2284 if (*pixmap
== NO_PIXMAP
)
2286 x_destroy_x_image (*ximg
);
2288 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2293 #endif /* HAVE_X_WINDOWS */
2297 BITMAPINFOHEADER
*header
;
2299 int scanline_width_bits
;
2301 int palette_colors
= 0;
2306 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2307 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2309 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2313 scanline_width_bits
= width
* depth
;
2314 remainder
= scanline_width_bits
% 32;
2317 scanline_width_bits
+= 32 - remainder
;
2319 /* Bitmaps with a depth less than 16 need a palette. */
2320 /* BITMAPINFO structure already contains the first RGBQUAD. */
2322 palette_colors
= 1 << depth
- 1;
2324 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2327 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2331 header
= &((*ximg
)->info
.bmiHeader
);
2332 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2333 header
->biSize
= sizeof (*header
);
2334 header
->biWidth
= width
;
2335 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2336 header
->biPlanes
= 1;
2337 header
->biBitCount
= depth
;
2338 header
->biCompression
= BI_RGB
;
2339 header
->biClrUsed
= palette_colors
;
2341 /* TODO: fill in palette. */
2344 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2345 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2346 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2347 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2348 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2349 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2350 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2351 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2354 hdc
= get_frame_dc (f
);
2356 /* Create a DIBSection and raster array for the bitmap,
2357 and store its handle in *pixmap. */
2358 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2359 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2360 /* casting avoids a GCC warning */
2361 (void **)&((*ximg
)->data
), NULL
, 0);
2363 /* Realize display palette and garbage all frames. */
2364 release_frame_dc (f
, hdc
);
2366 if (*pixmap
== NULL
)
2368 DWORD err
= GetLastError ();
2369 Lisp_Object errcode
;
2370 /* All system errors are < 10000, so the following is safe. */
2371 XSETINT (errcode
, (int) err
);
2372 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2373 x_destroy_x_image (*ximg
);
2379 #endif /* HAVE_NTGUI */
2382 *pixmap
= ns_image_for_XPM(width
, height
, depth
);
2386 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil
, Qnil
);
2395 /* Destroy XImage XIMG. Free XIMG->data. */
2398 x_destroy_x_image (ximg
)
2401 xassert (interrupt_input_blocked
);
2404 #ifdef HAVE_X_WINDOWS
2407 XDestroyImage (ximg
);
2408 #endif /* HAVE_X_WINDOWS */
2410 /* Data will be freed by DestroyObject. */
2413 #endif /* HAVE_NTGUI */
2415 ns_release_object(ximg
);
2416 #endif /* HAVE_NS */
2421 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2422 are width and height of both the image and pixmap. */
2425 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2431 #ifdef HAVE_X_WINDOWS
2434 xassert (interrupt_input_blocked
);
2435 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2436 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2437 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2438 #endif /* HAVE_X_WINDOWS */
2441 #if 0 /* I don't think this is necessary looking at where it is used. */
2442 HDC hdc
= get_frame_dc (f
);
2443 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2444 release_frame_dc (f
, hdc
);
2446 #endif /* HAVE_NTGUI */
2449 xassert (ximg
== pixmap
);
2450 ns_retain_object(ximg
);
2455 /***********************************************************************
2457 ***********************************************************************/
2459 static unsigned char *slurp_file
P_ ((char *, int *));
2462 /* Find image file FILE. Look in data-directory/images, then
2463 x-bitmap-file-path. Value is the encoded full name of the file
2464 found, or nil if not found. */
2467 x_find_image_file (file
)
2470 Lisp_Object file_found
, search_path
;
2471 struct gcpro gcpro1
, gcpro2
;
2475 /* TODO I think this should use something like image-load-path
2476 instead. Unfortunately, that can contain non-string elements. */
2477 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2479 Vx_bitmap_file_path
);
2480 GCPRO2 (file_found
, search_path
);
2482 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2483 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2489 file_found
= ENCODE_FILE (file_found
);
2498 /* Read FILE into memory. Value is a pointer to a buffer allocated
2499 with xmalloc holding FILE's contents. Value is null if an error
2500 occurred. *SIZE is set to the size of the file. */
2502 static unsigned char *
2503 slurp_file (file
, size
)
2508 unsigned char *buf
= NULL
;
2511 if (stat (file
, &st
) == 0
2512 && (fp
= fopen (file
, "rb")) != NULL
2513 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2514 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2535 /***********************************************************************
2537 ***********************************************************************/
2539 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2540 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2541 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2542 unsigned char *, unsigned char *));
2543 static int xbm_image_p
P_ ((Lisp_Object object
));
2544 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2545 unsigned char *, unsigned char *,
2546 int *, int *, unsigned char **));
2547 static int xbm_file_p
P_ ((Lisp_Object
));
2550 /* Indices of image specification fields in xbm_format, below. */
2552 enum xbm_keyword_index
2570 /* Vector of image_keyword structures describing the format
2571 of valid XBM image specifications. */
2573 static struct image_keyword xbm_format
[XBM_LAST
] =
2575 {":type", IMAGE_SYMBOL_VALUE
, 1},
2576 {":file", IMAGE_STRING_VALUE
, 0},
2577 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2578 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2579 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2580 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2581 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2582 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2583 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2584 {":relief", IMAGE_INTEGER_VALUE
, 0},
2585 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2586 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2587 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2590 /* Structure describing the image type XBM. */
2592 static struct image_type xbm_type
=
2601 /* Tokens returned from xbm_scan. */
2610 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2611 A valid specification is a list starting with the symbol `image'
2612 The rest of the list is a property list which must contain an
2615 If the specification specifies a file to load, it must contain
2616 an entry `:file FILENAME' where FILENAME is a string.
2618 If the specification is for a bitmap loaded from memory it must
2619 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2620 WIDTH and HEIGHT are integers > 0. DATA may be:
2622 1. a string large enough to hold the bitmap data, i.e. it must
2623 have a size >= (WIDTH + 7) / 8 * HEIGHT
2625 2. a bool-vector of size >= WIDTH * HEIGHT
2627 3. a vector of strings or bool-vectors, one for each line of the
2630 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2631 may not be specified in this case because they are defined in the
2634 Both the file and data forms may contain the additional entries
2635 `:background COLOR' and `:foreground COLOR'. If not present,
2636 foreground and background of the frame on which the image is
2637 displayed is used. */
2640 xbm_image_p (object
)
2643 struct image_keyword kw
[XBM_LAST
];
2645 bcopy (xbm_format
, kw
, sizeof kw
);
2646 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2649 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2651 if (kw
[XBM_FILE
].count
)
2653 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2656 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2658 /* In-memory XBM file. */
2659 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2667 /* Entries for `:width', `:height' and `:data' must be present. */
2668 if (!kw
[XBM_WIDTH
].count
2669 || !kw
[XBM_HEIGHT
].count
2670 || !kw
[XBM_DATA
].count
)
2673 data
= kw
[XBM_DATA
].value
;
2674 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2675 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2677 /* Check type of data, and width and height against contents of
2683 /* Number of elements of the vector must be >= height. */
2684 if (XVECTOR (data
)->size
< height
)
2687 /* Each string or bool-vector in data must be large enough
2688 for one line of the image. */
2689 for (i
= 0; i
< height
; ++i
)
2691 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2696 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2699 else if (BOOL_VECTOR_P (elt
))
2701 if (XBOOL_VECTOR (elt
)->size
< width
)
2708 else if (STRINGP (data
))
2711 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2714 else if (BOOL_VECTOR_P (data
))
2716 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2727 /* Scan a bitmap file. FP is the stream to read from. Value is
2728 either an enumerator from enum xbm_token, or a character for a
2729 single-character token, or 0 at end of file. If scanning an
2730 identifier, store the lexeme of the identifier in SVAL. If
2731 scanning a number, store its value in *IVAL. */
2734 xbm_scan (s
, end
, sval
, ival
)
2735 unsigned char **s
, *end
;
2743 /* Skip white space. */
2744 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2749 else if (isdigit (c
))
2751 int value
= 0, digit
;
2753 if (c
== '0' && *s
< end
)
2756 if (c
== 'x' || c
== 'X')
2763 else if (c
>= 'a' && c
<= 'f')
2764 digit
= c
- 'a' + 10;
2765 else if (c
>= 'A' && c
<= 'F')
2766 digit
= c
- 'A' + 10;
2769 value
= 16 * value
+ digit
;
2772 else if (isdigit (c
))
2776 && (c
= *(*s
)++, isdigit (c
)))
2777 value
= 8 * value
+ c
- '0';
2784 && (c
= *(*s
)++, isdigit (c
)))
2785 value
= 10 * value
+ c
- '0';
2793 else if (isalpha (c
) || c
== '_')
2797 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2804 else if (c
== '/' && **s
== '*')
2806 /* C-style comment. */
2808 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2822 /* Create a Windows bitmap from X bitmap data. */
2824 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2826 static unsigned char swap_nibble
[16]
2827 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2828 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2829 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2830 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2832 unsigned char *bits
, *p
;
2835 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2836 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2837 bits
= (unsigned char *) alloca (height
* w2
);
2838 bzero (bits
, height
* w2
);
2839 for (i
= 0; i
< height
; i
++)
2842 for (j
= 0; j
< w1
; j
++)
2844 /* Bitswap XBM bytes to match how Windows does things. */
2845 unsigned char c
= *data
++;
2846 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2847 | (swap_nibble
[(c
>>4) & 0xf]));
2850 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2856 convert_mono_to_color_image (f
, img
, foreground
, background
)
2859 COLORREF foreground
, background
;
2861 HDC hdc
, old_img_dc
, new_img_dc
;
2862 HGDIOBJ old_prev
, new_prev
;
2865 hdc
= get_frame_dc (f
);
2866 old_img_dc
= CreateCompatibleDC (hdc
);
2867 new_img_dc
= CreateCompatibleDC (hdc
);
2868 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2869 release_frame_dc (f
, hdc
);
2870 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2871 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2872 /* Windows convention for mono bitmaps is black = background,
2873 white = foreground. */
2874 SetTextColor (new_img_dc
, background
);
2875 SetBkColor (new_img_dc
, foreground
);
2877 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2880 SelectObject (old_img_dc
, old_prev
);
2881 SelectObject (new_img_dc
, new_prev
);
2882 DeleteDC (old_img_dc
);
2883 DeleteDC (new_img_dc
);
2884 DeleteObject (img
->pixmap
);
2885 if (new_pixmap
== 0)
2886 fprintf (stderr
, "Failed to convert image to color.\n");
2888 img
->pixmap
= new_pixmap
;
2891 #define XBM_BIT_SHUFFLE(b) (~(b))
2895 #define XBM_BIT_SHUFFLE(b) (b)
2897 #endif /* HAVE_NTGUI */
2901 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
2905 RGB_PIXEL_COLOR fg
, bg
;
2906 int non_default_colors
;
2910 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2912 /* If colors were specified, transfer the bitmap to a color one. */
2913 if (non_default_colors
)
2914 convert_mono_to_color_image (f
, img
, fg
, bg
);
2916 #elif defined (HAVE_NS)
2917 img
->pixmap
= ns_image_from_XBM(data
, img
->width
, img
->height
);
2921 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2924 img
->width
, img
->height
,
2926 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2927 #endif /* !HAVE_NTGUI && !HAVE_NS */
2932 /* Replacement for XReadBitmapFileData which isn't available under old
2933 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2934 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2935 the image. Return in *DATA the bitmap data allocated with xmalloc.
2936 Value is non-zero if successful. DATA null means just test if
2937 CONTENTS looks like an in-memory XBM file. */
2940 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
2942 unsigned char *contents
, *end
;
2943 int *width
, *height
;
2944 unsigned char **data
;
2946 unsigned char *s
= contents
;
2947 char buffer
[BUFSIZ
];
2950 int bytes_per_line
, i
, nbytes
;
2956 LA1 = xbm_scan (&s, end, buffer, &value)
2958 #define expect(TOKEN) \
2959 if (LA1 != (TOKEN)) \
2964 #define expect_ident(IDENT) \
2965 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2970 *width
= *height
= -1;
2973 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2975 /* Parse defines for width, height and hot-spots. */
2979 expect_ident ("define");
2980 expect (XBM_TK_IDENT
);
2982 if (LA1
== XBM_TK_NUMBER
)
2984 char *p
= strrchr (buffer
, '_');
2985 p
= p
? p
+ 1 : buffer
;
2986 if (strcmp (p
, "width") == 0)
2988 else if (strcmp (p
, "height") == 0)
2991 expect (XBM_TK_NUMBER
);
2994 if (!check_image_size (f
, *width
, *height
))
2996 else if (data
== NULL
)
2999 /* Parse bits. Must start with `static'. */
3000 expect_ident ("static");
3001 if (LA1
== XBM_TK_IDENT
)
3003 if (strcmp (buffer
, "unsigned") == 0)
3006 expect_ident ("char");
3008 else if (strcmp (buffer
, "short") == 0)
3012 if (*width
% 16 && *width
% 16 < 9)
3015 else if (strcmp (buffer
, "char") == 0)
3023 expect (XBM_TK_IDENT
);
3029 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3030 nbytes
= bytes_per_line
* *height
;
3031 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3035 for (i
= 0; i
< nbytes
; i
+= 2)
3038 expect (XBM_TK_NUMBER
);
3040 *p
++ = XBM_BIT_SHUFFLE (val
);
3041 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3042 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3044 if (LA1
== ',' || LA1
== '}')
3052 for (i
= 0; i
< nbytes
; ++i
)
3055 expect (XBM_TK_NUMBER
);
3057 *p
++ = XBM_BIT_SHUFFLE (val
);
3059 if (LA1
== ',' || LA1
== '}')
3084 /* Load XBM image IMG which will be displayed on frame F from buffer
3085 CONTENTS. END is the end of the buffer. Value is non-zero if
3089 xbm_load_image (f
, img
, contents
, end
)
3092 unsigned char *contents
, *end
;
3095 unsigned char *data
;
3098 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3101 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3102 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3103 int non_default_colors
= 0;
3106 xassert (img
->width
> 0 && img
->height
> 0);
3108 /* Get foreground and background colors, maybe allocate colors. */
3109 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3112 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3113 non_default_colors
= 1;
3115 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3118 background
= x_alloc_image_color (f
, img
, value
, background
);
3119 img
->background
= background
;
3120 img
->background_valid
= 1;
3121 non_default_colors
= 1;
3124 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3125 foreground
, background
,
3126 non_default_colors
);
3129 if (img
->pixmap
== NO_PIXMAP
)
3131 x_clear_image (f
, img
);
3132 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3138 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3144 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3151 return (STRINGP (data
)
3152 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3159 /* Fill image IMG which is used on frame F with pixmap data. Value is
3160 non-zero if successful. */
3168 Lisp_Object file_name
;
3170 xassert (xbm_image_p (img
->spec
));
3172 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3173 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3174 if (STRINGP (file_name
))
3177 unsigned char *contents
;
3179 struct gcpro gcpro1
;
3181 file
= x_find_image_file (file_name
);
3183 if (!STRINGP (file
))
3185 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3190 contents
= slurp_file (SDATA (file
), &size
);
3191 if (contents
== NULL
)
3193 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3198 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3203 struct image_keyword fmt
[XBM_LAST
];
3205 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3206 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3207 int non_default_colors
= 0;
3210 int in_memory_file_p
= 0;
3212 /* See if data looks like an in-memory XBM file. */
3213 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3214 in_memory_file_p
= xbm_file_p (data
);
3216 /* Parse the image specification. */
3217 bcopy (xbm_format
, fmt
, sizeof fmt
);
3218 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3221 /* Get specified width, and height. */
3222 if (!in_memory_file_p
)
3224 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3225 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3226 xassert (img
->width
> 0 && img
->height
> 0);
3229 /* Get foreground and background colors, maybe allocate colors. */
3230 if (fmt
[XBM_FOREGROUND
].count
3231 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3233 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3235 non_default_colors
= 1;
3238 if (fmt
[XBM_BACKGROUND
].count
3239 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3241 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3243 non_default_colors
= 1;
3246 if (in_memory_file_p
)
3247 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3256 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3258 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3259 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3261 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3263 bcopy (SDATA (line
), p
, nbytes
);
3265 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3268 else if (STRINGP (data
))
3269 bits
= SDATA (data
);
3271 bits
= XBOOL_VECTOR (data
)->data
;
3277 /* Windows mono bitmaps are reversed compared with X. */
3278 invertedBits
= bits
;
3279 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3281 bits
= (char *) alloca(nbytes
);
3282 for (i
= 0; i
< nbytes
; i
++)
3283 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3286 /* Create the pixmap. */
3288 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3289 foreground
, background
,
3290 non_default_colors
);
3295 image_error ("Unable to create pixmap for XBM image `%s'",
3297 x_clear_image (f
, img
);
3307 /***********************************************************************
3309 ***********************************************************************/
3311 #if defined (HAVE_XPM) || defined (HAVE_NS)
3313 static int xpm_image_p
P_ ((Lisp_Object object
));
3314 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3315 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3317 #endif /* HAVE_XPM || HAVE_NS */
3321 /* Indicate to xpm.h that we don't have Xlib. */
3323 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3324 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3325 #define XColor xpm_XColor
3326 #define XImage xpm_XImage
3327 #define Display xpm_Display
3328 #define PIXEL_ALREADY_TYPEDEFED
3329 #include "X11/xpm.h"
3334 #undef PIXEL_ALREADY_TYPEDEFED
3336 #include "X11/xpm.h"
3337 #endif /* HAVE_NTGUI */
3338 #endif /* HAVE_XPM */
3340 #if defined (HAVE_XPM) || defined (HAVE_NS)
3341 /* The symbol `xpm' identifying XPM-format images. */
3345 /* Indices of image specification fields in xpm_format, below. */
3347 enum xpm_keyword_index
3363 /* Vector of image_keyword structures describing the format
3364 of valid XPM image specifications. */
3366 static struct image_keyword xpm_format
[XPM_LAST
] =
3368 {":type", IMAGE_SYMBOL_VALUE
, 1},
3369 {":file", IMAGE_STRING_VALUE
, 0},
3370 {":data", IMAGE_STRING_VALUE
, 0},
3371 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3372 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3373 {":relief", IMAGE_INTEGER_VALUE
, 0},
3374 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3375 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3376 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3377 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3378 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3381 /* Structure describing the image type XPM. */
3383 static struct image_type xpm_type
=
3392 #ifdef HAVE_X_WINDOWS
3394 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3395 functions for allocating image colors. Our own functions handle
3396 color allocation failures more gracefully than the ones on the XPM
3399 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3400 #define ALLOC_XPM_COLORS
3402 #endif /* HAVE_X_WINDOWS */
3404 #ifdef ALLOC_XPM_COLORS
3406 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3407 static void xpm_free_color_cache
P_ ((void));
3408 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3409 static int xpm_color_bucket
P_ ((char *));
3410 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3413 /* An entry in a hash table used to cache color definitions of named
3414 colors. This cache is necessary to speed up XPM image loading in
3415 case we do color allocations ourselves. Without it, we would need
3416 a call to XParseColor per pixel in the image. */
3418 struct xpm_cached_color
3420 /* Next in collision chain. */
3421 struct xpm_cached_color
*next
;
3423 /* Color definition (RGB and pixel color). */
3430 /* The hash table used for the color cache, and its bucket vector
3433 #define XPM_COLOR_CACHE_BUCKETS 1001
3434 struct xpm_cached_color
**xpm_color_cache
;
3436 /* Initialize the color cache. */
3439 xpm_init_color_cache (f
, attrs
)
3441 XpmAttributes
*attrs
;
3443 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3444 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3445 memset (xpm_color_cache
, 0, nbytes
);
3446 init_color_table ();
3448 if (attrs
->valuemask
& XpmColorSymbols
)
3453 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3454 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3455 attrs
->colorsymbols
[i
].value
, &color
))
3457 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3459 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3464 /* Free the color cache. */
3467 xpm_free_color_cache ()
3469 struct xpm_cached_color
*p
, *next
;
3472 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3473 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3479 xfree (xpm_color_cache
);
3480 xpm_color_cache
= NULL
;
3481 free_color_table ();
3484 /* Return the bucket index for color named COLOR_NAME in the color
3488 xpm_color_bucket (color_name
)
3494 for (s
= color_name
; *s
; ++s
)
3496 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3500 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3501 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3504 static struct xpm_cached_color
*
3505 xpm_cache_color (f
, color_name
, color
, bucket
)
3512 struct xpm_cached_color
*p
;
3515 bucket
= xpm_color_bucket (color_name
);
3517 nbytes
= sizeof *p
+ strlen (color_name
);
3518 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3519 strcpy (p
->name
, color_name
);
3521 p
->next
= xpm_color_cache
[bucket
];
3522 xpm_color_cache
[bucket
] = p
;
3526 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3527 return the cached definition in *COLOR. Otherwise, make a new
3528 entry in the cache and allocate the color. Value is zero if color
3529 allocation failed. */
3532 xpm_lookup_color (f
, color_name
, color
)
3537 struct xpm_cached_color
*p
;
3538 int h
= xpm_color_bucket (color_name
);
3540 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3541 if (strcmp (p
->name
, color_name
) == 0)
3546 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3549 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3551 p
= xpm_cache_color (f
, color_name
, color
, h
);
3553 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3554 with transparency, and it's useful. */
3555 else if (strcmp ("opaque", color_name
) == 0)
3557 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3558 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3559 p
= xpm_cache_color (f
, color_name
, color
, h
);
3566 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3567 CLOSURE is a pointer to the frame on which we allocate the
3568 color. Return in *COLOR the allocated color. Value is non-zero
3572 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3579 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3583 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3584 is a pointer to the frame on which we allocate the color. Value is
3585 non-zero if successful. */
3588 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3598 #endif /* ALLOC_XPM_COLORS */
3603 /* XPM library details. */
3605 DEF_IMGLIB_FN (XpmFreeAttributes
);
3606 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3607 DEF_IMGLIB_FN (XpmReadFileToImage
);
3608 DEF_IMGLIB_FN (XImageFree
);
3611 init_xpm_functions (Lisp_Object libraries
)
3615 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3618 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3619 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3620 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3621 LOAD_IMGLIB_FN (library
, XImageFree
);
3625 #endif /* HAVE_NTGUI */
3628 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3629 for XPM images. Such a list must consist of conses whose car and
3633 xpm_valid_color_symbols_p (color_symbols
)
3634 Lisp_Object color_symbols
;
3636 while (CONSP (color_symbols
))
3638 Lisp_Object sym
= XCAR (color_symbols
);
3640 || !STRINGP (XCAR (sym
))
3641 || !STRINGP (XCDR (sym
)))
3643 color_symbols
= XCDR (color_symbols
);
3646 return NILP (color_symbols
);
3650 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3653 xpm_image_p (object
)
3656 struct image_keyword fmt
[XPM_LAST
];
3657 bcopy (xpm_format
, fmt
, sizeof fmt
);
3658 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3659 /* Either `:file' or `:data' must be present. */
3660 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3661 /* Either no `:color-symbols' or it's a list of conses
3662 whose car and cdr are strings. */
3663 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3664 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3667 #endif /* HAVE_XPM || HAVE_NS */
3669 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3671 x_create_bitmap_from_xpm_data (f
, bits
)
3675 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3677 XpmAttributes attrs
;
3678 Pixmap bitmap
, mask
;
3680 bzero (&attrs
, sizeof attrs
);
3682 attrs
.visual
= FRAME_X_VISUAL (f
);
3683 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3684 attrs
.valuemask
|= XpmVisual
;
3685 attrs
.valuemask
|= XpmColormap
;
3687 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3688 bits
, &bitmap
, &mask
, &attrs
);
3689 if (rc
!= XpmSuccess
)
3691 XpmFreeAttributes (&attrs
);
3695 id
= x_allocate_bitmap_record (f
);
3696 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3697 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3698 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3699 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3700 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3701 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3702 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3703 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3705 XpmFreeAttributes (&attrs
);
3708 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3710 /* Load image IMG which will be displayed on frame F. Value is
3711 non-zero if successful. */
3721 XpmAttributes attrs
;
3722 Lisp_Object specified_file
, color_symbols
;
3725 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3726 #endif /* HAVE_NTGUI */
3728 /* Configure the XPM lib. Use the visual of frame F. Allocate
3729 close colors. Return colors allocated. */
3730 bzero (&attrs
, sizeof attrs
);
3733 attrs
.visual
= FRAME_X_VISUAL (f
);
3734 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3735 attrs
.valuemask
|= XpmVisual
;
3736 attrs
.valuemask
|= XpmColormap
;
3737 #endif /* HAVE_NTGUI */
3739 #ifdef ALLOC_XPM_COLORS
3740 /* Allocate colors with our own functions which handle
3741 failing color allocation more gracefully. */
3742 attrs
.color_closure
= f
;
3743 attrs
.alloc_color
= xpm_alloc_color
;
3744 attrs
.free_colors
= xpm_free_colors
;
3745 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3746 #else /* not ALLOC_XPM_COLORS */
3747 /* Let the XPM lib allocate colors. */
3748 attrs
.valuemask
|= XpmReturnAllocPixels
;
3749 #ifdef XpmAllocCloseColors
3750 attrs
.alloc_close_colors
= 1;
3751 attrs
.valuemask
|= XpmAllocCloseColors
;
3752 #else /* not XpmAllocCloseColors */
3753 attrs
.closeness
= 600;
3754 attrs
.valuemask
|= XpmCloseness
;
3755 #endif /* not XpmAllocCloseColors */
3756 #endif /* ALLOC_XPM_COLORS */
3758 /* If image specification contains symbolic color definitions, add
3759 these to `attrs'. */
3760 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3761 if (CONSP (color_symbols
))
3764 XpmColorSymbol
*xpm_syms
;
3767 attrs
.valuemask
|= XpmColorSymbols
;
3769 /* Count number of symbols. */
3770 attrs
.numsymbols
= 0;
3771 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3774 /* Allocate an XpmColorSymbol array. */
3775 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3776 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3777 bzero (xpm_syms
, size
);
3778 attrs
.colorsymbols
= xpm_syms
;
3780 /* Fill the color symbol array. */
3781 for (tail
= color_symbols
, i
= 0;
3783 ++i
, tail
= XCDR (tail
))
3785 Lisp_Object name
= XCAR (XCAR (tail
));
3786 Lisp_Object color
= XCDR (XCAR (tail
));
3787 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3788 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3789 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3790 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3794 /* Create a pixmap for the image, either from a file, or from a
3795 string buffer containing data in the same format as an XPM file. */
3796 #ifdef ALLOC_XPM_COLORS
3797 xpm_init_color_cache (f
, &attrs
);
3800 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3804 HDC frame_dc
= get_frame_dc (f
);
3805 hdc
= CreateCompatibleDC (frame_dc
);
3806 release_frame_dc (f
, frame_dc
);
3808 #endif /* HAVE_NTGUI */
3810 if (STRINGP (specified_file
))
3812 Lisp_Object file
= x_find_image_file (specified_file
);
3813 if (!STRINGP (file
))
3815 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3820 /* XpmReadFileToPixmap is not available in the Windows port of
3821 libxpm. But XpmReadFileToImage almost does what we want. */
3822 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3823 &xpm_image
, &xpm_mask
,
3826 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3827 SDATA (file
), &img
->pixmap
, &img
->mask
,
3829 #endif /* HAVE_NTGUI */
3833 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3835 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3836 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3837 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3838 &xpm_image
, &xpm_mask
,
3841 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3843 &img
->pixmap
, &img
->mask
,
3845 #endif /* HAVE_NTGUI */
3848 if (rc
== XpmSuccess
)
3850 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3851 img
->colors
= colors_in_color_table (&img
->ncolors
);
3852 #else /* not ALLOC_XPM_COLORS */
3856 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3857 plus some duplicate attributes. */
3858 if (xpm_image
&& xpm_image
->bitmap
)
3860 img
->pixmap
= xpm_image
->bitmap
;
3861 /* XImageFree in libXpm frees XImage struct without destroying
3862 the bitmap, which is what we want. */
3863 fn_XImageFree (xpm_image
);
3865 if (xpm_mask
&& xpm_mask
->bitmap
)
3867 /* The mask appears to be inverted compared with what we expect.
3868 TODO: invert our expectations. See other places where we
3869 have to invert bits because our idea of masks is backwards. */
3871 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3873 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3874 SelectObject (hdc
, old_obj
);
3876 img
->mask
= xpm_mask
->bitmap
;
3877 fn_XImageFree (xpm_mask
);
3882 #endif /* HAVE_NTGUI */
3884 /* Remember allocated colors. */
3885 img
->ncolors
= attrs
.nalloc_pixels
;
3886 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3887 * sizeof *img
->colors
);
3888 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3890 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3891 #ifdef DEBUG_X_COLORS
3892 register_color (img
->colors
[i
]);
3895 #endif /* not ALLOC_XPM_COLORS */
3897 img
->width
= attrs
.width
;
3898 img
->height
= attrs
.height
;
3899 xassert (img
->width
> 0 && img
->height
> 0);
3901 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3903 fn_XpmFreeAttributes (&attrs
);
3905 XpmFreeAttributes (&attrs
);
3906 #endif /* HAVE_NTGUI */
3912 #endif /* HAVE_NTGUI */
3917 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3920 case XpmFileInvalid
:
3921 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3925 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3928 case XpmColorFailed
:
3929 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3933 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3938 #ifdef ALLOC_XPM_COLORS
3939 xpm_free_color_cache ();
3941 return rc
== XpmSuccess
;
3944 #endif /* HAVE_XPM */
3946 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3948 /* XPM support functions for NS where libxpm is not available.
3949 Only XPM version 3 (without any extensions) is supported. */
3951 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
3952 const unsigned char **, int *));
3953 static Lisp_Object xpm_make_color_table_v
3954 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3955 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3956 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
3958 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3959 const unsigned char *, int));
3960 static Lisp_Object xpm_make_color_table_h
3961 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3962 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3963 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
3965 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3966 const unsigned char *, int));
3967 static int xpm_str_to_color_key
P_ ((const char *));
3968 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3969 const unsigned char *, const unsigned char *));
3971 /* Tokens returned from xpm_scan. */
3980 /* Scan an XPM data and return a character (< 256) or a token defined
3981 by enum xpm_token above. *S and END are the start (inclusive) and
3982 the end (exclusive) addresses of the data, respectively. Advance
3983 *S while scanning. If token is either XPM_TK_IDENT or
3984 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3985 length of the corresponding token, respectively. */
3988 xpm_scan (s
, end
, beg
, len
)
3989 const unsigned char **s
, *end
, **beg
;
3996 /* Skip white-space. */
3997 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
4000 /* gnus-pointer.xpm uses '-' in its identifier.
4001 sb-dir-plus.xpm uses '+' in its identifier. */
4002 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4006 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4009 return XPM_TK_IDENT
;
4014 while (*s
< end
&& **s
!= '"')
4019 return XPM_TK_STRING
;
4023 if (*s
< end
&& **s
== '*')
4025 /* C-style comment. */
4029 while (*s
< end
&& *(*s
)++ != '*')
4032 while (*s
< end
&& **s
!= '/');
4046 /* Functions for color table lookup in XPM data. A key is a string
4047 specifying the color of each pixel in XPM data. A value is either
4048 an integer that specifies a pixel color, Qt that specifies
4049 transparency, or Qnil for the unspecified color. If the length of
4050 the key string is one, a vector is used as a table. Otherwise, a
4051 hash table is used. */
4054 xpm_make_color_table_v (put_func
, get_func
)
4055 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4056 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4058 *put_func
= xpm_put_color_table_v
;
4059 *get_func
= xpm_get_color_table_v
;
4060 return Fmake_vector (make_number (256), Qnil
);
4064 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4065 Lisp_Object color_table
;
4066 const unsigned char *chars_start
;
4070 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4074 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4075 Lisp_Object color_table
;
4076 const unsigned char *chars_start
;
4079 return XVECTOR (color_table
)->contents
[*chars_start
];
4083 xpm_make_color_table_h (put_func
, get_func
)
4084 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4085 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4087 *put_func
= xpm_put_color_table_h
;
4088 *get_func
= xpm_get_color_table_h
;
4089 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4090 make_float (DEFAULT_REHASH_SIZE
),
4091 make_float (DEFAULT_REHASH_THRESHOLD
),
4096 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4097 Lisp_Object color_table
;
4098 const unsigned char *chars_start
;
4102 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4104 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4106 hash_lookup (table
, chars
, &hash_code
);
4107 hash_put (table
, chars
, color
, hash_code
);
4111 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4112 Lisp_Object color_table
;
4113 const unsigned char *chars_start
;
4116 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4117 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4120 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4123 enum xpm_color_key
{
4131 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4134 xpm_str_to_color_key (s
)
4140 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4142 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4148 xpm_load_image (f
, img
, contents
, end
)
4151 const unsigned char *contents
, *end
;
4153 const unsigned char *s
= contents
, *beg
, *str
;
4154 unsigned char buffer
[BUFSIZ
];
4155 int width
, height
, x
, y
;
4156 int num_colors
, chars_per_pixel
;
4158 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4159 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4160 Lisp_Object frame
, color_symbols
, color_table
;
4161 int best_key
, have_mask
= 0;
4162 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4165 LA1 = xpm_scan (&s, end, &beg, &len)
4167 #define expect(TOKEN) \
4168 if (LA1 != (TOKEN)) \
4173 #define expect_ident(IDENT) \
4174 if (LA1 == XPM_TK_IDENT \
4175 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4180 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4184 expect_ident ("static");
4185 expect_ident ("char");
4187 expect (XPM_TK_IDENT
);
4192 expect (XPM_TK_STRING
);
4195 memcpy (buffer
, beg
, len
);
4197 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4198 &num_colors
, &chars_per_pixel
) != 4
4199 || width
<= 0 || height
<= 0
4200 || num_colors
<= 0 || chars_per_pixel
<= 0)
4203 if (!check_image_size (f
, width
, height
))
4205 image_error ("Invalid image size", Qnil
, Qnil
);
4211 XSETFRAME (frame
, f
);
4212 if (!NILP (Fxw_display_color_p (frame
)))
4213 best_key
= XPM_COLOR_KEY_C
;
4214 else if (!NILP (Fx_display_grayscale_p (frame
)))
4215 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4216 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4218 best_key
= XPM_COLOR_KEY_M
;
4220 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4221 if (chars_per_pixel
== 1)
4222 color_table
= xpm_make_color_table_v (&put_color_table
,
4225 color_table
= xpm_make_color_table_h (&put_color_table
,
4228 while (num_colors
-- > 0)
4230 unsigned char *color
, *max_color
;
4231 int key
, next_key
, max_key
= 0;
4232 Lisp_Object symbol_color
= Qnil
, color_val
;
4235 expect (XPM_TK_STRING
);
4236 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4238 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4239 buffer
[len
- chars_per_pixel
] = '\0';
4241 str
= strtok (buffer
, " \t");
4244 key
= xpm_str_to_color_key (str
);
4249 color
= strtok (NULL
, " \t");
4253 while ((str
= strtok (NULL
, " \t")) != NULL
)
4255 next_key
= xpm_str_to_color_key (str
);
4258 color
[strlen (color
)] = ' ';
4261 if (key
== XPM_COLOR_KEY_S
)
4263 if (NILP (symbol_color
))
4264 symbol_color
= build_string (color
);
4266 else if (max_key
< key
&& key
<= best_key
)
4276 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4278 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4280 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4282 if (xstrcasecmp (SDATA (XCDR (specified_color
)), "None") == 0)
4284 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4286 color_val
= make_number (cdef
.pixel
);
4289 if (NILP (color_val
) && max_key
> 0)
4291 if (xstrcasecmp (max_color
, "None") == 0)
4293 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4294 color_val
= make_number (cdef
.pixel
);
4296 if (!NILP (color_val
))
4297 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4302 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4303 &ximg
, &img
->pixmap
)
4305 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4306 &mask_img
, &img
->mask
)
4310 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4314 for (y
= 0; y
< height
; y
++)
4316 expect (XPM_TK_STRING
);
4318 if (len
< width
* chars_per_pixel
)
4320 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4322 Lisp_Object color_val
=
4323 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4325 XPutPixel (ximg
, x
, y
,
4326 (INTEGERP (color_val
) ? XINT (color_val
)
4327 : FRAME_FOREGROUND_PIXEL (f
)));
4329 XPutPixel (mask_img
, x
, y
,
4330 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4331 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4333 if (EQ(color_val
, Qt
))
4334 ns_set_alpha(ximg
, x
, y
, 0);
4342 img
->height
= height
;
4344 /* Maybe fill in the background field while we have ximg handy. */
4345 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4346 IMAGE_BACKGROUND (img
, f
, ximg
);
4348 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4349 x_destroy_x_image (ximg
);
4353 /* Fill in the background_transparent field while we have the
4355 image_background_transparent (img
, f
, mask_img
);
4357 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4358 x_destroy_x_image (mask_img
);
4362 x_destroy_x_image (mask_img
);
4363 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4364 img
->mask
= NO_PIXMAP
;
4370 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4372 x_destroy_x_image (ximg
);
4373 x_destroy_x_image (mask_img
);
4374 x_clear_image (f
, img
);
4388 Lisp_Object file_name
;
4390 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4391 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4392 if (STRINGP (file_name
))
4395 unsigned char *contents
;
4397 struct gcpro gcpro1
;
4399 file
= x_find_image_file (file_name
);
4401 if (!STRINGP (file
))
4403 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4408 contents
= slurp_file (SDATA (file
), &size
);
4409 if (contents
== NULL
)
4411 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4416 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4424 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4425 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4426 SDATA (data
) + SBYTES (data
));
4432 #endif /* HAVE_NS && !HAVE_XPM */
4436 /***********************************************************************
4438 ***********************************************************************/
4440 #ifdef COLOR_TABLE_SUPPORT
4442 /* An entry in the color table mapping an RGB color to a pixel color. */
4447 unsigned long pixel
;
4449 /* Next in color table collision list. */
4450 struct ct_color
*next
;
4453 /* The bucket vector size to use. Must be prime. */
4457 /* Value is a hash of the RGB color given by R, G, and B. */
4459 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4461 /* The color hash table. */
4463 struct ct_color
**ct_table
;
4465 /* Number of entries in the color table. */
4467 int ct_colors_allocated
;
4469 /* Initialize the color table. */
4474 int size
= CT_SIZE
* sizeof (*ct_table
);
4475 ct_table
= (struct ct_color
**) xmalloc (size
);
4476 bzero (ct_table
, size
);
4477 ct_colors_allocated
= 0;
4481 /* Free memory associated with the color table. */
4487 struct ct_color
*p
, *next
;
4489 for (i
= 0; i
< CT_SIZE
; ++i
)
4490 for (p
= ct_table
[i
]; p
; p
= next
)
4501 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4502 entry for that color already is in the color table, return the
4503 pixel color of that entry. Otherwise, allocate a new color for R,
4504 G, B, and make an entry in the color table. */
4506 static unsigned long
4507 lookup_rgb_color (f
, r
, g
, b
)
4511 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4512 int i
= hash
% CT_SIZE
;
4514 Display_Info
*dpyinfo
;
4516 /* Handle TrueColor visuals specially, which improves performance by
4517 two orders of magnitude. Freeing colors on TrueColor visuals is
4518 a nop, and pixel colors specify RGB values directly. See also
4519 the Xlib spec, chapter 3.1. */
4520 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4521 if (dpyinfo
->red_bits
> 0)
4523 unsigned long pr
, pg
, pb
;
4525 /* Apply gamma-correction like normal color allocation does. */
4529 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4530 gamma_correct (f
, &color
);
4531 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4534 /* Scale down RGB values to the visual's bits per RGB, and shift
4535 them to the right position in the pixel color. Note that the
4536 original RGB values are 16-bit values, as usual in X. */
4537 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4538 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4539 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4541 /* Assemble the pixel color. */
4542 return pr
| pg
| pb
;
4545 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4546 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4552 #ifdef HAVE_X_WINDOWS
4561 cmap
= FRAME_X_COLORMAP (f
);
4562 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4565 ++ct_colors_allocated
;
4566 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4570 p
->pixel
= color
.pixel
;
4571 p
->next
= ct_table
[i
];
4575 return FRAME_FOREGROUND_PIXEL (f
);
4580 color
= PALETTERGB (r
, g
, b
);
4582 color
= RGB_TO_ULONG (r
, g
, b
);
4583 #endif /* HAVE_NTGUI */
4584 ++ct_colors_allocated
;
4585 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4590 p
->next
= ct_table
[i
];
4592 #endif /* HAVE_X_WINDOWS */
4600 /* Look up pixel color PIXEL which is used on frame F in the color
4601 table. If not already present, allocate it. Value is PIXEL. */
4603 static unsigned long
4604 lookup_pixel_color (f
, pixel
)
4606 unsigned long pixel
;
4608 int i
= pixel
% CT_SIZE
;
4611 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4612 if (p
->pixel
== pixel
)
4621 #ifdef HAVE_X_WINDOWS
4622 cmap
= FRAME_X_COLORMAP (f
);
4623 color
.pixel
= pixel
;
4624 x_query_color (f
, &color
);
4625 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4628 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4629 color
.pixel
= pixel
;
4630 XQueryColor (NULL
, cmap
, &color
);
4631 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4633 #endif /* HAVE_X_WINDOWS */
4637 ++ct_colors_allocated
;
4639 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4644 p
->next
= ct_table
[i
];
4648 return FRAME_FOREGROUND_PIXEL (f
);
4654 /* Value is a vector of all pixel colors contained in the color table,
4655 allocated via xmalloc. Set *N to the number of colors. */
4657 static unsigned long *
4658 colors_in_color_table (n
)
4663 unsigned long *colors
;
4665 if (ct_colors_allocated
== 0)
4672 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4674 *n
= ct_colors_allocated
;
4676 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4677 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4678 colors
[j
++] = p
->pixel
;
4684 #else /* COLOR_TABLE_SUPPORT */
4686 static unsigned long
4687 lookup_rgb_color (f
, r
, g
, b
)
4691 unsigned long pixel
;
4694 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4695 #endif /* HAVE_NTGUI */
4698 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4699 #endif /* HAVE_NS */
4707 #endif /* COLOR_TABLE_SUPPORT */
4710 /***********************************************************************
4712 ***********************************************************************/
4714 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4715 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4716 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4719 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4720 #endif /* HAVE_NTGUI */
4722 /* Non-zero means draw a cross on images having `:conversion
4725 int cross_disabled_images
;
4727 /* Edge detection matrices for different edge-detection
4730 static int emboss_matrix
[9] = {
4732 2, -1, 0, /* y - 1 */
4734 0, 1, -2 /* y + 1 */
4737 static int laplace_matrix
[9] = {
4739 1, 0, 0, /* y - 1 */
4741 0, 0, -1 /* y + 1 */
4744 /* Value is the intensity of the color whose red/green/blue values
4747 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4750 /* On frame F, return an array of XColor structures describing image
4751 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4752 non-zero means also fill the red/green/blue members of the XColor
4753 structures. Value is a pointer to the array of XColors structures,
4754 allocated with xmalloc; it must be freed by the caller. */
4757 x_to_xcolors (f
, img
, rgb_p
)
4764 XImagePtr_or_DC ximg
;
4768 #endif /* HAVE_NTGUI */
4770 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4773 /* Get the X image IMG->pixmap. */
4774 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4775 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4777 /* Load the image into a memory device context. */
4778 hdc
= get_frame_dc (f
);
4779 ximg
= CreateCompatibleDC (hdc
);
4780 release_frame_dc (f
, hdc
);
4781 prev
= SelectObject (ximg
, img
->pixmap
);
4782 #endif /* HAVE_NTGUI */
4784 /* Fill the `pixel' members of the XColor array. I wished there
4785 were an easy and portable way to circumvent XGetPixel. */
4787 for (y
= 0; y
< img
->height
; ++y
)
4791 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4792 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4793 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4795 x_query_colors (f
, row
, img
->width
);
4799 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4801 /* W32_TODO: palette support needed here? */
4802 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4805 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4806 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4807 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4810 #endif /* HAVE_X_WINDOWS */
4813 Destroy_Image (ximg
, prev
);
4820 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4821 created with CreateDIBSection, with the pointer to the bit values
4822 stored in ximg->data. */
4825 XPutPixel (ximg
, x
, y
, color
)
4830 int width
= ximg
->info
.bmiHeader
.biWidth
;
4831 int height
= ximg
->info
.bmiHeader
.biHeight
;
4832 unsigned char * pixel
;
4834 /* True color images. */
4835 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4837 int rowbytes
= width
* 3;
4838 /* Ensure scanlines are aligned on 4 byte boundaries. */
4840 rowbytes
+= 4 - (rowbytes
% 4);
4842 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4843 /* Windows bitmaps are in BGR order. */
4844 *pixel
= GetBValue (color
);
4845 *(pixel
+ 1) = GetGValue (color
);
4846 *(pixel
+ 2) = GetRValue (color
);
4848 /* Monochrome images. */
4849 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4851 int rowbytes
= width
/ 8;
4852 /* Ensure scanlines are aligned on 4 byte boundaries. */
4854 rowbytes
+= 4 - (rowbytes
% 4);
4855 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4856 /* Filter out palette info. */
4857 if (color
& 0x00ffffff)
4858 *pixel
= *pixel
| (1 << x
% 8);
4860 *pixel
= *pixel
& ~(1 << x
% 8);
4863 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4866 #endif /* HAVE_NTGUI */
4868 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4869 RGB members are set. F is the frame on which this all happens.
4870 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4873 x_from_xcolors (f
, img
, colors
)
4879 XImagePtr oimg
= NULL
;
4883 init_color_table ();
4885 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4888 for (y
= 0; y
< img
->height
; ++y
)
4889 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4891 unsigned long pixel
;
4892 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4893 XPutPixel (oimg
, x
, y
, pixel
);
4897 x_clear_image_1 (f
, img
, 1, 0, 1);
4899 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4900 x_destroy_x_image (oimg
);
4901 img
->pixmap
= pixmap
;
4902 #ifdef COLOR_TABLE_SUPPORT
4903 img
->colors
= colors_in_color_table (&img
->ncolors
);
4904 free_color_table ();
4905 #endif /* COLOR_TABLE_SUPPORT */
4909 /* On frame F, perform edge-detection on image IMG.
4911 MATRIX is a nine-element array specifying the transformation
4912 matrix. See emboss_matrix for an example.
4914 COLOR_ADJUST is a color adjustment added to each pixel of the
4918 x_detect_edges (f
, img
, matrix
, color_adjust
)
4921 int matrix
[9], color_adjust
;
4923 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4927 for (i
= sum
= 0; i
< 9; ++i
)
4928 sum
+= eabs (matrix
[i
]);
4930 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4932 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4934 for (y
= 0; y
< img
->height
; ++y
)
4936 p
= COLOR (new, 0, y
);
4937 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4938 p
= COLOR (new, img
->width
- 1, y
);
4939 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4942 for (x
= 1; x
< img
->width
- 1; ++x
)
4944 p
= COLOR (new, x
, 0);
4945 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4946 p
= COLOR (new, x
, img
->height
- 1);
4947 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4950 for (y
= 1; y
< img
->height
- 1; ++y
)
4952 p
= COLOR (new, 1, y
);
4954 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4956 int r
, g
, b
, y1
, x1
;
4959 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4960 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4963 XColor
*t
= COLOR (colors
, x1
, y1
);
4964 r
+= matrix
[i
] * t
->red
;
4965 g
+= matrix
[i
] * t
->green
;
4966 b
+= matrix
[i
] * t
->blue
;
4969 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4970 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4971 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4972 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4977 x_from_xcolors (f
, img
, new);
4983 /* Perform the pre-defined `emboss' edge-detection on image IMG
4991 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
4995 /* Transform image IMG which is used on frame F with a Laplace
4996 edge-detection algorithm. The result is an image that can be used
4997 to draw disabled buttons, for example. */
5004 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5008 /* Perform edge-detection on image IMG on frame F, with specified
5009 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5011 MATRIX must be either
5013 - a list of at least 9 numbers in row-major form
5014 - a vector of at least 9 numbers
5016 COLOR_ADJUST nil means use a default; otherwise it must be a
5020 x_edge_detection (f
, img
, matrix
, color_adjust
)
5023 Lisp_Object matrix
, color_adjust
;
5031 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5032 ++i
, matrix
= XCDR (matrix
))
5033 trans
[i
] = XFLOATINT (XCAR (matrix
));
5035 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5037 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5038 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5041 if (NILP (color_adjust
))
5042 color_adjust
= make_number (0xffff / 2);
5044 if (i
== 9 && NUMBERP (color_adjust
))
5045 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5049 /* Transform image IMG on frame F so that it looks disabled. */
5052 x_disable_image (f
, img
)
5056 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5058 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5060 int n_planes
= dpyinfo
->n_planes
;
5061 #endif /* HAVE_NTGUI */
5065 /* Color (or grayscale). Convert to gray, and equalize. Just
5066 drawing such images with a stipple can look very odd, so
5067 we're using this method instead. */
5068 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5070 const int h
= 15000;
5071 const int l
= 30000;
5073 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5077 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5078 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5079 p
->red
= p
->green
= p
->blue
= i2
;
5082 x_from_xcolors (f
, img
, colors
);
5085 /* Draw a cross over the disabled image, if we must or if we
5087 if (n_planes
< 2 || cross_disabled_images
)
5090 Display
*dpy
= FRAME_X_DISPLAY (f
);
5093 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5095 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5097 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5098 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5099 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5100 img
->width
- 1, img
->height
- 1);
5101 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5107 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5108 XSetForeground (dpy
, gc
, MaskForeground (f
));
5109 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5110 img
->width
- 1, img
->height
- 1);
5111 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5115 #endif /* !HAVE_NS */
5120 hdc
= get_frame_dc (f
);
5121 bmpdc
= CreateCompatibleDC (hdc
);
5122 release_frame_dc (f
, hdc
);
5124 prev
= SelectObject (bmpdc
, img
->pixmap
);
5126 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5127 MoveToEx (bmpdc
, 0, 0, NULL
);
5128 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5129 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5130 LineTo (bmpdc
, img
->width
- 1, 0);
5134 SelectObject (bmpdc
, img
->mask
);
5135 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5136 MoveToEx (bmpdc
, 0, 0, NULL
);
5137 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5138 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5139 LineTo (bmpdc
, img
->width
- 1, 0);
5141 SelectObject (bmpdc
, prev
);
5143 #endif /* HAVE_NTGUI */
5148 /* Build a mask for image IMG which is used on frame F. FILE is the
5149 name of an image file, for error messages. HOW determines how to
5150 determine the background color of IMG. If it is a list '(R G B)',
5151 with R, G, and B being integers >= 0, take that as the color of the
5152 background. Otherwise, determine the background color of IMG
5153 heuristically. Value is non-zero if successful. */
5156 x_build_heuristic_mask (f
, img
, how
)
5161 XImagePtr_or_DC ximg
;
5169 #endif /* HAVE_NTGUI */
5170 int x
, y
, rc
, use_img_background
;
5171 unsigned long bg
= 0;
5175 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5176 img
->mask
= NO_PIXMAP
;
5177 img
->background_transparent_valid
= 0;
5182 /* Create an image and pixmap serving as mask. */
5183 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5184 &mask_img
, &img
->mask
);
5187 #endif /* !HAVE_NS */
5189 /* Get the X image of IMG->pixmap. */
5190 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5191 img
->width
, img
->height
,
5194 /* Create the bit array serving as mask. */
5195 row_width
= (img
->width
+ 7) / 8;
5196 mask_img
= xmalloc (row_width
* img
->height
);
5197 bzero (mask_img
, row_width
* img
->height
);
5199 /* Create a memory device context for IMG->pixmap. */
5200 frame_dc
= get_frame_dc (f
);
5201 ximg
= CreateCompatibleDC (frame_dc
);
5202 release_frame_dc (f
, frame_dc
);
5203 prev
= SelectObject (ximg
, img
->pixmap
);
5204 #endif /* HAVE_NTGUI */
5206 /* Determine the background color of ximg. If HOW is `(R G B)'
5207 take that as color. Otherwise, use the image's background color. */
5208 use_img_background
= 1;
5214 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5216 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5220 if (i
== 3 && NILP (how
))
5222 char color_name
[30];
5223 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5226 0x00ffffff & /* Filter out palette info. */
5227 #endif /* HAVE_NTGUI */
5228 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5229 use_img_background
= 0;
5233 if (use_img_background
)
5234 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5236 /* Set all bits in mask_img to 1 whose color in ximg is different
5237 from the background color bg. */
5239 for (y
= 0; y
< img
->height
; ++y
)
5240 for (x
= 0; x
< img
->width
; ++x
)
5242 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5243 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5245 if (XGetPixel (ximg
, x
, y
) == bg
)
5246 ns_set_alpha(ximg
, x
, y
, 0);
5247 #endif /* HAVE_NS */
5249 /* Fill in the background_transparent field while we have the mask handy. */
5250 image_background_transparent (img
, f
, mask_img
);
5252 /* Put mask_img into img->mask. */
5253 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5254 x_destroy_x_image (mask_img
);
5255 #endif /* !HAVE_NS */
5257 for (y
= 0; y
< img
->height
; ++y
)
5258 for (x
= 0; x
< img
->width
; ++x
)
5260 COLORREF p
= GetPixel (ximg
, x
, y
);
5262 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5265 /* Create the mask image. */
5266 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5268 /* Fill in the background_transparent field while we have the mask handy. */
5269 SelectObject (ximg
, img
->mask
);
5270 image_background_transparent (img
, f
, ximg
);
5272 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5274 #endif /* HAVE_NTGUI */
5276 Destroy_Image (ximg
, prev
);
5282 /***********************************************************************
5283 PBM (mono, gray, color)
5284 ***********************************************************************/
5286 static int pbm_image_p
P_ ((Lisp_Object object
));
5287 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5288 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5290 /* The symbol `pbm' identifying images of this type. */
5294 /* Indices of image specification fields in gs_format, below. */
5296 enum pbm_keyword_index
5312 /* Vector of image_keyword structures describing the format
5313 of valid user-defined image specifications. */
5315 static struct image_keyword pbm_format
[PBM_LAST
] =
5317 {":type", IMAGE_SYMBOL_VALUE
, 1},
5318 {":file", IMAGE_STRING_VALUE
, 0},
5319 {":data", IMAGE_STRING_VALUE
, 0},
5320 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5321 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5322 {":relief", IMAGE_INTEGER_VALUE
, 0},
5323 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5324 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5325 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5326 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5327 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5330 /* Structure describing the image type `pbm'. */
5332 static struct image_type pbm_type
=
5342 /* Return non-zero if OBJECT is a valid PBM image specification. */
5345 pbm_image_p (object
)
5348 struct image_keyword fmt
[PBM_LAST
];
5350 bcopy (pbm_format
, fmt
, sizeof fmt
);
5352 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5355 /* Must specify either :data or :file. */
5356 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5360 /* Scan a decimal number from *S and return it. Advance *S while
5361 reading the number. END is the end of the string. Value is -1 at
5365 pbm_scan_number (s
, end
)
5366 unsigned char **s
, *end
;
5368 int c
= 0, val
= -1;
5372 /* Skip white-space. */
5373 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5378 /* Skip comment to end of line. */
5379 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5382 else if (isdigit (c
))
5384 /* Read decimal number. */
5386 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5387 val
= 10 * val
+ c
- '0';
5399 #if 0 /* Unused. ++kfs */
5401 /* Read FILE into memory. Value is a pointer to a buffer allocated
5402 with xmalloc holding FILE's contents. Value is null if an error
5403 occurred. *SIZE is set to the size of the file. */
5406 pbm_read_file (file
, size
)
5414 if (stat (SDATA (file
), &st
) == 0
5415 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5416 && (buf
= (char *) xmalloc (st
.st_size
),
5417 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5436 #endif /* HAVE_NTGUI */
5438 /* Load PBM image IMG for use on frame F. */
5446 int width
, height
, max_color_idx
= 0;
5448 Lisp_Object file
, specified_file
;
5449 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5450 struct gcpro gcpro1
;
5451 unsigned char *contents
= NULL
;
5452 unsigned char *end
, *p
;
5455 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5459 if (STRINGP (specified_file
))
5461 file
= x_find_image_file (specified_file
);
5462 if (!STRINGP (file
))
5464 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5469 contents
= slurp_file (SDATA (file
), &size
);
5470 if (contents
== NULL
)
5472 image_error ("Error reading `%s'", file
, Qnil
);
5478 end
= contents
+ size
;
5483 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5485 end
= p
+ SBYTES (data
);
5488 /* Check magic number. */
5489 if (end
- p
< 2 || *p
++ != 'P')
5491 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5501 raw_p
= 0, type
= PBM_MONO
;
5505 raw_p
= 0, type
= PBM_GRAY
;
5509 raw_p
= 0, type
= PBM_COLOR
;
5513 raw_p
= 1, type
= PBM_MONO
;
5517 raw_p
= 1, type
= PBM_GRAY
;
5521 raw_p
= 1, type
= PBM_COLOR
;
5525 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5529 /* Read width, height, maximum color-component. Characters
5530 starting with `#' up to the end of a line are ignored. */
5531 width
= pbm_scan_number (&p
, end
);
5532 height
= pbm_scan_number (&p
, end
);
5534 if (type
!= PBM_MONO
)
5536 max_color_idx
= pbm_scan_number (&p
, end
);
5537 if (max_color_idx
> 65535 || max_color_idx
< 0)
5539 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
5544 if (!check_image_size (f
, width
, height
))
5546 image_error ("Invalid image size", Qnil
, Qnil
);
5550 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5551 &ximg
, &img
->pixmap
))
5554 /* Initialize the color hash table. */
5555 init_color_table ();
5557 if (type
== PBM_MONO
)
5560 struct image_keyword fmt
[PBM_LAST
];
5561 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5562 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5564 /* Parse the image specification. */
5565 bcopy (pbm_format
, fmt
, sizeof fmt
);
5566 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5568 /* Get foreground and background colors, maybe allocate colors. */
5569 if (fmt
[PBM_FOREGROUND
].count
5570 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5571 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5572 if (fmt
[PBM_BACKGROUND
].count
5573 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5575 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5576 img
->background
= bg
;
5577 img
->background_valid
= 1;
5580 for (y
= 0; y
< height
; ++y
)
5581 for (x
= 0; x
< width
; ++x
)
5589 x_destroy_x_image (ximg
);
5590 x_clear_image (f
, img
);
5591 image_error ("Invalid image size in image `%s'",
5601 g
= pbm_scan_number (&p
, end
);
5603 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5608 int expected_size
= height
* width
;
5609 if (max_color_idx
> 255)
5611 if (type
== PBM_COLOR
)
5614 if (raw_p
&& p
+ expected_size
> end
)
5616 x_destroy_x_image (ximg
);
5617 x_clear_image (f
, img
);
5618 image_error ("Invalid image size in image `%s'",
5623 for (y
= 0; y
< height
; ++y
)
5624 for (x
= 0; x
< width
; ++x
)
5628 if (type
== PBM_GRAY
&& raw_p
)
5631 if (max_color_idx
> 255)
5632 r
= g
= b
= r
* 256 + *p
++;
5634 else if (type
== PBM_GRAY
)
5635 r
= g
= b
= pbm_scan_number (&p
, end
);
5639 if (max_color_idx
> 255)
5642 if (max_color_idx
> 255)
5645 if (max_color_idx
> 255)
5650 r
= pbm_scan_number (&p
, end
);
5651 g
= pbm_scan_number (&p
, end
);
5652 b
= pbm_scan_number (&p
, end
);
5655 if (r
< 0 || g
< 0 || b
< 0)
5657 x_destroy_x_image (ximg
);
5658 image_error ("Invalid pixel value in image `%s'",
5663 /* RGB values are now in the range 0..max_color_idx.
5664 Scale this to the range 0..0xffff supported by X. */
5665 r
= (double) r
* 65535 / max_color_idx
;
5666 g
= (double) g
* 65535 / max_color_idx
;
5667 b
= (double) b
* 65535 / max_color_idx
;
5668 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5672 #ifdef COLOR_TABLE_SUPPORT
5673 /* Store in IMG->colors the colors allocated for the image, and
5674 free the color table. */
5675 img
->colors
= colors_in_color_table (&img
->ncolors
);
5676 free_color_table ();
5677 #endif /* COLOR_TABLE_SUPPORT */
5680 img
->height
= height
;
5682 /* Maybe fill in the background field while we have ximg handy. */
5684 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5685 /* Casting avoids a GCC warning. */
5686 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5688 /* Put the image into a pixmap. */
5689 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5690 x_destroy_x_image (ximg
);
5692 /* X and W32 versions did it here, MAC version above. ++kfs
5694 img->height = height; */
5702 /***********************************************************************
5704 ***********************************************************************/
5706 #if defined (HAVE_PNG) || defined (HAVE_NS)
5708 /* Function prototypes. */
5710 static int png_image_p
P_ ((Lisp_Object object
));
5711 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5713 /* The symbol `png' identifying images of this type. */
5717 /* Indices of image specification fields in png_format, below. */
5719 enum png_keyword_index
5734 /* Vector of image_keyword structures describing the format
5735 of valid user-defined image specifications. */
5737 static struct image_keyword png_format
[PNG_LAST
] =
5739 {":type", IMAGE_SYMBOL_VALUE
, 1},
5740 {":data", IMAGE_STRING_VALUE
, 0},
5741 {":file", IMAGE_STRING_VALUE
, 0},
5742 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5743 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5744 {":relief", IMAGE_INTEGER_VALUE
, 0},
5745 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5746 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5747 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5748 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5751 /* Structure describing the image type `png'. */
5753 static struct image_type png_type
=
5762 /* Return non-zero if OBJECT is a valid PNG image specification. */
5765 png_image_p (object
)
5768 struct image_keyword fmt
[PNG_LAST
];
5769 bcopy (png_format
, fmt
, sizeof fmt
);
5771 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5774 /* Must specify either the :data or :file keyword. */
5775 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5778 #endif /* HAVE_PNG || HAVE_NS */
5783 #if defined HAVE_LIBPNG_PNG_H
5784 # include <libpng/png.h>
5790 /* PNG library details. */
5792 DEF_IMGLIB_FN (png_get_io_ptr
);
5793 DEF_IMGLIB_FN (png_check_sig
);
5794 DEF_IMGLIB_FN (png_create_read_struct
);
5795 DEF_IMGLIB_FN (png_create_info_struct
);
5796 DEF_IMGLIB_FN (png_destroy_read_struct
);
5797 DEF_IMGLIB_FN (png_set_read_fn
);
5798 DEF_IMGLIB_FN (png_set_sig_bytes
);
5799 DEF_IMGLIB_FN (png_read_info
);
5800 DEF_IMGLIB_FN (png_get_IHDR
);
5801 DEF_IMGLIB_FN (png_get_valid
);
5802 DEF_IMGLIB_FN (png_set_strip_16
);
5803 DEF_IMGLIB_FN (png_set_expand
);
5804 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5805 DEF_IMGLIB_FN (png_set_background
);
5806 DEF_IMGLIB_FN (png_get_bKGD
);
5807 DEF_IMGLIB_FN (png_read_update_info
);
5808 DEF_IMGLIB_FN (png_get_channels
);
5809 DEF_IMGLIB_FN (png_get_rowbytes
);
5810 DEF_IMGLIB_FN (png_read_image
);
5811 DEF_IMGLIB_FN (png_read_end
);
5812 DEF_IMGLIB_FN (png_error
);
5815 init_png_functions (Lisp_Object libraries
)
5819 /* Try loading libpng under probable names. */
5820 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5823 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5824 LOAD_IMGLIB_FN (library
, png_check_sig
);
5825 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5826 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5827 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5828 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5829 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5830 LOAD_IMGLIB_FN (library
, png_read_info
);
5831 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5832 LOAD_IMGLIB_FN (library
, png_get_valid
);
5833 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5834 LOAD_IMGLIB_FN (library
, png_set_expand
);
5835 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5836 LOAD_IMGLIB_FN (library
, png_set_background
);
5837 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5838 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5839 LOAD_IMGLIB_FN (library
, png_get_channels
);
5840 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5841 LOAD_IMGLIB_FN (library
, png_read_image
);
5842 LOAD_IMGLIB_FN (library
, png_read_end
);
5843 LOAD_IMGLIB_FN (library
, png_error
);
5848 #define fn_png_get_io_ptr png_get_io_ptr
5849 #define fn_png_check_sig png_check_sig
5850 #define fn_png_create_read_struct png_create_read_struct
5851 #define fn_png_create_info_struct png_create_info_struct
5852 #define fn_png_destroy_read_struct png_destroy_read_struct
5853 #define fn_png_set_read_fn png_set_read_fn
5854 #define fn_png_set_sig_bytes png_set_sig_bytes
5855 #define fn_png_read_info png_read_info
5856 #define fn_png_get_IHDR png_get_IHDR
5857 #define fn_png_get_valid png_get_valid
5858 #define fn_png_set_strip_16 png_set_strip_16
5859 #define fn_png_set_expand png_set_expand
5860 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5861 #define fn_png_set_background png_set_background
5862 #define fn_png_get_bKGD png_get_bKGD
5863 #define fn_png_read_update_info png_read_update_info
5864 #define fn_png_get_channels png_get_channels
5865 #define fn_png_get_rowbytes png_get_rowbytes
5866 #define fn_png_read_image png_read_image
5867 #define fn_png_read_end png_read_end
5868 #define fn_png_error png_error
5870 #endif /* HAVE_NTGUI */
5872 /* Error and warning handlers installed when the PNG library
5876 my_png_error (png_ptr
, msg
)
5877 png_struct
*png_ptr
;
5880 xassert (png_ptr
!= NULL
);
5881 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5882 longjmp (png_ptr
->jmpbuf
, 1);
5887 my_png_warning (png_ptr
, msg
)
5888 png_struct
*png_ptr
;
5891 xassert (png_ptr
!= NULL
);
5892 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5895 /* Memory source for PNG decoding. */
5897 struct png_memory_storage
5899 unsigned char *bytes
; /* The data */
5900 size_t len
; /* How big is it? */
5901 int index
; /* Where are we? */
5905 /* Function set as reader function when reading PNG image from memory.
5906 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5907 bytes from the input to DATA. */
5910 png_read_from_memory (png_ptr
, data
, length
)
5911 png_structp png_ptr
;
5915 struct png_memory_storage
*tbr
5916 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5918 if (length
> tbr
->len
- tbr
->index
)
5919 fn_png_error (png_ptr
, "Read error");
5921 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5922 tbr
->index
= tbr
->index
+ length
;
5926 /* Function set as reader function when reading PNG image from a file.
5927 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5928 bytes from the input to DATA. */
5931 png_read_from_file (png_ptr
, data
, length
)
5932 png_structp png_ptr
;
5936 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
5938 if (fread (data
, 1, length
, fp
) < length
)
5939 fn_png_error (png_ptr
, "Read error");
5943 /* Load PNG image IMG for use on frame F. Value is non-zero if
5951 Lisp_Object file
, specified_file
;
5952 Lisp_Object specified_data
;
5954 XImagePtr ximg
, mask_img
= NULL
;
5955 struct gcpro gcpro1
;
5956 png_struct
*png_ptr
= NULL
;
5957 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5958 FILE *volatile fp
= NULL
;
5960 png_byte
* volatile pixels
= NULL
;
5961 png_byte
** volatile rows
= NULL
;
5962 png_uint_32 width
, height
;
5963 int bit_depth
, color_type
, interlace_type
;
5965 png_uint_32 row_bytes
;
5967 struct png_memory_storage tbr
; /* Data to be read */
5969 /* Find out what file to load. */
5970 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5971 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5975 if (NILP (specified_data
))
5977 file
= x_find_image_file (specified_file
);
5978 if (!STRINGP (file
))
5980 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5985 /* Open the image file. */
5986 fp
= fopen (SDATA (file
), "rb");
5989 image_error ("Cannot open image file `%s'", file
, Qnil
);
5994 /* Check PNG signature. */
5995 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
5996 || !fn_png_check_sig (sig
, sizeof sig
))
5998 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6006 /* Read from memory. */
6007 tbr
.bytes
= SDATA (specified_data
);
6008 tbr
.len
= SBYTES (specified_data
);
6011 /* Check PNG signature. */
6012 if (tbr
.len
< sizeof sig
6013 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6015 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6020 /* Need to skip past the signature. */
6021 tbr
.bytes
+= sizeof (sig
);
6024 /* Initialize read and info structs for PNG lib. Casting return
6025 value avoids a GCC warning on W32. */
6026 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6031 if (fp
) fclose (fp
);
6036 /* Casting return value avoids a GCC warning on W32. */
6037 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6040 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6041 if (fp
) fclose (fp
);
6046 /* Casting return value avoids a GCC warning on W32. */
6047 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6050 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6051 if (fp
) fclose (fp
);
6056 /* Set error jump-back. We come back here when the PNG library
6057 detects an error. */
6058 if (setjmp (png_ptr
->jmpbuf
))
6062 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6065 if (fp
) fclose (fp
);
6070 /* Read image info. */
6071 if (!NILP (specified_data
))
6072 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6074 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6076 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6077 fn_png_read_info (png_ptr
, info_ptr
);
6078 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6079 &interlace_type
, NULL
, NULL
);
6081 if (!check_image_size (f
, width
, height
))
6084 /* If image contains simply transparency data, we prefer to
6085 construct a clipping mask. */
6086 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6091 /* This function is easier to write if we only have to handle
6092 one data format: RGB or RGBA with 8 bits per channel. Let's
6093 transform other formats into that format. */
6095 /* Strip more than 8 bits per channel. */
6096 if (bit_depth
== 16)
6097 fn_png_set_strip_16 (png_ptr
);
6099 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6101 fn_png_set_expand (png_ptr
);
6103 /* Convert grayscale images to RGB. */
6104 if (color_type
== PNG_COLOR_TYPE_GRAY
6105 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6106 fn_png_set_gray_to_rgb (png_ptr
);
6108 /* Handle alpha channel by combining the image with a background
6109 color. Do this only if a real alpha channel is supplied. For
6110 simple transparency, we prefer a clipping mask. */
6113 /* png_color_16 *image_bg; */
6114 Lisp_Object specified_bg
6115 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6116 int shift
= (bit_depth
== 16) ? 0 : 8;
6118 if (STRINGP (specified_bg
))
6119 /* The user specified `:background', use that. */
6122 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6124 png_color_16 user_bg
;
6126 bzero (&user_bg
, sizeof user_bg
);
6127 user_bg
.red
= color
.red
>> shift
;
6128 user_bg
.green
= color
.green
>> shift
;
6129 user_bg
.blue
= color
.blue
>> shift
;
6131 fn_png_set_background (png_ptr
, &user_bg
,
6132 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6137 /* We use the current frame background, ignoring any default
6138 background color set by the image. */
6139 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
6141 png_color_16 frame_background
;
6143 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6144 x_query_color (f
, &color
);
6146 bzero (&frame_background
, sizeof frame_background
);
6147 frame_background
.red
= color
.red
>> shift
;
6148 frame_background
.green
= color
.green
>> shift
;
6149 frame_background
.blue
= color
.blue
>> shift
;
6150 #endif /* HAVE_X_WINDOWS */
6152 fn_png_set_background (png_ptr
, &frame_background
,
6153 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6157 /* Update info structure. */
6158 fn_png_read_update_info (png_ptr
, info_ptr
);
6160 /* Get number of channels. Valid values are 1 for grayscale images
6161 and images with a palette, 2 for grayscale images with transparency
6162 information (alpha channel), 3 for RGB images, and 4 for RGB
6163 images with alpha channel, i.e. RGBA. If conversions above were
6164 sufficient we should only have 3 or 4 channels here. */
6165 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6166 xassert (channels
== 3 || channels
== 4);
6168 /* Number of bytes needed for one row of the image. */
6169 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6171 /* Allocate memory for the image. */
6172 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6173 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6174 for (i
= 0; i
< height
; ++i
)
6175 rows
[i
] = pixels
+ i
* row_bytes
;
6177 /* Read the entire image. */
6178 fn_png_read_image (png_ptr
, rows
);
6179 fn_png_read_end (png_ptr
, info_ptr
);
6186 /* Create the X image and pixmap. */
6187 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6191 /* Create an image and pixmap serving as mask if the PNG image
6192 contains an alpha channel. */
6195 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6196 &mask_img
, &img
->mask
))
6198 x_destroy_x_image (ximg
);
6199 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6200 img
->pixmap
= NO_PIXMAP
;
6204 /* Fill the X image and mask from PNG data. */
6205 init_color_table ();
6207 for (y
= 0; y
< height
; ++y
)
6209 png_byte
*p
= rows
[y
];
6211 for (x
= 0; x
< width
; ++x
)
6218 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6219 /* An alpha channel, aka mask channel, associates variable
6220 transparency with an image. Where other image formats
6221 support binary transparency---fully transparent or fully
6222 opaque---PNG allows up to 254 levels of partial transparency.
6223 The PNG library implements partial transparency by combining
6224 the image with a specified background color.
6226 I'm not sure how to handle this here nicely: because the
6227 background on which the image is displayed may change, for
6228 real alpha channel support, it would be necessary to create
6229 a new image for each possible background.
6231 What I'm doing now is that a mask is created if we have
6232 boolean transparency information. Otherwise I'm using
6233 the frame's background color to combine the image with. */
6238 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6244 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6245 /* Set IMG's background color from the PNG image, unless the user
6249 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6251 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6252 img
->background_valid
= 1;
6256 #ifdef COLOR_TABLE_SUPPORT
6257 /* Remember colors allocated for this image. */
6258 img
->colors
= colors_in_color_table (&img
->ncolors
);
6259 free_color_table ();
6260 #endif /* COLOR_TABLE_SUPPORT */
6263 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6268 img
->height
= height
;
6270 /* Maybe fill in the background field while we have ximg handy.
6271 Casting avoids a GCC warning. */
6272 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6274 /* Put the image into the pixmap, then free the X image and its buffer. */
6275 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6276 x_destroy_x_image (ximg
);
6278 /* Same for the mask. */
6281 /* Fill in the background_transparent field while we have the
6282 mask handy. Casting avoids a GCC warning. */
6283 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6285 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6286 x_destroy_x_image (mask_img
);
6293 #else /* HAVE_PNG */
6297 png_load (struct frame
*f
, struct image
*img
)
6299 return ns_load_image(f
, img
,
6300 image_spec_value (img
->spec
, QCfile
, NULL
),
6301 image_spec_value (img
->spec
, QCdata
, NULL
));
6303 #endif /* HAVE_NS */
6306 #endif /* !HAVE_PNG */
6310 /***********************************************************************
6312 ***********************************************************************/
6314 #if defined (HAVE_JPEG) || defined (HAVE_NS)
6316 static int jpeg_image_p
P_ ((Lisp_Object object
));
6317 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6319 /* The symbol `jpeg' identifying images of this type. */
6323 /* Indices of image specification fields in gs_format, below. */
6325 enum jpeg_keyword_index
6334 JPEG_HEURISTIC_MASK
,
6340 /* Vector of image_keyword structures describing the format
6341 of valid user-defined image specifications. */
6343 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6345 {":type", IMAGE_SYMBOL_VALUE
, 1},
6346 {":data", IMAGE_STRING_VALUE
, 0},
6347 {":file", IMAGE_STRING_VALUE
, 0},
6348 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6349 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6350 {":relief", IMAGE_INTEGER_VALUE
, 0},
6351 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6352 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6353 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6354 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6357 /* Structure describing the image type `jpeg'. */
6359 static struct image_type jpeg_type
=
6368 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6371 jpeg_image_p (object
)
6374 struct image_keyword fmt
[JPEG_LAST
];
6376 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6378 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6381 /* Must specify either the :data or :file keyword. */
6382 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6385 #endif /* HAVE_JPEG || HAVE_NS */
6389 /* Work around a warning about HAVE_STDLIB_H being redefined in
6391 #ifdef HAVE_STDLIB_H
6392 #define HAVE_STDLIB_H_1
6393 #undef HAVE_STDLIB_H
6394 #endif /* HAVE_STLIB_H */
6396 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6397 /* In older releases of the jpeg library, jpeglib.h will define boolean
6398 differently depending on __WIN32__, so make sure it is defined. */
6402 #include <jpeglib.h>
6406 #ifdef HAVE_STLIB_H_1
6407 #define HAVE_STDLIB_H 1
6412 /* JPEG library details. */
6413 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6414 DEF_IMGLIB_FN (jpeg_start_decompress
);
6415 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6416 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6417 DEF_IMGLIB_FN (jpeg_read_header
);
6418 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6419 DEF_IMGLIB_FN (jpeg_std_error
);
6420 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6423 init_jpeg_functions (Lisp_Object libraries
)
6427 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6430 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6431 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6432 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6433 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6434 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6435 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6436 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6437 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6441 /* Wrapper since we can't directly assign the function pointer
6442 to another function pointer that was declared more completely easily. */
6444 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
6445 j_decompress_ptr cinfo
;
6448 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6453 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6454 #define fn_jpeg_start_decompress jpeg_start_decompress
6455 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6456 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6457 #define fn_jpeg_read_header jpeg_read_header
6458 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6459 #define fn_jpeg_std_error jpeg_std_error
6460 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6462 #endif /* HAVE_NTGUI */
6464 struct my_jpeg_error_mgr
6466 struct jpeg_error_mgr pub
;
6467 jmp_buf setjmp_buffer
;
6472 my_error_exit (cinfo
)
6475 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6476 longjmp (mgr
->setjmp_buffer
, 1);
6480 /* Init source method for JPEG data source manager. Called by
6481 jpeg_read_header() before any data is actually read. See
6482 libjpeg.doc from the JPEG lib distribution. */
6485 our_common_init_source (cinfo
)
6486 j_decompress_ptr cinfo
;
6491 /* Method to terminate data source. Called by
6492 jpeg_finish_decompress() after all data has been processed. */
6495 our_common_term_source (cinfo
)
6496 j_decompress_ptr cinfo
;
6501 /* Fill input buffer method for JPEG data source manager. Called
6502 whenever more data is needed. We read the whole image in one step,
6503 so this only adds a fake end of input marker at the end. */
6505 static JOCTET our_memory_buffer
[2];
6508 our_memory_fill_input_buffer (cinfo
)
6509 j_decompress_ptr cinfo
;
6511 /* Insert a fake EOI marker. */
6512 struct jpeg_source_mgr
*src
= cinfo
->src
;
6514 our_memory_buffer
[0] = (JOCTET
) 0xFF;
6515 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
6517 src
->next_input_byte
= our_memory_buffer
;
6518 src
->bytes_in_buffer
= 2;
6523 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6524 is the JPEG data source manager. */
6527 our_memory_skip_input_data (cinfo
, num_bytes
)
6528 j_decompress_ptr cinfo
;
6531 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6535 if (num_bytes
> src
->bytes_in_buffer
)
6536 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6538 src
->bytes_in_buffer
-= num_bytes
;
6539 src
->next_input_byte
+= num_bytes
;
6544 /* Set up the JPEG lib for reading an image from DATA which contains
6545 LEN bytes. CINFO is the decompression info structure created for
6546 reading the image. */
6549 jpeg_memory_src (cinfo
, data
, len
)
6550 j_decompress_ptr cinfo
;
6554 struct jpeg_source_mgr
*src
;
6556 if (cinfo
->src
== NULL
)
6558 /* First time for this JPEG object? */
6559 cinfo
->src
= (struct jpeg_source_mgr
*)
6560 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6561 sizeof (struct jpeg_source_mgr
));
6562 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6563 src
->next_input_byte
= data
;
6566 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6567 src
->init_source
= our_common_init_source
;
6568 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6569 src
->skip_input_data
= our_memory_skip_input_data
;
6570 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6571 src
->term_source
= our_common_term_source
;
6572 src
->bytes_in_buffer
= len
;
6573 src
->next_input_byte
= data
;
6577 struct jpeg_stdio_mgr
6579 struct jpeg_source_mgr mgr
;
6586 /* Size of buffer to read JPEG from file.
6587 Not too big, as we want to use alloc_small. */
6588 #define JPEG_STDIO_BUFFER_SIZE 8192
6591 /* Fill input buffer method for JPEG data source manager. Called
6592 whenever more data is needed. The data is read from a FILE *. */
6595 our_stdio_fill_input_buffer (cinfo
)
6596 j_decompress_ptr cinfo
;
6598 struct jpeg_stdio_mgr
*src
;
6600 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6605 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6607 src
->mgr
.bytes_in_buffer
= bytes
;
6610 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6612 src
->buffer
[0] = (JOCTET
) 0xFF;
6613 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6614 src
->mgr
.bytes_in_buffer
= 2;
6616 src
->mgr
.next_input_byte
= src
->buffer
;
6623 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6624 is the JPEG data source manager. */
6627 our_stdio_skip_input_data (cinfo
, num_bytes
)
6628 j_decompress_ptr cinfo
;
6631 struct jpeg_stdio_mgr
*src
;
6632 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6634 while (num_bytes
> 0 && !src
->finished
)
6636 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6638 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6639 src
->mgr
.next_input_byte
+= num_bytes
;
6644 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6645 src
->mgr
.bytes_in_buffer
= 0;
6646 src
->mgr
.next_input_byte
= NULL
;
6648 our_stdio_fill_input_buffer (cinfo
);
6654 /* Set up the JPEG lib for reading an image from a FILE *.
6655 CINFO is the decompression info structure created for
6656 reading the image. */
6659 jpeg_file_src (cinfo
, fp
)
6660 j_decompress_ptr cinfo
;
6663 struct jpeg_stdio_mgr
*src
;
6665 if (cinfo
->src
!= NULL
)
6666 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6669 /* First time for this JPEG object? */
6670 cinfo
->src
= (struct jpeg_source_mgr
*)
6671 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6672 sizeof (struct jpeg_stdio_mgr
));
6673 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6674 src
->buffer
= (JOCTET
*)
6675 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6676 JPEG_STDIO_BUFFER_SIZE
);
6681 src
->mgr
.init_source
= our_common_init_source
;
6682 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6683 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6684 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6685 src
->mgr
.term_source
= our_common_term_source
;
6686 src
->mgr
.bytes_in_buffer
= 0;
6687 src
->mgr
.next_input_byte
= NULL
;
6691 /* Load image IMG for use on frame F. Patterned after example.c
6692 from the JPEG lib. */
6699 struct jpeg_decompress_struct cinfo
;
6700 struct my_jpeg_error_mgr mgr
;
6701 Lisp_Object file
, specified_file
;
6702 Lisp_Object specified_data
;
6703 FILE * volatile fp
= NULL
;
6705 int row_stride
, x
, y
;
6706 XImagePtr ximg
= NULL
;
6708 unsigned long *colors
;
6710 struct gcpro gcpro1
;
6712 /* Open the JPEG file. */
6713 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6714 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6718 if (NILP (specified_data
))
6720 file
= x_find_image_file (specified_file
);
6721 if (!STRINGP (file
))
6723 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6728 fp
= fopen (SDATA (file
), "rb");
6731 image_error ("Cannot open `%s'", file
, Qnil
);
6737 /* Customize libjpeg's error handling to call my_error_exit when an
6738 error is detected. This function will perform a longjmp.
6739 Casting return value avoids a GCC warning on W32. */
6740 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
6741 mgr
.pub
.error_exit
= my_error_exit
;
6743 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6747 /* Called from my_error_exit. Display a JPEG error. */
6748 char buffer
[JMSG_LENGTH_MAX
];
6749 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6750 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6751 build_string (buffer
));
6754 /* Close the input file and destroy the JPEG object. */
6756 fclose ((FILE *) fp
);
6757 fn_jpeg_destroy_decompress (&cinfo
);
6759 /* If we already have an XImage, free that. */
6760 x_destroy_x_image (ximg
);
6762 /* Free pixmap and colors. */
6763 x_clear_image (f
, img
);
6769 /* Create the JPEG decompression object. Let it read from fp.
6770 Read the JPEG image header. */
6771 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6773 if (NILP (specified_data
))
6774 jpeg_file_src (&cinfo
, (FILE *) fp
);
6776 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6777 SBYTES (specified_data
));
6779 fn_jpeg_read_header (&cinfo
, 1);
6781 /* Customize decompression so that color quantization will be used.
6782 Start decompression. */
6783 cinfo
.quantize_colors
= 1;
6784 fn_jpeg_start_decompress (&cinfo
);
6785 width
= img
->width
= cinfo
.output_width
;
6786 height
= img
->height
= cinfo
.output_height
;
6788 if (!check_image_size (f
, width
, height
))
6790 image_error ("Invalid image size", Qnil
, Qnil
);
6791 longjmp (mgr
.setjmp_buffer
, 2);
6794 /* Create X image and pixmap. */
6795 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6796 longjmp (mgr
.setjmp_buffer
, 2);
6798 /* Allocate colors. When color quantization is used,
6799 cinfo.actual_number_of_colors has been set with the number of
6800 colors generated, and cinfo.colormap is a two-dimensional array
6801 of color indices in the range 0..cinfo.actual_number_of_colors.
6802 No more than 255 colors will be generated. */
6806 if (cinfo
.out_color_components
> 2)
6807 ir
= 0, ig
= 1, ib
= 2;
6808 else if (cinfo
.out_color_components
> 1)
6809 ir
= 0, ig
= 1, ib
= 0;
6811 ir
= 0, ig
= 0, ib
= 0;
6813 /* Use the color table mechanism because it handles colors that
6814 cannot be allocated nicely. Such colors will be replaced with
6815 a default color, and we don't have to care about which colors
6816 can be freed safely, and which can't. */
6817 init_color_table ();
6818 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6821 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6823 /* Multiply RGB values with 255 because X expects RGB values
6824 in the range 0..0xffff. */
6825 int r
= cinfo
.colormap
[ir
][i
] << 8;
6826 int g
= cinfo
.colormap
[ig
][i
] << 8;
6827 int b
= cinfo
.colormap
[ib
][i
] << 8;
6828 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6831 #ifdef COLOR_TABLE_SUPPORT
6832 /* Remember those colors actually allocated. */
6833 img
->colors
= colors_in_color_table (&img
->ncolors
);
6834 free_color_table ();
6835 #endif /* COLOR_TABLE_SUPPORT */
6839 row_stride
= width
* cinfo
.output_components
;
6840 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6842 for (y
= 0; y
< height
; ++y
)
6844 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6845 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6846 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6850 fn_jpeg_finish_decompress (&cinfo
);
6851 fn_jpeg_destroy_decompress (&cinfo
);
6853 fclose ((FILE *) fp
);
6855 /* Maybe fill in the background field while we have ximg handy. */
6856 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6857 /* Casting avoids a GCC warning. */
6858 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6860 /* Put the image into the pixmap. */
6861 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6862 x_destroy_x_image (ximg
);
6867 #else /* HAVE_JPEG */
6871 jpeg_load (struct frame
*f
, struct image
*img
)
6873 return ns_load_image(f
, img
,
6874 image_spec_value (img
->spec
, QCfile
, NULL
),
6875 image_spec_value (img
->spec
, QCdata
, NULL
));
6877 #endif /* HAVE_NS */
6879 #endif /* !HAVE_JPEG */
6883 /***********************************************************************
6885 ***********************************************************************/
6887 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6889 static int tiff_image_p
P_ ((Lisp_Object object
));
6890 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6892 /* The symbol `tiff' identifying images of this type. */
6896 /* Indices of image specification fields in tiff_format, below. */
6898 enum tiff_keyword_index
6907 TIFF_HEURISTIC_MASK
,
6914 /* Vector of image_keyword structures describing the format
6915 of valid user-defined image specifications. */
6917 static struct image_keyword tiff_format
[TIFF_LAST
] =
6919 {":type", IMAGE_SYMBOL_VALUE
, 1},
6920 {":data", IMAGE_STRING_VALUE
, 0},
6921 {":file", IMAGE_STRING_VALUE
, 0},
6922 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6923 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6924 {":relief", IMAGE_INTEGER_VALUE
, 0},
6925 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6926 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6927 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6928 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6929 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
6932 /* Structure describing the image type `tiff'. */
6934 static struct image_type tiff_type
=
6943 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6946 tiff_image_p (object
)
6949 struct image_keyword fmt
[TIFF_LAST
];
6950 bcopy (tiff_format
, fmt
, sizeof fmt
);
6952 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6955 /* Must specify either the :data or :file keyword. */
6956 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6959 #endif /* HAVE_TIFF || HAVE_NS */
6967 /* TIFF library details. */
6968 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6969 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6970 DEF_IMGLIB_FN (TIFFOpen
);
6971 DEF_IMGLIB_FN (TIFFClientOpen
);
6972 DEF_IMGLIB_FN (TIFFGetField
);
6973 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6974 DEF_IMGLIB_FN (TIFFClose
);
6975 DEF_IMGLIB_FN (TIFFSetDirectory
);
6978 init_tiff_functions (Lisp_Object libraries
)
6982 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
6985 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
6986 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
6987 LOAD_IMGLIB_FN (library
, TIFFOpen
);
6988 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
6989 LOAD_IMGLIB_FN (library
, TIFFGetField
);
6990 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
6991 LOAD_IMGLIB_FN (library
, TIFFClose
);
6992 LOAD_IMGLIB_FN (library
, TIFFSetDirectory
);
6998 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6999 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7000 #define fn_TIFFOpen TIFFOpen
7001 #define fn_TIFFClientOpen TIFFClientOpen
7002 #define fn_TIFFGetField TIFFGetField
7003 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7004 #define fn_TIFFClose TIFFClose
7005 #define fn_TIFFSetDirectory TIFFSetDirectory
7006 #endif /* HAVE_NTGUI */
7009 /* Reading from a memory buffer for TIFF images Based on the PNG
7010 memory source, but we have to provide a lot of extra functions.
7013 We really only need to implement read and seek, but I am not
7014 convinced that the TIFF library is smart enough not to destroy
7015 itself if we only hand it the function pointers we need to
7020 unsigned char *bytes
;
7027 tiff_read_from_memory (data
, buf
, size
)
7032 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7034 if (size
> src
->len
- src
->index
)
7036 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7042 tiff_write_from_memory (data
, buf
, size
)
7051 tiff_seek_in_memory (data
, off
, whence
)
7056 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7061 case SEEK_SET
: /* Go from beginning of source. */
7065 case SEEK_END
: /* Go from end of source. */
7066 idx
= src
->len
+ off
;
7069 case SEEK_CUR
: /* Go from current position. */
7070 idx
= src
->index
+ off
;
7073 default: /* Invalid `whence'. */
7077 if (idx
> src
->len
|| idx
< 0)
7085 tiff_close_memory (data
)
7093 tiff_mmap_memory (data
, pbase
, psize
)
7098 /* It is already _IN_ memory. */
7103 tiff_unmap_memory (data
, base
, size
)
7108 /* We don't need to do this. */
7112 tiff_size_of_memory (data
)
7115 return ((tiff_memory_source
*) data
)->len
;
7120 tiff_error_handler (title
, format
, ap
)
7121 const char *title
, *format
;
7127 len
= sprintf (buf
, "TIFF error: %s ", title
);
7128 vsprintf (buf
+ len
, format
, ap
);
7129 add_to_log (buf
, Qnil
, Qnil
);
7134 tiff_warning_handler (title
, format
, ap
)
7135 const char *title
, *format
;
7141 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7142 vsprintf (buf
+ len
, format
, ap
);
7143 add_to_log (buf
, Qnil
, Qnil
);
7147 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7155 Lisp_Object file
, specified_file
;
7156 Lisp_Object specified_data
;
7158 int width
, height
, x
, y
, count
;
7162 struct gcpro gcpro1
;
7163 tiff_memory_source memsrc
;
7166 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7167 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7171 fn_TIFFSetErrorHandler (tiff_error_handler
);
7172 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7174 if (NILP (specified_data
))
7176 /* Read from a file */
7177 file
= x_find_image_file (specified_file
);
7178 if (!STRINGP (file
))
7180 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7185 /* Try to open the image file. Casting return value avoids a
7186 GCC warning on W32. */
7187 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7190 image_error ("Cannot open `%s'", file
, Qnil
);
7197 /* Memory source! */
7198 memsrc
.bytes
= SDATA (specified_data
);
7199 memsrc
.len
= SBYTES (specified_data
);
7202 /* Casting return value avoids a GCC warning on W32. */
7203 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7204 (TIFFReadWriteProc
) tiff_read_from_memory
,
7205 (TIFFReadWriteProc
) tiff_write_from_memory
,
7206 tiff_seek_in_memory
,
7208 tiff_size_of_memory
,
7214 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7220 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7221 if (INTEGERP (image
))
7223 int ino
= XFASTINT (image
);
7224 if (!fn_TIFFSetDirectory (tiff
, ino
))
7226 image_error ("Invalid image number `%s' in image `%s'",
7228 fn_TIFFClose (tiff
);
7234 /* Get width and height of the image, and allocate a raster buffer
7235 of width x height 32-bit values. */
7236 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7237 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7239 if (!check_image_size (f
, width
, height
))
7241 image_error ("Invalid image size", Qnil
, Qnil
);
7242 fn_TIFFClose (tiff
);
7247 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7249 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7251 /* Count the number of images in the file. */
7252 for (count
= 1, rc2
= 1; rc2
; count
++)
7253 rc2
= fn_TIFFSetDirectory (tiff
, count
);
7256 img
->data
.lisp_val
= Fcons (Qcount
,
7257 Fcons (make_number (count
),
7258 img
->data
.lisp_val
));
7260 fn_TIFFClose (tiff
);
7263 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7269 /* Create the X image and pixmap. */
7270 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7277 /* Initialize the color table. */
7278 init_color_table ();
7280 /* Process the pixel raster. Origin is in the lower-left corner. */
7281 for (y
= 0; y
< height
; ++y
)
7283 uint32
*row
= buf
+ y
* width
;
7285 for (x
= 0; x
< width
; ++x
)
7287 uint32 abgr
= row
[x
];
7288 int r
= TIFFGetR (abgr
) << 8;
7289 int g
= TIFFGetG (abgr
) << 8;
7290 int b
= TIFFGetB (abgr
) << 8;
7291 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7295 #ifdef COLOR_TABLE_SUPPORT
7296 /* Remember the colors allocated for the image. Free the color table. */
7297 img
->colors
= colors_in_color_table (&img
->ncolors
);
7298 free_color_table ();
7299 #endif /* COLOR_TABLE_SUPPORT */
7302 img
->height
= height
;
7304 /* Maybe fill in the background field while we have ximg handy. */
7305 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7306 /* Casting avoids a GCC warning on W32. */
7307 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7309 /* Put the image into the pixmap, then free the X image and its buffer. */
7310 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7311 x_destroy_x_image (ximg
);
7318 #else /* HAVE_TIFF */
7322 tiff_load (struct frame
*f
, struct image
*img
)
7324 return ns_load_image(f
, img
,
7325 image_spec_value (img
->spec
, QCfile
, NULL
),
7326 image_spec_value (img
->spec
, QCdata
, NULL
));
7328 #endif /* HAVE_NS */
7330 #endif /* !HAVE_TIFF */
7334 /***********************************************************************
7336 ***********************************************************************/
7338 #if defined (HAVE_GIF) || defined (HAVE_NS)
7340 static int gif_image_p
P_ ((Lisp_Object object
));
7341 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7342 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7344 /* The symbol `gif' identifying images of this type. */
7348 /* Indices of image specification fields in gif_format, below. */
7350 enum gif_keyword_index
7366 /* Vector of image_keyword structures describing the format
7367 of valid user-defined image specifications. */
7369 static struct image_keyword gif_format
[GIF_LAST
] =
7371 {":type", IMAGE_SYMBOL_VALUE
, 1},
7372 {":data", IMAGE_STRING_VALUE
, 0},
7373 {":file", IMAGE_STRING_VALUE
, 0},
7374 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7375 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7376 {":relief", IMAGE_INTEGER_VALUE
, 0},
7377 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7378 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7379 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7380 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7381 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7384 /* Structure describing the image type `gif'. */
7386 static struct image_type gif_type
=
7395 /* Free X resources of GIF image IMG which is used on frame F. */
7398 gif_clear_image (f
, img
)
7402 /* IMG->data.ptr_val may contain extension data. */
7403 img
->data
.lisp_val
= Qnil
;
7404 x_clear_image (f
, img
);
7407 /* Return non-zero if OBJECT is a valid GIF image specification. */
7410 gif_image_p (object
)
7413 struct image_keyword fmt
[GIF_LAST
];
7414 bcopy (gif_format
, fmt
, sizeof fmt
);
7416 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7419 /* Must specify either the :data or :file keyword. */
7420 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7423 #endif /* HAVE_GIF */
7427 #if defined (HAVE_NTGUI)
7428 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7429 Undefine before redefining to avoid a preprocessor warning. */
7433 /* avoid conflict with QuickdrawText.h */
7434 #define DrawText gif_DrawText
7435 #include <gif_lib.h>
7438 #else /* HAVE_NTGUI */
7440 #include <gif_lib.h>
7442 #endif /* HAVE_NTGUI */
7447 /* GIF library details. */
7448 DEF_IMGLIB_FN (DGifCloseFile
);
7449 DEF_IMGLIB_FN (DGifSlurp
);
7450 DEF_IMGLIB_FN (DGifOpen
);
7451 DEF_IMGLIB_FN (DGifOpenFileName
);
7454 init_gif_functions (Lisp_Object libraries
)
7458 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7461 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7462 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7463 LOAD_IMGLIB_FN (library
, DGifOpen
);
7464 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7470 #define fn_DGifCloseFile DGifCloseFile
7471 #define fn_DGifSlurp DGifSlurp
7472 #define fn_DGifOpen DGifOpen
7473 #define fn_DGifOpenFileName DGifOpenFileName
7475 #endif /* HAVE_NTGUI */
7477 /* Reading a GIF image from memory
7478 Based on the PNG memory stuff to a certain extent. */
7482 unsigned char *bytes
;
7488 /* Make the current memory source available to gif_read_from_memory.
7489 It's done this way because not all versions of libungif support
7490 a UserData field in the GifFileType structure. */
7491 static gif_memory_source
*current_gif_memory_src
;
7494 gif_read_from_memory (file
, buf
, len
)
7499 gif_memory_source
*src
= current_gif_memory_src
;
7501 if (len
> src
->len
- src
->index
)
7504 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7510 /* Load GIF image IMG for use on frame F. Value is non-zero if
7513 static int interlace_start
[] = {0, 4, 2, 1};
7514 static int interlace_increment
[] = {8, 8, 4, 2};
7521 Lisp_Object file
, specified_file
;
7522 Lisp_Object specified_data
;
7523 int rc
, width
, height
, x
, y
, i
;
7525 ColorMapObject
*gif_color_map
;
7526 unsigned long pixel_colors
[256];
7528 struct gcpro gcpro1
;
7530 int ino
, image_height
, image_width
;
7531 gif_memory_source memsrc
;
7532 unsigned char *raster
;
7534 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7535 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7539 if (NILP (specified_data
))
7541 file
= x_find_image_file (specified_file
);
7542 if (!STRINGP (file
))
7544 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7549 /* Open the GIF file. Casting return value avoids a GCC warning
7551 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7554 image_error ("Cannot open `%s'", file
, Qnil
);
7561 /* Read from memory! */
7562 current_gif_memory_src
= &memsrc
;
7563 memsrc
.bytes
= SDATA (specified_data
);
7564 memsrc
.len
= SBYTES (specified_data
);
7567 /* Casting return value avoids a GCC warning on W32. */
7568 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
7571 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7577 /* Before reading entire contents, check the declared image size. */
7578 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7580 image_error ("Invalid image size", Qnil
, Qnil
);
7581 fn_DGifCloseFile (gif
);
7586 /* Read entire contents. */
7587 rc
= fn_DGifSlurp (gif
);
7588 if (rc
== GIF_ERROR
)
7590 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7591 fn_DGifCloseFile (gif
);
7596 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7597 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7598 if (ino
>= gif
->ImageCount
)
7600 image_error ("Invalid image number `%s' in image `%s'",
7602 fn_DGifCloseFile (gif
);
7607 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7608 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7609 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7610 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7611 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7612 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7614 width
= img
->width
= max (gif
->SWidth
,
7615 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7616 img
->corners
[RIGHT_CORNER
]));
7617 height
= img
->height
= max (gif
->SHeight
,
7618 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7619 img
->corners
[BOT_CORNER
]));
7621 if (!check_image_size (f
, width
, height
))
7623 image_error ("Invalid image size", Qnil
, Qnil
);
7624 fn_DGifCloseFile (gif
);
7629 /* Create the X image and pixmap. */
7630 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7632 fn_DGifCloseFile (gif
);
7637 /* Allocate colors. */
7638 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7640 gif_color_map
= gif
->SColorMap
;
7641 init_color_table ();
7642 bzero (pixel_colors
, sizeof pixel_colors
);
7645 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7647 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7648 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7649 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7650 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7653 #ifdef COLOR_TABLE_SUPPORT
7654 img
->colors
= colors_in_color_table (&img
->ncolors
);
7655 free_color_table ();
7656 #endif /* COLOR_TABLE_SUPPORT */
7658 /* Clear the part of the screen image that are not covered by
7659 the image from the GIF file. Full animated GIF support
7660 requires more than can be done here (see the gif89 spec,
7661 disposal methods). Let's simply assume that the part
7662 not covered by a sub-image is in the frame's background color. */
7663 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7664 for (x
= 0; x
< width
; ++x
)
7665 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7667 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7668 for (x
= 0; x
< width
; ++x
)
7669 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7671 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7673 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7674 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7675 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7676 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7679 /* Read the GIF image into the X image. We use a local variable
7680 `raster' here because RasterBits below is a char *, and invites
7681 problems with bytes >= 0x80. */
7682 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7684 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7687 int row
= interlace_start
[0];
7691 for (y
= 0; y
< image_height
; y
++)
7693 if (row
>= image_height
)
7695 row
= interlace_start
[++pass
];
7696 while (row
>= image_height
)
7697 row
= interlace_start
[++pass
];
7700 for (x
= 0; x
< image_width
; x
++)
7702 int i
= raster
[(y
* image_width
) + x
];
7703 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7704 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7707 row
+= interlace_increment
[pass
];
7712 for (y
= 0; y
< image_height
; ++y
)
7713 for (x
= 0; x
< image_width
; ++x
)
7715 int i
= raster
[y
* image_width
+ x
];
7716 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7717 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7721 /* Save GIF image extension data for `image-extension-data'.
7722 Format is (count IMAGES FUNCTION "BYTES" ...). */
7723 img
->data
.lisp_val
= Qnil
;
7724 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7726 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7727 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7728 /* Append (... FUNCTION "BYTES") */
7729 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7730 Fcons (make_number (ext
->Function
),
7731 img
->data
.lisp_val
));
7732 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7734 if (gif
->ImageCount
> 1)
7735 img
->data
.lisp_val
= Fcons (Qcount
,
7736 Fcons (make_number (gif
->ImageCount
),
7737 img
->data
.lisp_val
));
7739 fn_DGifCloseFile (gif
);
7741 /* Maybe fill in the background field while we have ximg handy. */
7742 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7743 /* Casting avoids a GCC warning. */
7744 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7746 /* Put the image into the pixmap, then free the X image and its buffer. */
7747 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7748 x_destroy_x_image (ximg
);
7754 #else /* !HAVE_GIF */
7758 gif_load (struct frame
*f
, struct image
*img
)
7760 return ns_load_image(f
, img
,
7761 image_spec_value (img
->spec
, QCfile
, NULL
),
7762 image_spec_value (img
->spec
, QCdata
, NULL
));
7764 #endif /* HAVE_NS */
7766 #endif /* HAVE_GIF */
7770 /***********************************************************************
7772 ***********************************************************************/
7774 #if defined (HAVE_RSVG)
7776 /* Function prototypes. */
7778 static int svg_image_p
P_ ((Lisp_Object object
));
7779 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
7781 static int svg_load_image
P_ ((struct frame
*, struct image
*,
7782 unsigned char *, unsigned int));
7784 /* The symbol `svg' identifying images of this type. */
7788 /* Indices of image specification fields in svg_format, below. */
7790 enum svg_keyword_index
7805 /* Vector of image_keyword structures describing the format
7806 of valid user-defined image specifications. */
7808 static struct image_keyword svg_format
[SVG_LAST
] =
7810 {":type", IMAGE_SYMBOL_VALUE
, 1},
7811 {":data", IMAGE_STRING_VALUE
, 0},
7812 {":file", IMAGE_STRING_VALUE
, 0},
7813 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7814 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7815 {":relief", IMAGE_INTEGER_VALUE
, 0},
7816 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7817 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7818 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7819 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7822 /* Structure describing the image type `svg'. Its the same type of
7823 structure defined for all image formats, handled by emacs image
7824 functions. See struct image_type in dispextern.h. */
7826 static struct image_type svg_type
=
7828 /* An identifier showing that this is an image structure for the SVG format. */
7830 /* Handle to a function that can be used to identify a SVG file. */
7832 /* Handle to function used to load a SVG file. */
7834 /* Handle to function to free sresources for SVG. */
7836 /* An internal field to link to the next image type in a list of
7837 image types, will be filled in when registering the format. */
7842 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7843 this by calling parse_image_spec and supplying the keywords that
7844 identify the SVG format. */
7847 svg_image_p (object
)
7850 struct image_keyword fmt
[SVG_LAST
];
7851 bcopy (svg_format
, fmt
, sizeof fmt
);
7853 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
7856 /* Must specify either the :data or :file keyword. */
7857 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
7860 #include <librsvg/rsvg.h>
7864 /* SVG library functions. */
7865 DEF_IMGLIB_FN (rsvg_handle_new
);
7866 DEF_IMGLIB_FN (rsvg_handle_get_dimensions
);
7867 DEF_IMGLIB_FN (rsvg_handle_write
);
7868 DEF_IMGLIB_FN (rsvg_handle_close
);
7869 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
7870 DEF_IMGLIB_FN (rsvg_handle_free
);
7872 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
7873 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
7874 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
7875 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
7876 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
7877 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
7878 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
7879 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
7881 DEF_IMGLIB_FN (g_type_init
);
7882 DEF_IMGLIB_FN (g_object_unref
);
7883 DEF_IMGLIB_FN (g_error_free
);
7885 Lisp_Object Qgdk_pixbuf
, Qglib
, Qgobject
;
7888 init_svg_functions (Lisp_Object libraries
)
7890 HMODULE library
, gdklib
, glib
, gobject
;
7892 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
7893 || !(gobject
= w32_delayed_load (libraries
, Qgobject
))
7894 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
7895 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
7898 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
7899 LOAD_IMGLIB_FN (library
, rsvg_handle_get_dimensions
);
7900 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
7901 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
7902 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
7903 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
7905 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
7906 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
7907 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
7908 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
7909 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
7910 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
7911 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
7912 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
7914 LOAD_IMGLIB_FN (gobject
, g_type_init
);
7915 LOAD_IMGLIB_FN (gobject
, g_object_unref
);
7916 LOAD_IMGLIB_FN (glib
, g_error_free
);
7922 /* The following aliases for library functions allow dynamic loading
7923 to be used on some platforms. */
7924 #define fn_rsvg_handle_new rsvg_handle_new
7925 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7926 #define fn_rsvg_handle_write rsvg_handle_write
7927 #define fn_rsvg_handle_close rsvg_handle_close
7928 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7929 #define fn_rsvg_handle_free rsvg_handle_free
7931 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7932 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7933 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7934 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7935 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7936 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7937 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7938 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7940 #define fn_g_type_init g_type_init
7941 #define fn_g_object_unref g_object_unref
7942 #define fn_g_error_free g_error_free
7943 #endif /* !HAVE_NTGUI */
7945 /* Load SVG image IMG for use on frame F. Value is non-zero if
7946 successful. this function will go into the svg_type structure, and
7947 the prototype thus needs to be compatible with that structure. */
7955 Lisp_Object file_name
;
7957 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7958 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7959 if (STRINGP (file_name
))
7962 unsigned char *contents
;
7964 struct gcpro gcpro1
;
7966 file
= x_find_image_file (file_name
);
7968 if (!STRINGP (file
))
7970 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7975 /* Read the entire file into memory. */
7976 contents
= slurp_file (SDATA (file
), &size
);
7977 if (contents
== NULL
)
7979 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
7983 /* If the file was slurped into memory properly, parse it. */
7984 success_p
= svg_load_image (f
, img
, contents
, size
);
7988 /* Else its not a file, its a lisp object. Load the image from a
7989 lisp object rather than a file. */
7994 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7995 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8001 /* svg_load_image is a helper function for svg_load, which does the
8002 actual loading given contents and size, apart from frame and image
8003 structures, passed from svg_load.
8005 Uses librsvg to do most of the image processing.
8007 Returns non-zero when successful. */
8009 svg_load_image (f
, img
, contents
, size
)
8010 /* Pointer to emacs frame structure. */
8012 /* Pointer to emacs image structure. */
8014 /* String containing the SVG XML data to be parsed. */
8015 unsigned char *contents
;
8016 /* Size of data in bytes. */
8019 RsvgHandle
*rsvg_handle
;
8020 RsvgDimensionData dimension_data
;
8021 GError
*error
= NULL
;
8025 const guint8
*pixels
;
8028 Lisp_Object specified_bg
;
8033 /* g_type_init is a glib function that must be called prior to using
8034 gnome type library functions. */
8036 /* Make a handle to a new rsvg object. */
8037 rsvg_handle
= (RsvgHandle
*) fn_rsvg_handle_new ();
8039 /* Parse the contents argument and fill in the rsvg_handle. */
8040 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8041 if (error
) goto rsvg_error
;
8043 /* The parsing is complete, rsvg_handle is ready to used, close it
8044 for further writes. */
8045 fn_rsvg_handle_close (rsvg_handle
, &error
);
8046 if (error
) goto rsvg_error
;
8048 fn_rsvg_handle_get_dimensions (rsvg_handle
, &dimension_data
);
8049 if (! check_image_size (f
, dimension_data
.width
, dimension_data
.height
))
8052 /* We can now get a valid pixel buffer from the svg file, if all
8054 pixbuf
= (GdkPixbuf
*) fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8055 if (!pixbuf
) goto rsvg_error
;
8056 fn_g_object_unref (rsvg_handle
);
8058 /* Extract some meta data from the svg handle. */
8059 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8060 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8061 pixels
= (const guint8
*) fn_gdk_pixbuf_get_pixels (pixbuf
);
8062 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8064 /* Validate the svg meta data. */
8065 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8066 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8067 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8068 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8070 /* Try to create a x pixmap to hold the svg pixmap. */
8071 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8073 fn_g_object_unref (pixbuf
);
8077 init_color_table ();
8079 /* Handle alpha channel by combining the image with a background
8081 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8082 if (!STRINGP (specified_bg
)
8083 || !x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8086 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8087 x_query_color (f
, &background
);
8089 ns_query_color(FRAME_BACKGROUND_COLOR (f
), &background
, 1);
8093 /* SVG pixmaps specify transparency in the last byte, so right
8094 shift 8 bits to get rid of it, since emacs doesn't support
8096 background
.red
>>= 8;
8097 background
.green
>>= 8;
8098 background
.blue
>>= 8;
8100 /* This loop handles opacity values, since Emacs assumes
8101 non-transparent images. Each pixel must be "flattened" by
8102 calculating the resulting color, given the transparency of the
8103 pixel, and the image background color. */
8104 for (y
= 0; y
< height
; ++y
)
8106 for (x
= 0; x
< width
; ++x
)
8116 opacity
= *pixels
++;
8118 red
= ((red
* opacity
)
8119 + (background
.red
* ((1 << 8) - opacity
)));
8120 green
= ((green
* opacity
)
8121 + (background
.green
* ((1 << 8) - opacity
)));
8122 blue
= ((blue
* opacity
)
8123 + (background
.blue
* ((1 << 8) - opacity
)));
8125 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8128 pixels
+= rowstride
- 4 * width
;
8131 #ifdef COLOR_TABLE_SUPPORT
8132 /* Remember colors allocated for this image. */
8133 img
->colors
= colors_in_color_table (&img
->ncolors
);
8134 free_color_table ();
8135 #endif /* COLOR_TABLE_SUPPORT */
8137 fn_g_object_unref (pixbuf
);
8140 img
->height
= height
;
8142 /* Maybe fill in the background field while we have ximg handy.
8143 Casting avoids a GCC warning. */
8144 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8146 /* Put the image into the pixmap, then free the X image and its
8148 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8149 x_destroy_x_image (ximg
);
8154 fn_g_object_unref (rsvg_handle
);
8155 /* FIXME: Use error->message so the user knows what is the actual
8156 problem with the image. */
8157 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8158 fn_g_error_free (error
);
8162 #endif /* defined (HAVE_RSVG) */
8167 /***********************************************************************
8169 ***********************************************************************/
8171 #ifdef HAVE_X_WINDOWS
8172 #define HAVE_GHOSTSCRIPT 1
8173 #endif /* HAVE_X_WINDOWS */
8175 /* The symbol `postscript' identifying images of this type. */
8177 Lisp_Object Qpostscript
;
8179 #ifdef HAVE_GHOSTSCRIPT
8181 static int gs_image_p
P_ ((Lisp_Object object
));
8182 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8183 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8185 /* Keyword symbols. */
8187 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8189 /* Indices of image specification fields in gs_format, below. */
8191 enum gs_keyword_index
8209 /* Vector of image_keyword structures describing the format
8210 of valid user-defined image specifications. */
8212 static struct image_keyword gs_format
[GS_LAST
] =
8214 {":type", IMAGE_SYMBOL_VALUE
, 1},
8215 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8216 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8217 {":file", IMAGE_STRING_VALUE
, 1},
8218 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8219 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8220 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8221 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8222 {":relief", IMAGE_INTEGER_VALUE
, 0},
8223 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8224 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8225 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8226 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8229 /* Structure describing the image type `ghostscript'. */
8231 static struct image_type gs_type
=
8241 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8244 gs_clear_image (f
, img
)
8248 /* IMG->data.ptr_val may contain a recorded colormap. */
8249 xfree (img
->data
.ptr_val
);
8250 x_clear_image (f
, img
);
8254 /* Return non-zero if OBJECT is a valid Ghostscript image
8261 struct image_keyword fmt
[GS_LAST
];
8265 bcopy (gs_format
, fmt
, sizeof fmt
);
8267 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8270 /* Bounding box must be a list or vector containing 4 integers. */
8271 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8274 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8275 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8280 else if (VECTORP (tem
))
8282 if (XVECTOR (tem
)->size
!= 4)
8284 for (i
= 0; i
< 4; ++i
)
8285 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8295 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8304 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8305 struct gcpro gcpro1
, gcpro2
;
8307 double in_width
, in_height
;
8308 Lisp_Object pixel_colors
= Qnil
;
8310 /* Compute pixel size of pixmap needed from the given size in the
8311 image specification. Sizes in the specification are in pt. 1 pt
8312 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8314 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8315 in_width
= XFASTINT (pt_width
) / 72.0;
8316 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8317 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8318 in_height
= XFASTINT (pt_height
) / 72.0;
8319 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8321 if (!check_image_size (f
, img
->width
, img
->height
))
8323 image_error ("Invalid image size", Qnil
, Qnil
);
8327 /* Create the pixmap. */
8328 xassert (img
->pixmap
== NO_PIXMAP
);
8330 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8332 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8333 img
->width
, img
->height
,
8334 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8339 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8343 /* Call the loader to fill the pixmap. It returns a process object
8344 if successful. We do not record_unwind_protect here because
8345 other places in redisplay like calling window scroll functions
8346 don't either. Let the Lisp loader use `unwind-protect' instead. */
8347 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8349 sprintf (buffer
, "%lu %lu",
8350 (unsigned long) FRAME_X_WINDOW (f
),
8351 (unsigned long) img
->pixmap
);
8352 window_and_pixmap_id
= build_string (buffer
);
8354 sprintf (buffer
, "%lu %lu",
8355 FRAME_FOREGROUND_PIXEL (f
),
8356 FRAME_BACKGROUND_PIXEL (f
));
8357 pixel_colors
= build_string (buffer
);
8359 XSETFRAME (frame
, f
);
8360 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8362 loader
= intern ("gs-load-image");
8364 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8365 make_number (img
->width
),
8366 make_number (img
->height
),
8367 window_and_pixmap_id
,
8370 return PROCESSP (img
->data
.lisp_val
);
8374 /* Kill the Ghostscript process that was started to fill PIXMAP on
8375 frame F. Called from XTread_socket when receiving an event
8376 telling Emacs that Ghostscript has finished drawing. */
8379 x_kill_gs_process (pixmap
, f
)
8383 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
8387 /* Find the image containing PIXMAP. */
8388 for (i
= 0; i
< c
->used
; ++i
)
8389 if (c
->images
[i
]->pixmap
== pixmap
)
8392 /* Should someone in between have cleared the image cache, for
8393 instance, give up. */
8397 /* Kill the GS process. We should have found PIXMAP in the image
8398 cache and its image should contain a process object. */
8400 xassert (PROCESSP (img
->data
.lisp_val
));
8401 Fkill_process (img
->data
.lisp_val
, Qnil
);
8402 img
->data
.lisp_val
= Qnil
;
8404 #if defined (HAVE_X_WINDOWS)
8406 /* On displays with a mutable colormap, figure out the colors
8407 allocated for the image by looking at the pixels of an XImage for
8409 class = FRAME_X_VISUAL (f
)->class;
8410 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8416 /* Try to get an XImage for img->pixmep. */
8417 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8418 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8423 /* Initialize the color table. */
8424 init_color_table ();
8426 /* For each pixel of the image, look its color up in the
8427 color table. After having done so, the color table will
8428 contain an entry for each color used by the image. */
8429 for (y
= 0; y
< img
->height
; ++y
)
8430 for (x
= 0; x
< img
->width
; ++x
)
8432 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8433 lookup_pixel_color (f
, pixel
);
8436 /* Record colors in the image. Free color table and XImage. */
8437 #ifdef COLOR_TABLE_SUPPORT
8438 img
->colors
= colors_in_color_table (&img
->ncolors
);
8439 free_color_table ();
8441 XDestroyImage (ximg
);
8443 #if 0 /* This doesn't seem to be the case. If we free the colors
8444 here, we get a BadAccess later in x_clear_image when
8445 freeing the colors. */
8446 /* We have allocated colors once, but Ghostscript has also
8447 allocated colors on behalf of us. So, to get the
8448 reference counts right, free them once. */
8450 x_free_colors (f
, img
->colors
, img
->ncolors
);
8454 image_error ("Cannot get X image of `%s'; colors will not be freed",
8459 #endif /* HAVE_X_WINDOWS */
8461 /* Now that we have the pixmap, compute mask and transform the
8462 image if requested. */
8464 postprocess_image (f
, img
);
8468 #endif /* HAVE_GHOSTSCRIPT */
8471 /***********************************************************************
8473 ***********************************************************************/
8477 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8478 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8482 return valid_image_p (spec
) ? Qt
: Qnil
;
8486 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8492 if (valid_image_p (spec
))
8493 id
= lookup_image (SELECTED_FRAME (), spec
);
8496 return make_number (id
);
8499 #endif /* GLYPH_DEBUG != 0 */
8502 /***********************************************************************
8504 ***********************************************************************/
8507 /* Image types that rely on external libraries are loaded dynamically
8508 if the library is available. */
8509 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8510 define_image_type (image_type, init_lib_fn (libraries))
8512 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8513 define_image_type (image_type, 1)
8514 #endif /* HAVE_NTGUI */
8516 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8517 doc
: /* Initialize image library implementing image type TYPE.
8518 Return non-nil if TYPE is a supported image type.
8520 Image types pbm and xbm are prebuilt; other types are loaded here.
8521 Libraries to load are specified in alist LIBRARIES (usually, the value
8522 of `image-library-alist', which see). */)
8524 Lisp_Object type
, libraries
;
8528 /* Don't try to reload the library. */
8529 tested
= Fassq (type
, Vimage_type_cache
);
8531 return XCDR (tested
);
8533 #if defined (HAVE_XPM) || defined (HAVE_NS)
8534 if (EQ (type
, Qxpm
))
8535 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8538 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8539 if (EQ (type
, Qjpeg
))
8540 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8543 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8544 if (EQ (type
, Qtiff
))
8545 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8548 #if defined (HAVE_GIF) || defined (HAVE_NS)
8549 if (EQ (type
, Qgif
))
8550 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8553 #if defined (HAVE_PNG) || defined (HAVE_NS)
8554 if (EQ (type
, Qpng
))
8555 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8558 #if defined (HAVE_RSVG)
8559 if (EQ (type
, Qsvg
))
8560 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
8563 #ifdef HAVE_GHOSTSCRIPT
8564 if (EQ (type
, Qpostscript
))
8565 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8568 /* If the type is not recognized, avoid testing it ever again. */
8569 CACHE_IMAGE_TYPE (type
, Qnil
);
8576 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8578 /* Initialize this only once, since that's what we do with Vimage_types
8579 and they are supposed to be in sync. Initializing here gives correct
8580 operation on GNU/Linux of calling dump-emacs after loading some images. */
8583 /* Must be defined now becase we're going to update it below, while
8584 defining the supported image types. */
8585 DEFVAR_LISP ("image-types", &Vimage_types
,
8586 doc
: /* List of potentially supported image types.
8587 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8588 To check whether it is really supported, use `image-type-available-p'. */);
8589 Vimage_types
= Qnil
;
8591 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8592 doc
: /* Alist of image types vs external libraries needed to display them.
8594 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8595 representing a supported image type, and the rest are strings giving
8596 alternate filenames for the corresponding external libraries.
8598 Emacs tries to load the libraries in the order they appear on the
8599 list; if none is loaded, the running session of Emacs won't
8600 support the image type. Types 'pbm and 'xbm don't need to be
8601 listed; they are always supported. */);
8602 Vimage_library_alist
= Qnil
;
8603 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8605 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8606 doc
: /* Maximum size of images.
8607 Emacs will not load an image into memory if its pixel width or
8608 pixel height exceeds this limit.
8610 If the value is an integer, it directly specifies the maximum
8611 image height and width, measured in pixels. If it is a floating
8612 point number, it specifies the maximum image height and width
8613 as a ratio to the frame height and width. If the value is
8614 non-numeric, there is no explicit limit on the size of images. */);
8615 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8617 Vimage_type_cache
= Qnil
;
8618 staticpro (&Vimage_type_cache
);
8620 Qpbm
= intern ("pbm");
8622 ADD_IMAGE_TYPE (Qpbm
);
8624 Qxbm
= intern ("xbm");
8626 ADD_IMAGE_TYPE (Qxbm
);
8628 define_image_type (&xbm_type
, 1);
8629 define_image_type (&pbm_type
, 1);
8631 Qcount
= intern ("count");
8632 staticpro (&Qcount
);
8634 QCascent
= intern (":ascent");
8635 staticpro (&QCascent
);
8636 QCmargin
= intern (":margin");
8637 staticpro (&QCmargin
);
8638 QCrelief
= intern (":relief");
8639 staticpro (&QCrelief
);
8640 QCconversion
= intern (":conversion");
8641 staticpro (&QCconversion
);
8642 QCcolor_symbols
= intern (":color-symbols");
8643 staticpro (&QCcolor_symbols
);
8644 QCheuristic_mask
= intern (":heuristic-mask");
8645 staticpro (&QCheuristic_mask
);
8646 QCindex
= intern (":index");
8647 staticpro (&QCindex
);
8648 QCmatrix
= intern (":matrix");
8649 staticpro (&QCmatrix
);
8650 QCcolor_adjustment
= intern (":color-adjustment");
8651 staticpro (&QCcolor_adjustment
);
8652 QCmask
= intern (":mask");
8653 staticpro (&QCmask
);
8655 Qlaplace
= intern ("laplace");
8656 staticpro (&Qlaplace
);
8657 Qemboss
= intern ("emboss");
8658 staticpro (&Qemboss
);
8659 Qedge_detection
= intern ("edge-detection");
8660 staticpro (&Qedge_detection
);
8661 Qheuristic
= intern ("heuristic");
8662 staticpro (&Qheuristic
);
8664 Qpostscript
= intern ("postscript");
8665 staticpro (&Qpostscript
);
8666 #ifdef HAVE_GHOSTSCRIPT
8667 ADD_IMAGE_TYPE (Qpostscript
);
8668 QCloader
= intern (":loader");
8669 staticpro (&QCloader
);
8670 QCbounding_box
= intern (":bounding-box");
8671 staticpro (&QCbounding_box
);
8672 QCpt_width
= intern (":pt-width");
8673 staticpro (&QCpt_width
);
8674 QCpt_height
= intern (":pt-height");
8675 staticpro (&QCpt_height
);
8676 #endif /* HAVE_GHOSTSCRIPT */
8678 #if defined (HAVE_XPM) || defined (HAVE_NS)
8679 Qxpm
= intern ("xpm");
8681 ADD_IMAGE_TYPE (Qxpm
);
8684 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8685 Qjpeg
= intern ("jpeg");
8687 ADD_IMAGE_TYPE (Qjpeg
);
8690 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8691 Qtiff
= intern ("tiff");
8693 ADD_IMAGE_TYPE (Qtiff
);
8696 #if defined (HAVE_GIF) || defined (HAVE_NS)
8697 Qgif
= intern ("gif");
8699 ADD_IMAGE_TYPE (Qgif
);
8702 #if defined (HAVE_PNG) || defined (HAVE_NS)
8703 Qpng
= intern ("png");
8705 ADD_IMAGE_TYPE (Qpng
);
8708 #if defined (HAVE_RSVG)
8709 Qsvg
= intern ("svg");
8711 ADD_IMAGE_TYPE (Qsvg
);
8713 /* Other libraries used directly by svg code. */
8714 Qgdk_pixbuf
= intern ("gdk-pixbuf");
8715 staticpro (&Qgdk_pixbuf
);
8716 Qglib
= intern ("glib");
8718 Qgobject
= intern ("gobject");
8719 staticpro (&Qgobject
);
8720 #endif /* HAVE_NTGUI */
8721 #endif /* HAVE_RSVG */
8723 defsubr (&Sinit_image_library
);
8724 defsubr (&Sclear_image_cache
);
8725 defsubr (&Simage_refresh
);
8726 defsubr (&Simage_size
);
8727 defsubr (&Simage_mask_p
);
8728 defsubr (&Simage_extension_data
);
8732 defsubr (&Slookup_image
);
8735 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8736 doc
: /* Non-nil means always draw a cross over disabled images.
8737 Disabled images are those having a `:conversion disabled' property.
8738 A cross is always drawn on black & white displays. */);
8739 cross_disabled_images
= 0;
8741 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8742 doc
: /* List of directories to search for window system bitmap files. */);
8743 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8745 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8746 doc
: /* Time after which cached images are removed from the cache.
8747 When an image has not been displayed this many seconds, remove it
8748 from the image cache. Value must be an integer or nil with nil
8749 meaning don't clear the cache. */);
8750 Vimage_cache_eviction_delay
= make_number (30 * 60);
8758 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8759 (do not change this comment) */