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
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)
82 #endif /* HAVE_NTGUI */
86 #include <sys/types.h>
89 #undef COLOR_TABLE_SUPPORT
91 typedef struct ns_bitmap_record Bitmap_Record
;
93 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
96 #define RGB_PIXEL_COLOR unsigned long
99 #define PIX_MASK_RETAIN 0
100 #define PIX_MASK_DRAW 1
102 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
103 #define x_defined_color(f, name, color_def, alloc) \
104 ns_defined_color (f, name, color_def, alloc, 0)
105 #define FRAME_X_SCREEN(f) 0
106 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
110 /* Search path for bitmap files. */
112 Lisp_Object Vx_bitmap_file_path
;
115 static void x_disable_image
P_ ((struct frame
*, struct image
*));
116 static void x_edge_detection
P_ ((struct frame
*, struct image
*, Lisp_Object
,
119 static void init_color_table
P_ ((void));
120 static unsigned long lookup_rgb_color
P_ ((struct frame
*f
, int r
, int g
, int b
));
121 #ifdef COLOR_TABLE_SUPPORT
122 static void free_color_table
P_ ((void));
123 static unsigned long *colors_in_color_table
P_ ((int *n
));
124 static unsigned long lookup_pixel_color
P_ ((struct frame
*f
, unsigned long p
));
127 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
128 id, which is just an int that this section returns. Bitmaps are
129 reference counted so they can be shared among frames.
131 Bitmap indices are guaranteed to be > 0, so a negative number can
132 be used to indicate no bitmap.
134 If you use x_create_bitmap_from_data, then you must keep track of
135 the bitmaps yourself. That is, creating a bitmap from the same
136 data more than once will not be caught. */
141 XGetImage (display
, pixmap
, x
, y
, width
, height
, plane_mask
, format
)
142 Display
*display
; /* not used */
144 int x
, y
; /* not used */
145 unsigned int width
, height
; /* not used */
146 unsigned long plane_mask
; /* not used */
147 int format
; /* not used */
149 #if !USE_MAC_IMAGE_IO
151 xassert (x
== 0 && y
== 0);
154 SetRect (&ri
, 0, 0, width
, height
);
155 xassert (EqualRect (&ri
, GetPixBounds (GetGWorldPixMap (pixmap
), &rp
)));
157 xassert (! (pixelsLocked
& GetPixelsState (GetGWorldPixMap (pixmap
))));
160 LockPixels (GetGWorldPixMap (pixmap
));
167 XPutPixel (ximage
, x
, y
, pixel
)
173 if (ximage
->bits_per_pixel
== 32)
174 ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
176 ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
] = pixel
;
178 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
179 short depth
= GetPixDepth (pixmap
);
181 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
184 char *base_addr
= GetPixBaseAddr (pixmap
);
185 short row_bytes
= GetPixRowBytes (pixmap
);
187 ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] = 0xff000000 | pixel
;
193 char *base_addr
= GetPixBaseAddr (pixmap
);
194 short row_bytes
= GetPixRowBytes (pixmap
);
196 if (pixel
== PIX_MASK_DRAW
)
197 base_addr
[y
* row_bytes
+ x
/ 8] |= (1 << 7) >> (x
& 7);
199 base_addr
[y
* row_bytes
+ x
/ 8] &= ~((1 << 7) >> (x
& 7));
207 GetGWorld (&old_port
, &old_gdh
);
208 SetGWorld (ximage
, NULL
);
210 color
.red
= RED16_FROM_ULONG (pixel
);
211 color
.green
= GREEN16_FROM_ULONG (pixel
);
212 color
.blue
= BLUE16_FROM_ULONG (pixel
);
214 SetCPixel (x
, y
, &color
);
216 SetGWorld (old_port
, old_gdh
);
222 XGetPixel (ximage
, x
, y
)
227 if (ximage
->bits_per_pixel
== 32)
228 return ((unsigned int *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
230 return ((unsigned char *)(ximage
->data
+ y
* ximage
->bytes_per_line
))[x
];
232 PixMapHandle pixmap
= GetGWorldPixMap (ximage
);
233 short depth
= GetPixDepth (pixmap
);
235 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
238 char *base_addr
= GetPixBaseAddr (pixmap
);
239 short row_bytes
= GetPixRowBytes (pixmap
);
241 return ((unsigned long *) (base_addr
+ y
* row_bytes
))[x
] & 0x00ffffff;
247 char *base_addr
= GetPixBaseAddr (pixmap
);
248 short row_bytes
= GetPixRowBytes (pixmap
);
250 if (base_addr
[y
* row_bytes
+ x
/ 8] & (1 << (~x
& 7)))
251 return PIX_MASK_DRAW
;
253 return PIX_MASK_RETAIN
;
261 GetGWorld (&old_port
, &old_gdh
);
262 SetGWorld (ximage
, NULL
);
264 GetCPixel (x
, y
, &color
);
266 SetGWorld (old_port
, old_gdh
);
267 return RGB_TO_ULONG (color
.red
>> 8, color
.green
>> 8, color
.blue
>> 8);
276 #if !USE_MAC_IMAGE_IO
277 UnlockPixels (GetGWorldPixMap (ximg
));
284 mac_data_provider_release_data (info
, data
, size
)
289 xfree ((void *)data
);
294 mac_create_cg_image_from_image (f
, img
)
299 XImagePtr ximg
= img
->pixmap
;
300 CGDataProviderRef provider
;
306 unsigned long color
, alpha
;
308 for (y
= 0; y
< ximg
->height
; y
++)
309 for (x
= 0; x
< ximg
->width
; x
++)
311 color
= XGetPixel (ximg
, x
, y
);
312 alpha
= XGetPixel (img
->mask
, x
, y
);
313 XPutPixel (ximg
, x
, y
,
314 ARGB_TO_ULONG (alpha
,
315 RED_FROM_ULONG (color
)
316 * alpha
/ PIX_MASK_DRAW
,
317 GREEN_FROM_ULONG (color
)
318 * alpha
/ PIX_MASK_DRAW
,
319 BLUE_FROM_ULONG (color
)
320 * alpha
/ PIX_MASK_DRAW
));
322 xfree (img
->mask
->data
);
323 img
->mask
->data
= NULL
;
326 provider
= CGDataProviderCreateWithData (NULL
, ximg
->data
,
327 ximg
->bytes_per_line
* ximg
->height
,
328 mac_data_provider_release_data
);
330 result
= CGImageCreate (ximg
->width
, ximg
->height
, 8, 32,
331 ximg
->bytes_per_line
, mac_cg_color_space_rgb
,
332 ((img
->mask
? kCGImageAlphaPremultipliedFirst
333 : kCGImageAlphaNoneSkipFirst
)
334 | kCGBitmapByteOrder32Host
),
335 provider
, NULL
, 0, kCGRenderingIntentDefault
);
336 CGDataProviderRelease (provider
);
342 CGImageRef result
= NULL
;
349 mask
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
350 img
->width
, img
->height
, 1);
357 GetGWorld (&old_port
, &old_gdh
);
358 SetGWorld (mask
, NULL
);
359 BackColor (blackColor
); /* Don't mask. */
360 SetRect (&r
, 0, 0, img
->width
, img
->height
);
362 SetGWorld (old_port
, old_gdh
);
367 CreateCGImageFromPixMaps (GetGWorldPixMap (img
->pixmap
),
368 GetGWorldPixMap (mask
), &result
);
369 if (mask
!= img
->mask
)
370 XFreePixmap (FRAME_X_DISPLAY (f
), mask
);
377 #endif /* USE_CG_DRAWING */
382 XGetImage (Display
*display
, Pixmap pixmap
, int x
, int y
,
383 unsigned int width
, unsigned int height
,
384 unsigned long plane_mask
, int format
)
386 /* TODO: not sure what this function is supposed to do.. */
387 ns_retain_object(pixmap
);
391 /* use with imgs created by ns_image_for_XPM */
393 XGetPixel (XImagePtr ximage
, int x
, int y
)
395 return ns_get_pixel(ximage
, x
, y
);
398 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
399 pixel is assumed to be in form RGB */
401 XPutPixel (XImagePtr ximage
, int x
, int y
, unsigned long pixel
)
403 ns_put_pixel(ximage
, x
, y
, pixel
);
408 /* Functions to access the contents of a bitmap, given an id. */
411 x_bitmap_height (f
, id
)
415 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].height
;
419 x_bitmap_width (f
, id
)
423 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].width
;
426 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
428 x_bitmap_pixmap (f
, id
)
432 return (int) FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].pixmap
;
436 #ifdef HAVE_X_WINDOWS
438 x_bitmap_mask (f
, id
)
442 return FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].mask
;
446 /* Allocate a new bitmap record. Returns index of new record. */
449 x_allocate_bitmap_record (f
)
452 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
455 if (dpyinfo
->bitmaps
== NULL
)
457 dpyinfo
->bitmaps_size
= 10;
459 = (Bitmap_Record
*) xmalloc (dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
460 dpyinfo
->bitmaps_last
= 1;
464 if (dpyinfo
->bitmaps_last
< dpyinfo
->bitmaps_size
)
465 return ++dpyinfo
->bitmaps_last
;
467 for (i
= 0; i
< dpyinfo
->bitmaps_size
; ++i
)
468 if (dpyinfo
->bitmaps
[i
].refcount
== 0)
471 dpyinfo
->bitmaps_size
*= 2;
473 = (Bitmap_Record
*) xrealloc (dpyinfo
->bitmaps
,
474 dpyinfo
->bitmaps_size
* sizeof (Bitmap_Record
));
475 return ++dpyinfo
->bitmaps_last
;
478 /* Add one reference to the reference count of the bitmap with id ID. */
481 x_reference_bitmap (f
, id
)
485 ++FRAME_X_DISPLAY_INFO (f
)->bitmaps
[id
- 1].refcount
;
488 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
491 x_create_bitmap_from_data (f
, bits
, width
, height
)
494 unsigned int width
, height
;
496 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
499 #ifdef HAVE_X_WINDOWS
501 bitmap
= XCreateBitmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
502 bits
, width
, height
);
505 #endif /* HAVE_X_WINDOWS */
509 bitmap
= CreateBitmap (width
, height
,
510 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_planes
,
511 FRAME_X_DISPLAY_INFO (XFRAME (frame
))->n_cbits
,
515 #endif /* HAVE_NTGUI */
518 void *bitmap
= ns_image_from_XBM(bits
, width
, height
);
523 id
= x_allocate_bitmap_record (f
);
526 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
527 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
530 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
531 dpyinfo
->bitmaps
[id
- 1].height
= height
;
532 dpyinfo
->bitmaps
[id
- 1].width
= width
;
533 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
535 #ifdef HAVE_X_WINDOWS
536 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
537 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
538 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
539 #endif /* HAVE_X_WINDOWS */
542 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
543 dpyinfo
->bitmaps
[id
- 1].hinst
= NULL
;
544 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
545 #endif /* HAVE_NTGUI */
550 /* Create bitmap from file FILE for frame F. */
553 x_create_bitmap_from_file (f
, file
)
557 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
560 return -1; /* W32_TODO : bitmap support */
561 #endif /* HAVE_NTGUI */
565 void *bitmap
= ns_image_from_file(file
);
571 id
= x_allocate_bitmap_record (f
);
572 dpyinfo
->bitmaps
[id
- 1].img
= bitmap
;
573 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
574 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
575 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
576 dpyinfo
->bitmaps
[id
- 1].height
= ns_image_width(bitmap
);
577 dpyinfo
->bitmaps
[id
- 1].width
= ns_image_height(bitmap
);
578 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
582 #ifdef HAVE_X_WINDOWS
583 unsigned int width
, height
;
585 int xhot
, yhot
, result
, id
;
590 /* Look for an existing bitmap with the same name. */
591 for (id
= 0; id
< dpyinfo
->bitmaps_last
; ++id
)
593 if (dpyinfo
->bitmaps
[id
].refcount
594 && dpyinfo
->bitmaps
[id
].file
595 && !strcmp (dpyinfo
->bitmaps
[id
].file
, (char *) SDATA (file
)))
597 ++dpyinfo
->bitmaps
[id
].refcount
;
602 /* Search bitmap-file-path for the file, if appropriate. */
603 fd
= openp (Vx_bitmap_file_path
, file
, Qnil
, &found
, Qnil
);
608 filename
= (char *) SDATA (found
);
610 result
= XReadBitmapFile (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
611 filename
, &width
, &height
, &bitmap
, &xhot
, &yhot
);
612 if (result
!= BitmapSuccess
)
615 id
= x_allocate_bitmap_record (f
);
616 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
617 dpyinfo
->bitmaps
[id
- 1].have_mask
= 0;
618 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
619 dpyinfo
->bitmaps
[id
- 1].file
= (char *) xmalloc (SBYTES (file
) + 1);
620 dpyinfo
->bitmaps
[id
- 1].depth
= 1;
621 dpyinfo
->bitmaps
[id
- 1].height
= height
;
622 dpyinfo
->bitmaps
[id
- 1].width
= width
;
623 strcpy (dpyinfo
->bitmaps
[id
- 1].file
, SDATA (file
));
626 #endif /* HAVE_X_WINDOWS */
632 free_bitmap_record (dpyinfo
, bm
)
633 Display_Info
*dpyinfo
;
636 #ifdef HAVE_X_WINDOWS
637 XFreePixmap (dpyinfo
->display
, bm
->pixmap
);
639 XFreePixmap (dpyinfo
->display
, bm
->mask
);
640 #endif /* HAVE_X_WINDOWS */
643 DeleteObject (bm
->pixmap
);
644 #endif /* HAVE_NTGUI */
647 ns_release_object(bm
->img
);
657 /* Remove reference to bitmap with id number ID. */
660 x_destroy_bitmap (f
, id
)
664 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
668 Bitmap_Record
*bm
= &dpyinfo
->bitmaps
[id
- 1];
670 if (--bm
->refcount
== 0)
673 free_bitmap_record (dpyinfo
, bm
);
679 /* Free all the bitmaps for the display specified by DPYINFO. */
682 x_destroy_all_bitmaps (dpyinfo
)
683 Display_Info
*dpyinfo
;
686 Bitmap_Record
*bm
= dpyinfo
->bitmaps
;
688 for (i
= 0; i
< dpyinfo
->bitmaps_last
; i
++, bm
++)
689 if (bm
->refcount
> 0)
690 free_bitmap_record (dpyinfo
, bm
);
692 dpyinfo
->bitmaps_last
= 0;
696 #ifdef HAVE_X_WINDOWS
698 /* Useful functions defined in the section
699 `Image type independent image structures' below. */
701 static unsigned long four_corners_best
P_ ((XImagePtr ximg
,
704 unsigned long height
));
706 static int x_create_x_image_and_pixmap
P_ ((struct frame
*f
, int width
, int height
,
707 int depth
, XImagePtr
*ximg
,
710 static void x_destroy_x_image
P_ ((XImagePtr ximg
));
713 /* Create a mask of a bitmap. Note is this not a perfect mask.
714 It's nicer with some borders in this context */
717 x_create_bitmap_mask (f
, id
)
722 XImagePtr ximg
, mask_img
;
723 unsigned long width
, height
;
726 unsigned long x
, y
, xp
, xm
, yp
, ym
;
729 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
734 pixmap
= x_bitmap_pixmap (f
, id
);
735 width
= x_bitmap_width (f
, id
);
736 height
= x_bitmap_height (f
, id
);
739 ximg
= XGetImage (FRAME_X_DISPLAY (f
), pixmap
, 0, 0, width
, height
,
748 result
= x_create_x_image_and_pixmap (f
, width
, height
, 1, &mask_img
, &mask
);
753 XDestroyImage (ximg
);
757 bg
= four_corners_best (ximg
, NULL
, width
, height
);
759 for (y
= 0; y
< ximg
->height
; ++y
)
761 for (x
= 0; x
< ximg
->width
; ++x
)
763 xp
= x
!= ximg
->width
- 1 ? x
+ 1 : 0;
764 xm
= x
!= 0 ? x
- 1 : ximg
->width
- 1;
765 yp
= y
!= ximg
->height
- 1 ? y
+ 1 : 0;
766 ym
= y
!= 0 ? y
- 1 : ximg
->height
- 1;
767 if (XGetPixel (ximg
, x
, y
) == bg
768 && XGetPixel (ximg
, x
, yp
) == bg
769 && XGetPixel (ximg
, x
, ym
) == bg
770 && XGetPixel (ximg
, xp
, y
) == bg
771 && XGetPixel (ximg
, xp
, yp
) == bg
772 && XGetPixel (ximg
, xp
, ym
) == bg
773 && XGetPixel (ximg
, xm
, y
) == bg
774 && XGetPixel (ximg
, xm
, yp
) == bg
775 && XGetPixel (ximg
, xm
, ym
) == bg
)
776 XPutPixel (mask_img
, x
, y
, 0);
778 XPutPixel (mask_img
, x
, y
, 1);
782 xassert (interrupt_input_blocked
);
783 gc
= XCreateGC (FRAME_X_DISPLAY (f
), mask
, 0, NULL
);
784 XPutImage (FRAME_X_DISPLAY (f
), mask
, gc
, mask_img
, 0, 0, 0, 0,
786 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
788 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
789 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
791 XDestroyImage (ximg
);
792 x_destroy_x_image (mask_img
);
797 #endif /* HAVE_X_WINDOWS */
800 /***********************************************************************
802 ***********************************************************************/
804 /* Value is the number of elements of vector VECTOR. */
806 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
808 /* List of supported image types. Use define_image_type to add new
809 types. Use lookup_image_type to find a type for a given symbol. */
811 static struct image_type
*image_types
;
813 /* A list of symbols, one for each supported image type. */
815 Lisp_Object Vimage_types
;
817 /* An alist of image types and libraries that implement the type. */
819 Lisp_Object Vimage_library_alist
;
821 /* Cache for delayed-loading image types. */
823 static Lisp_Object Vimage_type_cache
;
825 /* The symbol `xbm' which is used as the type symbol for XBM images. */
831 extern Lisp_Object QCwidth
, QCheight
, QCforeground
, QCbackground
, QCfile
;
832 extern Lisp_Object QCdata
, QCtype
;
833 extern Lisp_Object Qcenter
;
834 Lisp_Object QCascent
, QCmargin
, QCrelief
, Qcount
;
835 Lisp_Object QCconversion
, QCcolor_symbols
, QCheuristic_mask
;
836 Lisp_Object QCindex
, QCmatrix
, QCcolor_adjustment
, QCmask
;
840 Lisp_Object Qlaplace
, Qemboss
, Qedge_detection
, Qheuristic
;
842 /* Time in seconds after which images should be removed from the cache
845 Lisp_Object Vimage_cache_eviction_delay
;
847 /* Function prototypes. */
849 static Lisp_Object define_image_type
P_ ((struct image_type
*type
, int loaded
));
850 static struct image_type
*lookup_image_type
P_ ((Lisp_Object symbol
));
851 static void image_error
P_ ((char *format
, Lisp_Object
, Lisp_Object
));
852 static void x_laplace
P_ ((struct frame
*, struct image
*));
853 static void x_emboss
P_ ((struct frame
*, struct image
*));
854 static int x_build_heuristic_mask
P_ ((struct frame
*, struct image
*,
857 #define CACHE_IMAGE_TYPE(type, status) \
858 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
860 #define ADD_IMAGE_TYPE(type) \
861 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
863 /* Define a new image type from TYPE. This adds a copy of TYPE to
864 image_types and caches the loading status of TYPE. */
867 define_image_type (type
, loaded
)
868 struct image_type
*type
;
877 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
878 The initialized data segment is read-only. */
879 struct image_type
*p
= (struct image_type
*) xmalloc (sizeof *p
);
880 bcopy (type
, p
, sizeof *p
);
881 p
->next
= image_types
;
886 CACHE_IMAGE_TYPE (*type
->type
, success
);
891 /* Look up image type SYMBOL, and return a pointer to its image_type
892 structure. Value is null if SYMBOL is not a known image type. */
894 static INLINE
struct image_type
*
895 lookup_image_type (symbol
)
898 struct image_type
*type
;
900 /* We must initialize the image-type if it hasn't been already. */
901 if (NILP (Finit_image_library (symbol
, Vimage_library_alist
)))
902 return 0; /* unimplemented */
904 for (type
= image_types
; type
; type
= type
->next
)
905 if (EQ (symbol
, *type
->type
))
912 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
913 valid image specification is a list whose car is the symbol
914 `image', and whose rest is a property list. The property list must
915 contain a value for key `:type'. That value must be the name of a
916 supported image type. The rest of the property list depends on the
920 valid_image_p (object
)
929 for (tem
= XCDR (object
); CONSP (tem
); tem
= XCDR (tem
))
930 if (EQ (XCAR (tem
), QCtype
))
933 if (CONSP (tem
) && SYMBOLP (XCAR (tem
)))
935 struct image_type
*type
;
936 type
= lookup_image_type (XCAR (tem
));
938 valid_p
= type
->valid_p (object
);
949 /* Log error message with format string FORMAT and argument ARG.
950 Signaling an error, e.g. when an image cannot be loaded, is not a
951 good idea because this would interrupt redisplay, and the error
952 message display would lead to another redisplay. This function
953 therefore simply displays a message. */
956 image_error (format
, arg1
, arg2
)
958 Lisp_Object arg1
, arg2
;
960 add_to_log (format
, arg1
, arg2
);
965 /***********************************************************************
967 ***********************************************************************/
969 enum image_value_type
971 IMAGE_DONT_CHECK_VALUE_TYPE
,
973 IMAGE_STRING_OR_NIL_VALUE
,
975 IMAGE_POSITIVE_INTEGER_VALUE
,
976 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
,
977 IMAGE_NON_NEGATIVE_INTEGER_VALUE
,
980 IMAGE_FUNCTION_VALUE
,
985 /* Structure used when parsing image specifications. */
989 /* Name of keyword. */
992 /* The type of value allowed. */
993 enum image_value_type type
;
995 /* Non-zero means key must be present. */
998 /* Used to recognize duplicate keywords in a property list. */
1001 /* The value that was found. */
1006 static int parse_image_spec
P_ ((Lisp_Object
, struct image_keyword
*,
1008 static Lisp_Object image_spec_value
P_ ((Lisp_Object
, Lisp_Object
, int *));
1011 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1012 has the format (image KEYWORD VALUE ...). One of the keyword/
1013 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1014 image_keywords structures of size NKEYWORDS describing other
1015 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1018 parse_image_spec (spec
, keywords
, nkeywords
, type
)
1020 struct image_keyword
*keywords
;
1030 plist
= XCDR (spec
);
1031 while (CONSP (plist
))
1033 Lisp_Object key
, value
;
1035 /* First element of a pair must be a symbol. */
1037 plist
= XCDR (plist
);
1041 /* There must follow a value. */
1044 value
= XCAR (plist
);
1045 plist
= XCDR (plist
);
1047 /* Find key in KEYWORDS. Error if not found. */
1048 for (i
= 0; i
< nkeywords
; ++i
)
1049 if (strcmp (keywords
[i
].name
, SDATA (SYMBOL_NAME (key
))) == 0)
1055 /* Record that we recognized the keyword. If a keywords
1056 was found more than once, it's an error. */
1057 keywords
[i
].value
= value
;
1058 ++keywords
[i
].count
;
1060 if (keywords
[i
].count
> 1)
1063 /* Check type of value against allowed type. */
1064 switch (keywords
[i
].type
)
1066 case IMAGE_STRING_VALUE
:
1067 if (!STRINGP (value
))
1071 case IMAGE_STRING_OR_NIL_VALUE
:
1072 if (!STRINGP (value
) && !NILP (value
))
1076 case IMAGE_SYMBOL_VALUE
:
1077 if (!SYMBOLP (value
))
1081 case IMAGE_POSITIVE_INTEGER_VALUE
:
1082 if (!INTEGERP (value
) || XINT (value
) <= 0)
1086 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
:
1087 if (INTEGERP (value
) && XINT (value
) >= 0)
1090 && INTEGERP (XCAR (value
)) && INTEGERP (XCDR (value
))
1091 && XINT (XCAR (value
)) >= 0 && XINT (XCDR (value
)) >= 0)
1095 case IMAGE_ASCENT_VALUE
:
1096 if (SYMBOLP (value
) && EQ (value
, Qcenter
))
1098 else if (INTEGERP (value
)
1099 && XINT (value
) >= 0
1100 && XINT (value
) <= 100)
1104 case IMAGE_NON_NEGATIVE_INTEGER_VALUE
:
1105 if (!INTEGERP (value
) || XINT (value
) < 0)
1109 case IMAGE_DONT_CHECK_VALUE_TYPE
:
1112 case IMAGE_FUNCTION_VALUE
:
1113 value
= indirect_function (value
);
1115 || COMPILEDP (value
)
1116 || (CONSP (value
) && EQ (XCAR (value
), Qlambda
)))
1120 case IMAGE_NUMBER_VALUE
:
1121 if (!INTEGERP (value
) && !FLOATP (value
))
1125 case IMAGE_INTEGER_VALUE
:
1126 if (!INTEGERP (value
))
1130 case IMAGE_BOOL_VALUE
:
1131 if (!NILP (value
) && !EQ (value
, Qt
))
1140 if (EQ (key
, QCtype
) && !EQ (type
, value
))
1144 /* Check that all mandatory fields are present. */
1145 for (i
= 0; i
< nkeywords
; ++i
)
1146 if (keywords
[i
].mandatory_p
&& keywords
[i
].count
== 0)
1149 return NILP (plist
);
1153 /* Return the value of KEY in image specification SPEC. Value is nil
1154 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1155 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1158 image_spec_value (spec
, key
, found
)
1159 Lisp_Object spec
, key
;
1164 xassert (valid_image_p (spec
));
1166 for (tail
= XCDR (spec
);
1167 CONSP (tail
) && CONSP (XCDR (tail
));
1168 tail
= XCDR (XCDR (tail
)))
1170 if (EQ (XCAR (tail
), key
))
1174 return XCAR (XCDR (tail
));
1184 DEFUN ("image-size", Fimage_size
, Simage_size
, 1, 3, 0,
1185 doc
: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1186 PIXELS non-nil means return the size in pixels, otherwise return the
1187 size in canonical character units.
1188 FRAME is the frame on which the image will be displayed. FRAME nil
1189 or omitted means use the selected frame. */)
1190 (spec
, pixels
, frame
)
1191 Lisp_Object spec
, pixels
, frame
;
1196 if (valid_image_p (spec
))
1198 struct frame
*f
= check_x_frame (frame
);
1199 int id
= lookup_image (f
, spec
);
1200 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1201 int width
= img
->width
+ 2 * img
->hmargin
;
1202 int height
= img
->height
+ 2 * img
->vmargin
;
1205 size
= Fcons (make_float ((double) width
/ FRAME_COLUMN_WIDTH (f
)),
1206 make_float ((double) height
/ FRAME_LINE_HEIGHT (f
)));
1208 size
= Fcons (make_number (width
), make_number (height
));
1211 error ("Invalid image specification");
1217 DEFUN ("image-mask-p", Fimage_mask_p
, Simage_mask_p
, 1, 2, 0,
1218 doc
: /* Return t if image SPEC has a mask bitmap.
1219 FRAME is the frame on which the image will be displayed. FRAME nil
1220 or omitted means use the selected frame. */)
1222 Lisp_Object spec
, frame
;
1227 if (valid_image_p (spec
))
1229 struct frame
*f
= check_x_frame (frame
);
1230 int id
= lookup_image (f
, spec
);
1231 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1236 error ("Invalid image specification");
1241 DEFUN ("image-extension-data", Fimage_extension_data
, Simage_extension_data
, 1, 2, 0,
1242 doc
: /* Return extension data for image SPEC.
1243 FRAME is the frame on which the image will be displayed. FRAME nil
1244 or omitted means use the selected frame. */)
1246 Lisp_Object spec
, frame
;
1251 if (valid_image_p (spec
))
1253 struct frame
*f
= check_x_frame (frame
);
1254 int id
= lookup_image (f
, spec
);
1255 struct image
*img
= IMAGE_FROM_ID (f
, id
);
1256 ext
= img
->data
.lisp_val
;
1263 /***********************************************************************
1264 Image type independent image structures
1265 ***********************************************************************/
1267 static struct image
*make_image
P_ ((Lisp_Object spec
, unsigned hash
));
1268 static void free_image
P_ ((struct frame
*f
, struct image
*img
));
1269 static int check_image_size
P_ ((struct frame
*f
, int width
, int height
));
1271 #define MAX_IMAGE_SIZE 6.0
1272 Lisp_Object Vmax_image_size
;
1274 /* Allocate and return a new image structure for image specification
1275 SPEC. SPEC has a hash value of HASH. */
1277 static struct image
*
1278 make_image (spec
, hash
)
1282 struct image
*img
= (struct image
*) xmalloc (sizeof *img
);
1283 Lisp_Object file
= image_spec_value (spec
, QCfile
, NULL
);
1285 xassert (valid_image_p (spec
));
1286 bzero (img
, sizeof *img
);
1287 img
->dependencies
= NILP (file
) ? Qnil
: list1 (file
);
1288 img
->type
= lookup_image_type (image_spec_value (spec
, QCtype
, NULL
));
1289 xassert (img
->type
!= NULL
);
1291 img
->data
.lisp_val
= Qnil
;
1292 img
->ascent
= DEFAULT_IMAGE_ASCENT
;
1294 img
->corners
[BOT_CORNER
] = -1; /* Full image */
1299 /* Free image IMG which was used on frame F, including its resources. */
1308 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1310 /* Remove IMG from the hash table of its cache. */
1312 img
->prev
->next
= img
->next
;
1314 c
->buckets
[img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
] = img
->next
;
1317 img
->next
->prev
= img
->prev
;
1319 c
->images
[img
->id
] = NULL
;
1321 /* Free resources, then free IMG. */
1322 img
->type
->free (f
, img
);
1327 /* Return 1 if the given widths and heights are valid for display;
1328 otherwise, return 0. */
1331 check_image_size (f
, width
, height
)
1338 if (width
<= 0 || height
<= 0)
1341 if (INTEGERP (Vmax_image_size
))
1342 w
= h
= XINT (Vmax_image_size
);
1343 else if (FLOATP (Vmax_image_size
))
1347 w
= FRAME_PIXEL_WIDTH (f
);
1348 h
= FRAME_PIXEL_HEIGHT (f
);
1351 w
= h
= 1024; /* Arbitrary size for unknown frame. */
1352 w
= (int) (XFLOAT_DATA (Vmax_image_size
) * w
);
1353 h
= (int) (XFLOAT_DATA (Vmax_image_size
) * h
);
1358 return (width
<= w
&& height
<= h
);
1361 /* Prepare image IMG for display on frame F. Must be called before
1362 drawing an image. */
1365 prepare_image_for_display (f
, img
)
1371 /* We're about to display IMG, so set its timestamp to `now'. */
1373 img
->timestamp
= EMACS_SECS (t
);
1375 /* If IMG doesn't have a pixmap yet, load it now, using the image
1376 type dependent loader function. */
1377 if (img
->pixmap
== NO_PIXMAP
&& !img
->load_failed_p
)
1378 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
1383 /* Value is the number of pixels for the ascent of image IMG when
1384 drawn in face FACE. */
1387 image_ascent (img
, face
, slice
)
1390 struct glyph_slice
*slice
;
1395 if (slice
->height
== img
->height
)
1396 height
= img
->height
+ img
->vmargin
;
1397 else if (slice
->y
== 0)
1398 height
= slice
->height
+ img
->vmargin
;
1400 height
= slice
->height
;
1402 if (img
->ascent
== CENTERED_IMAGE_ASCENT
)
1407 /* W32 specific version. Why?. ++kfs */
1408 ascent
= height
/ 2 - (FONT_DESCENT (face
->font
)
1409 - FONT_BASE (face
->font
)) / 2;
1411 /* This expression is arranged so that if the image can't be
1412 exactly centered, it will be moved slightly up. This is
1413 because a typical font is `top-heavy' (due to the presence
1414 uppercase letters), so the image placement should err towards
1415 being top-heavy too. It also just generally looks better. */
1416 ascent
= (height
+ FONT_BASE(face
->font
)
1417 - FONT_DESCENT(face
->font
) + 1) / 2;
1418 #endif /* HAVE_NTGUI */
1421 ascent
= height
/ 2;
1424 ascent
= (int) (height
* img
->ascent
/ 100.0);
1430 /* Image background colors. */
1432 /* Find the "best" corner color of a bitmap.
1433 On W32, XIMG is assumed to a device context with the bitmap selected. */
1435 static RGB_PIXEL_COLOR
1436 four_corners_best (ximg
, corners
, width
, height
)
1437 XImagePtr_or_DC ximg
;
1439 unsigned long width
, height
;
1441 RGB_PIXEL_COLOR corner_pixels
[4], best
;
1444 if (corners
&& corners
[BOT_CORNER
] >= 0)
1446 /* Get the colors at the corner_pixels of ximg. */
1447 corner_pixels
[0] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[TOP_CORNER
]);
1448 corner_pixels
[1] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[TOP_CORNER
]);
1449 corner_pixels
[2] = GET_PIXEL (ximg
, corners
[RIGHT_CORNER
] - 1, corners
[BOT_CORNER
] - 1);
1450 corner_pixels
[3] = GET_PIXEL (ximg
, corners
[LEFT_CORNER
], corners
[BOT_CORNER
] - 1);
1454 /* Get the colors at the corner_pixels of ximg. */
1455 corner_pixels
[0] = GET_PIXEL (ximg
, 0, 0);
1456 corner_pixels
[1] = GET_PIXEL (ximg
, width
- 1, 0);
1457 corner_pixels
[2] = GET_PIXEL (ximg
, width
- 1, height
- 1);
1458 corner_pixels
[3] = GET_PIXEL (ximg
, 0, height
- 1);
1460 /* Choose the most frequently found color as background. */
1461 for (i
= best_count
= 0; i
< 4; ++i
)
1465 for (j
= n
= 0; j
< 4; ++j
)
1466 if (corner_pixels
[i
] == corner_pixels
[j
])
1470 best
= corner_pixels
[i
], best_count
= n
;
1476 /* Portability macros */
1480 #define Destroy_Image(img_dc, prev) \
1481 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1483 #define Free_Pixmap(display, pixmap) \
1484 DeleteObject (pixmap)
1486 #elif defined (HAVE_NS)
1488 #define Destroy_Image(ximg, dummy) \
1489 ns_release_object(ximg)
1491 #define Free_Pixmap(display, pixmap) \
1492 ns_release_object(pixmap)
1496 #define Destroy_Image(ximg, dummy) \
1497 XDestroyImage (ximg)
1499 #define Free_Pixmap(display, pixmap) \
1500 XFreePixmap (display, pixmap)
1502 #endif /* !HAVE_NTGUI && !HAVE_NS */
1505 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1506 it is guessed heuristically. If non-zero, XIMG is an existing
1507 XImage object (or device context with the image selected on W32) to
1508 use for the heuristic. */
1511 image_background (img
, f
, ximg
)
1514 XImagePtr_or_DC ximg
;
1516 if (! img
->background_valid
)
1517 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1519 int free_ximg
= !ximg
;
1522 #endif /* HAVE_NTGUI */
1527 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
1528 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1530 HDC frame_dc
= get_frame_dc (f
);
1531 ximg
= CreateCompatibleDC (frame_dc
);
1532 release_frame_dc (f
, frame_dc
);
1533 prev
= SelectObject (ximg
, img
->pixmap
);
1534 #endif /* !HAVE_NTGUI */
1537 img
->background
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
1540 Destroy_Image (ximg
, prev
);
1542 img
->background_valid
= 1;
1545 return img
->background
;
1548 /* Return the `background_transparent' field of IMG. If IMG doesn't
1549 have one yet, it is guessed heuristically. If non-zero, MASK is an
1550 existing XImage object to use for the heuristic. */
1553 image_background_transparent (img
, f
, mask
)
1556 XImagePtr_or_DC mask
;
1558 if (! img
->background_transparent_valid
)
1559 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1563 int free_mask
= !mask
;
1566 #endif /* HAVE_NTGUI */
1571 mask
= XGetImage (FRAME_X_DISPLAY (f
), img
->mask
,
1572 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
1574 HDC frame_dc
= get_frame_dc (f
);
1575 mask
= CreateCompatibleDC (frame_dc
);
1576 release_frame_dc (f
, frame_dc
);
1577 prev
= SelectObject (mask
, img
->mask
);
1578 #endif /* HAVE_NTGUI */
1581 img
->background_transparent
1582 = (four_corners_best (mask
, img
->corners
, img
->width
, img
->height
) == PIX_MASK_RETAIN
);
1585 Destroy_Image (mask
, prev
);
1588 img
->background_transparent
= 0;
1590 img
->background_transparent_valid
= 1;
1593 return img
->background_transparent
;
1597 /***********************************************************************
1598 Helper functions for X image types
1599 ***********************************************************************/
1601 static void x_clear_image_1
P_ ((struct frame
*, struct image
*, int,
1603 static void x_clear_image
P_ ((struct frame
*f
, struct image
*img
));
1604 static unsigned long x_alloc_image_color
P_ ((struct frame
*f
,
1606 Lisp_Object color_name
,
1607 unsigned long dflt
));
1610 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1611 free the pixmap if any. MASK_P non-zero means clear the mask
1612 pixmap if any. COLORS_P non-zero means free colors allocated for
1613 the image, if any. */
1616 x_clear_image_1 (f
, img
, pixmap_p
, mask_p
, colors_p
)
1619 int pixmap_p
, mask_p
, colors_p
;
1621 if (pixmap_p
&& img
->pixmap
)
1623 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
1624 img
->pixmap
= NO_PIXMAP
;
1626 if (img
->background_valid
)
1627 ns_free_indexed_color(img
->background
);
1629 img
->background_valid
= 0;
1632 if (mask_p
&& img
->mask
)
1634 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1635 img
->mask
= NO_PIXMAP
;
1636 img
->background_transparent_valid
= 0;
1639 if (colors_p
&& img
->ncolors
)
1641 /* W32_TODO: color table support. */
1642 #ifdef HAVE_X_WINDOWS
1643 x_free_colors (f
, img
->colors
, img
->ncolors
);
1644 #endif /* HAVE_X_WINDOWS */
1645 xfree (img
->colors
);
1652 /* Free X resources of image IMG which is used on frame F. */
1655 x_clear_image (f
, img
)
1660 x_clear_image_1 (f
, img
, 1, 1, 1);
1665 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1666 cannot be allocated, use DFLT. Add a newly allocated color to
1667 IMG->colors, so that it can be freed again. Value is the pixel
1670 static unsigned long
1671 x_alloc_image_color (f
, img
, color_name
, dflt
)
1674 Lisp_Object color_name
;
1678 unsigned long result
;
1680 xassert (STRINGP (color_name
));
1682 if (x_defined_color (f
, SDATA (color_name
), &color
, 1))
1684 /* This isn't called frequently so we get away with simply
1685 reallocating the color vector to the needed size, here. */
1688 (unsigned long *) xrealloc (img
->colors
,
1689 img
->ncolors
* sizeof *img
->colors
);
1690 img
->colors
[img
->ncolors
- 1] = color
.pixel
;
1691 result
= color
.pixel
;
1701 /***********************************************************************
1703 ***********************************************************************/
1705 static struct image
*search_image_cache
P_ ((struct frame
*, Lisp_Object
, unsigned));
1706 static void cache_image
P_ ((struct frame
*f
, struct image
*img
));
1707 static void postprocess_image
P_ ((struct frame
*, struct image
*));
1709 /* Return a new, initialized image cache that is allocated from the
1710 heap. Call free_image_cache to free an image cache. */
1712 struct image_cache
*
1715 struct image_cache
*c
= (struct image_cache
*) xmalloc (sizeof *c
);
1718 bzero (c
, sizeof *c
);
1720 c
->images
= (struct image
**) xmalloc (c
->size
* sizeof *c
->images
);
1721 size
= IMAGE_CACHE_BUCKETS_SIZE
* sizeof *c
->buckets
;
1722 c
->buckets
= (struct image
**) xmalloc (size
);
1723 bzero (c
->buckets
, size
);
1728 /* Find an image matching SPEC in the cache, and return it. If no
1729 image is found, return NULL. */
1730 static struct image
*
1731 search_image_cache (f
, spec
, hash
)
1737 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1738 int i
= hash
% IMAGE_CACHE_BUCKETS_SIZE
;
1740 if (!c
) return NULL
;
1742 /* If the image spec does not specify a background color, the cached
1743 image must have the same background color as the current frame.
1744 The foreground color must also match, for the sake of monochrome
1747 In fact, we could ignore the foreground color matching condition
1748 for color images, or if the image spec specifies :foreground;
1749 similarly we could ignore the background color matching condition
1750 for formats that don't use transparency (such as jpeg), or if the
1751 image spec specifies :background. However, the extra memory
1752 usage is probably negligible in practice, so we don't bother. */
1754 for (img
= c
->buckets
[i
]; img
; img
= img
->next
)
1755 if (img
->hash
== hash
1756 && !NILP (Fequal (img
->spec
, spec
))
1757 && img
->frame_foreground
== FRAME_FOREGROUND_PIXEL (f
)
1758 && img
->frame_background
== FRAME_BACKGROUND_PIXEL (f
))
1764 /* Search frame F for an image with spec SPEC, and free it. */
1767 uncache_image (f
, spec
)
1771 struct image
*img
= search_image_cache (f
, spec
, sxhash (spec
, 0));
1773 free_image (f
, img
);
1777 /* Free image cache of frame F. Be aware that X frames share images
1781 free_image_cache (f
)
1784 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1789 /* Cache should not be referenced by any frame when freed. */
1790 xassert (c
->refcount
== 0);
1792 for (i
= 0; i
< c
->used
; ++i
)
1793 free_image (f
, c
->images
[i
]);
1797 FRAME_IMAGE_CACHE (f
) = NULL
;
1802 /* Clear image cache of frame F. FILTER=t means free all images.
1803 FILTER=nil means clear only images that haven't been
1804 displayed for some time.
1805 Else, only free the images which have FILTER in their `dependencies'.
1806 Should be called from time to time to reduce the number of loaded images.
1807 If image-cache-eviction-delay is non-nil, this frees images in the cache
1808 which weren't displayed for at least that many seconds. */
1811 clear_image_cache (struct frame
*f
, Lisp_Object filter
)
1813 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
1815 if (c
&& (!NILP (filter
) || INTEGERP (Vimage_cache_eviction_delay
)))
1822 old
= EMACS_SECS (t
) - XFASTINT (Vimage_cache_eviction_delay
);
1824 /* Block input so that we won't be interrupted by a SIGIO
1825 while being in an inconsistent state. */
1828 for (i
= nfreed
= 0; i
< c
->used
; ++i
)
1830 struct image
*img
= c
->images
[i
];
1832 && (NILP (filter
) ? img
->timestamp
< old
1834 || !NILP (Fmember (filter
, img
->dependencies
)))))
1836 free_image (f
, img
);
1841 /* We may be clearing the image cache because, for example,
1842 Emacs was iconified for a longer period of time. In that
1843 case, current matrices may still contain references to
1844 images freed above. So, clear these matrices. */
1847 Lisp_Object tail
, frame
;
1849 FOR_EACH_FRAME (tail
, frame
)
1851 struct frame
*f
= XFRAME (frame
);
1852 if (FRAME_IMAGE_CACHE (f
) == c
)
1853 clear_current_matrices (f
);
1856 ++windows_or_buffers_changed
;
1864 clear_image_caches (Lisp_Object filter
)
1866 /* FIXME: We want to do
1867 * struct terminal *t;
1868 * for (t = terminal_list; t; t = t->next_terminal)
1869 * clear_image_cache (t, filter); */
1870 Lisp_Object tail
, frame
;
1871 FOR_EACH_FRAME (tail
, frame
)
1872 if (FRAME_WINDOW_P (XFRAME (frame
)))
1873 clear_image_cache (XFRAME (frame
), filter
);
1876 DEFUN ("clear-image-cache", Fclear_image_cache
, Sclear_image_cache
,
1878 doc
: /* Clear the image cache.
1879 FILTER nil or a frame means clear all images in the selected frame.
1880 FILTER t means clear the image caches of all frames.
1881 Anything else, means only clear those images which refer to FILTER,
1882 which is then usually a filename. */)
1886 if (!(EQ (filter
, Qnil
) || FRAMEP (filter
)))
1887 clear_image_caches (filter
);
1889 clear_image_cache (check_x_frame (filter
), Qt
);
1895 DEFUN ("image-refresh", Fimage_refresh
, Simage_refresh
,
1897 doc
: /* Refresh the image with specification SPEC on frame FRAME.
1898 If SPEC specifies an image file, the displayed image is updated with
1899 the current contents of that file.
1900 FRAME nil or omitted means use the selected frame.
1901 FRAME t means refresh the image on all frames. */)
1903 Lisp_Object spec
, frame
;
1905 if (!valid_image_p (spec
))
1906 error ("Invalid image specification");
1911 FOR_EACH_FRAME (tail
, frame
)
1913 struct frame
*f
= XFRAME (frame
);
1914 if (FRAME_WINDOW_P (f
))
1915 uncache_image (f
, spec
);
1919 uncache_image (check_x_frame (frame
), spec
);
1925 /* Compute masks and transform image IMG on frame F, as specified
1926 by the image's specification, */
1929 postprocess_image (f
, img
)
1933 /* Manipulation of the image's mask. */
1936 Lisp_Object conversion
, spec
;
1941 /* `:heuristic-mask t'
1943 means build a mask heuristically.
1944 `:heuristic-mask (R G B)'
1945 `:mask (heuristic (R G B))'
1946 means build a mask from color (R G B) in the
1949 means remove a mask, if any. */
1951 mask
= image_spec_value (spec
, QCheuristic_mask
, NULL
);
1953 x_build_heuristic_mask (f
, img
, mask
);
1958 mask
= image_spec_value (spec
, QCmask
, &found_p
);
1960 if (EQ (mask
, Qheuristic
))
1961 x_build_heuristic_mask (f
, img
, Qt
);
1962 else if (CONSP (mask
)
1963 && EQ (XCAR (mask
), Qheuristic
))
1965 if (CONSP (XCDR (mask
)))
1966 x_build_heuristic_mask (f
, img
, XCAR (XCDR (mask
)));
1968 x_build_heuristic_mask (f
, img
, XCDR (mask
));
1970 else if (NILP (mask
) && found_p
&& img
->mask
)
1972 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
1973 img
->mask
= NO_PIXMAP
;
1978 /* Should we apply an image transformation algorithm? */
1979 conversion
= image_spec_value (spec
, QCconversion
, NULL
);
1980 if (EQ (conversion
, Qdisabled
))
1981 x_disable_image (f
, img
);
1982 else if (EQ (conversion
, Qlaplace
))
1984 else if (EQ (conversion
, Qemboss
))
1986 else if (CONSP (conversion
)
1987 && EQ (XCAR (conversion
), Qedge_detection
))
1990 tem
= XCDR (conversion
);
1992 x_edge_detection (f
, img
,
1993 Fplist_get (tem
, QCmatrix
),
1994 Fplist_get (tem
, QCcolor_adjustment
));
2000 /* Return the id of image with Lisp specification SPEC on frame F.
2001 SPEC must be a valid Lisp image specification (see valid_image_p). */
2004 lookup_image (f
, spec
)
2008 struct image_cache
*c
;
2011 struct gcpro gcpro1
;
2014 /* F must be a window-system frame, and SPEC must be a valid image
2016 xassert (FRAME_WINDOW_P (f
));
2017 xassert (valid_image_p (spec
));
2019 c
= FRAME_IMAGE_CACHE (f
);
2023 /* Look up SPEC in the hash table of the image cache. */
2024 hash
= sxhash (spec
, 0);
2025 img
= search_image_cache (f
, spec
, hash
);
2026 if (img
&& img
->load_failed_p
)
2028 free_image (f
, img
);
2032 /* If not found, create a new image and cache it. */
2035 extern Lisp_Object Qpostscript
;
2038 img
= make_image (spec
, hash
);
2039 cache_image (f
, img
);
2040 img
->load_failed_p
= img
->type
->load (f
, img
) == 0;
2041 img
->frame_foreground
= FRAME_FOREGROUND_PIXEL (f
);
2042 img
->frame_background
= FRAME_BACKGROUND_PIXEL (f
);
2044 /* If we can't load the image, and we don't have a width and
2045 height, use some arbitrary width and height so that we can
2046 draw a rectangle for it. */
2047 if (img
->load_failed_p
)
2051 value
= image_spec_value (spec
, QCwidth
, NULL
);
2052 img
->width
= (INTEGERP (value
)
2053 ? XFASTINT (value
) : DEFAULT_IMAGE_WIDTH
);
2054 value
= image_spec_value (spec
, QCheight
, NULL
);
2055 img
->height
= (INTEGERP (value
)
2056 ? XFASTINT (value
) : DEFAULT_IMAGE_HEIGHT
);
2060 /* Handle image type independent image attributes
2061 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2062 `:background COLOR'. */
2063 Lisp_Object ascent
, margin
, relief
, bg
;
2065 ascent
= image_spec_value (spec
, QCascent
, NULL
);
2066 if (INTEGERP (ascent
))
2067 img
->ascent
= XFASTINT (ascent
);
2068 else if (EQ (ascent
, Qcenter
))
2069 img
->ascent
= CENTERED_IMAGE_ASCENT
;
2071 margin
= image_spec_value (spec
, QCmargin
, NULL
);
2072 if (INTEGERP (margin
) && XINT (margin
) >= 0)
2073 img
->vmargin
= img
->hmargin
= XFASTINT (margin
);
2074 else if (CONSP (margin
) && INTEGERP (XCAR (margin
))
2075 && INTEGERP (XCDR (margin
)))
2077 if (XINT (XCAR (margin
)) > 0)
2078 img
->hmargin
= XFASTINT (XCAR (margin
));
2079 if (XINT (XCDR (margin
)) > 0)
2080 img
->vmargin
= XFASTINT (XCDR (margin
));
2083 relief
= image_spec_value (spec
, QCrelief
, NULL
);
2084 if (INTEGERP (relief
))
2086 img
->relief
= XINT (relief
);
2087 img
->hmargin
+= eabs (img
->relief
);
2088 img
->vmargin
+= eabs (img
->relief
);
2091 if (! img
->background_valid
)
2093 bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
2097 = x_alloc_image_color (f
, img
, bg
,
2098 FRAME_BACKGROUND_PIXEL (f
));
2099 img
->background_valid
= 1;
2103 /* Do image transformations and compute masks, unless we
2104 don't have the image yet. */
2105 if (!EQ (*img
->type
->type
, Qpostscript
))
2106 postprocess_image (f
, img
);
2112 /* We're using IMG, so set its timestamp to `now'. */
2113 EMACS_GET_TIME (now
);
2114 img
->timestamp
= EMACS_SECS (now
);
2118 /* Value is the image id. */
2123 /* Cache image IMG in the image cache of frame F. */
2126 cache_image (f
, img
)
2130 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
2133 /* Find a free slot in c->images. */
2134 for (i
= 0; i
< c
->used
; ++i
)
2135 if (c
->images
[i
] == NULL
)
2138 /* If no free slot found, maybe enlarge c->images. */
2139 if (i
== c
->used
&& c
->used
== c
->size
)
2142 c
->images
= (struct image
**) xrealloc (c
->images
,
2143 c
->size
* sizeof *c
->images
);
2146 /* Add IMG to c->images, and assign IMG an id. */
2152 /* Add IMG to the cache's hash table. */
2153 i
= img
->hash
% IMAGE_CACHE_BUCKETS_SIZE
;
2154 img
->next
= c
->buckets
[i
];
2156 img
->next
->prev
= img
;
2158 c
->buckets
[i
] = img
;
2162 /* Call FN on every image in the image cache of frame F. Used to mark
2163 Lisp Objects in the image cache. */
2165 /* Mark Lisp objects in image IMG. */
2171 mark_object (img
->spec
);
2172 mark_object (img
->dependencies
);
2174 if (!NILP (img
->data
.lisp_val
))
2175 mark_object (img
->data
.lisp_val
);
2180 mark_image_cache (struct image_cache
*c
)
2185 for (i
= 0; i
< c
->used
; ++i
)
2187 mark_image (c
->images
[i
]);
2193 /***********************************************************************
2194 X / NS / W32 support code
2195 ***********************************************************************/
2199 /* Macro for defining functions that will be loaded from image DLLs. */
2200 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2202 /* Macro for loading those image functions from the library. */
2203 #define LOAD_IMGLIB_FN(lib,func) { \
2204 fn_##func = (void *) GetProcAddress (lib, #func); \
2205 if (!fn_##func) return 0; \
2208 /* Load a DLL implementing an image type.
2209 The `image-library-alist' variable associates a symbol,
2210 identifying an image type, to a list of possible filenames.
2211 The function returns NULL if no library could be loaded for
2212 the given image type, or if the library was previously loaded;
2213 else the handle of the DLL. */
2215 w32_delayed_load (Lisp_Object libraries
, Lisp_Object type
)
2217 HMODULE library
= NULL
;
2219 if (CONSP (libraries
) && NILP (Fassq (type
, Vimage_type_cache
)))
2221 Lisp_Object dlls
= Fassq (type
, libraries
);
2224 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
2226 CHECK_STRING_CAR (dlls
);
2227 if (library
= LoadLibrary (SDATA (XCAR (dlls
))))
2235 #endif /* HAVE_NTGUI */
2237 static int x_create_x_image_and_pixmap
P_ ((struct frame
*, int, int, int,
2238 XImagePtr
*, Pixmap
*));
2239 static void x_destroy_x_image
P_ ((XImagePtr
));
2240 static void x_put_x_image
P_ ((struct frame
*, XImagePtr
, Pixmap
, int, int));
2243 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2244 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2245 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2246 via xmalloc. Print error messages via image_error if an error
2247 occurs. Value is non-zero if successful.
2249 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2250 should indicate the bit depth of the image. */
2253 x_create_x_image_and_pixmap (f
, width
, height
, depth
, ximg
, pixmap
)
2255 int width
, height
, depth
;
2259 #ifdef HAVE_X_WINDOWS
2260 Display
*display
= FRAME_X_DISPLAY (f
);
2261 Window window
= FRAME_X_WINDOW (f
);
2262 Screen
*screen
= FRAME_X_SCREEN (f
);
2264 xassert (interrupt_input_blocked
);
2267 depth
= DefaultDepthOfScreen (screen
);
2268 *ximg
= XCreateImage (display
, DefaultVisualOfScreen (screen
),
2269 depth
, ZPixmap
, 0, NULL
, width
, height
,
2270 depth
> 16 ? 32 : depth
> 8 ? 16 : 8, 0);
2273 image_error ("Unable to allocate X image", Qnil
, Qnil
);
2277 /* Allocate image raster. */
2278 (*ximg
)->data
= (char *) xmalloc ((*ximg
)->bytes_per_line
* height
);
2280 /* Allocate a pixmap of the same size. */
2281 *pixmap
= XCreatePixmap (display
, window
, width
, height
, depth
);
2282 if (*pixmap
== NO_PIXMAP
)
2284 x_destroy_x_image (*ximg
);
2286 image_error ("Unable to create X pixmap", Qnil
, Qnil
);
2291 #endif /* HAVE_X_WINDOWS */
2295 BITMAPINFOHEADER
*header
;
2297 int scanline_width_bits
;
2299 int palette_colors
= 0;
2304 if (depth
!= 1 && depth
!= 4 && depth
!= 8
2305 && depth
!= 16 && depth
!= 24 && depth
!= 32)
2307 image_error ("Invalid image bit depth specified", Qnil
, Qnil
);
2311 scanline_width_bits
= width
* depth
;
2312 remainder
= scanline_width_bits
% 32;
2315 scanline_width_bits
+= 32 - remainder
;
2317 /* Bitmaps with a depth less than 16 need a palette. */
2318 /* BITMAPINFO structure already contains the first RGBQUAD. */
2320 palette_colors
= 1 << depth
- 1;
2322 *ximg
= xmalloc (sizeof (XImage
) + palette_colors
* sizeof (RGBQUAD
));
2325 image_error ("Unable to allocate memory for XImage", Qnil
, Qnil
);
2329 header
= &((*ximg
)->info
.bmiHeader
);
2330 bzero (&((*ximg
)->info
), sizeof (BITMAPINFO
));
2331 header
->biSize
= sizeof (*header
);
2332 header
->biWidth
= width
;
2333 header
->biHeight
= -height
; /* negative indicates a top-down bitmap. */
2334 header
->biPlanes
= 1;
2335 header
->biBitCount
= depth
;
2336 header
->biCompression
= BI_RGB
;
2337 header
->biClrUsed
= palette_colors
;
2339 /* TODO: fill in palette. */
2342 (*ximg
)->info
.bmiColors
[0].rgbBlue
= 0;
2343 (*ximg
)->info
.bmiColors
[0].rgbGreen
= 0;
2344 (*ximg
)->info
.bmiColors
[0].rgbRed
= 0;
2345 (*ximg
)->info
.bmiColors
[0].rgbReserved
= 0;
2346 (*ximg
)->info
.bmiColors
[1].rgbBlue
= 255;
2347 (*ximg
)->info
.bmiColors
[1].rgbGreen
= 255;
2348 (*ximg
)->info
.bmiColors
[1].rgbRed
= 255;
2349 (*ximg
)->info
.bmiColors
[1].rgbReserved
= 0;
2352 hdc
= get_frame_dc (f
);
2354 /* Create a DIBSection and raster array for the bitmap,
2355 and store its handle in *pixmap. */
2356 *pixmap
= CreateDIBSection (hdc
, &((*ximg
)->info
),
2357 (depth
< 16) ? DIB_PAL_COLORS
: DIB_RGB_COLORS
,
2358 /* casting avoids a GCC warning */
2359 (void **)&((*ximg
)->data
), NULL
, 0);
2361 /* Realize display palette and garbage all frames. */
2362 release_frame_dc (f
, hdc
);
2364 if (*pixmap
== NULL
)
2366 DWORD err
= GetLastError ();
2367 Lisp_Object errcode
;
2368 /* All system errors are < 10000, so the following is safe. */
2369 XSETINT (errcode
, (int) err
);
2370 image_error ("Unable to create bitmap, error code %d", errcode
, Qnil
);
2371 x_destroy_x_image (*ximg
);
2377 #endif /* HAVE_NTGUI */
2380 *pixmap
= ns_image_for_XPM(width
, height
, depth
);
2384 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil
, Qnil
);
2393 /* Destroy XImage XIMG. Free XIMG->data. */
2396 x_destroy_x_image (ximg
)
2399 xassert (interrupt_input_blocked
);
2402 #ifdef HAVE_X_WINDOWS
2405 XDestroyImage (ximg
);
2406 #endif /* HAVE_X_WINDOWS */
2408 /* Data will be freed by DestroyObject. */
2411 #endif /* HAVE_NTGUI */
2413 ns_release_object(ximg
);
2414 #endif /* HAVE_NS */
2419 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2420 are width and height of both the image and pixmap. */
2423 x_put_x_image (f
, ximg
, pixmap
, width
, height
)
2429 #ifdef HAVE_X_WINDOWS
2432 xassert (interrupt_input_blocked
);
2433 gc
= XCreateGC (FRAME_X_DISPLAY (f
), pixmap
, 0, NULL
);
2434 XPutImage (FRAME_X_DISPLAY (f
), pixmap
, gc
, ximg
, 0, 0, 0, 0, width
, height
);
2435 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
2436 #endif /* HAVE_X_WINDOWS */
2439 #if 0 /* I don't think this is necessary looking at where it is used. */
2440 HDC hdc
= get_frame_dc (f
);
2441 SetDIBits (hdc
, pixmap
, 0, height
, ximg
->data
, &(ximg
->info
), DIB_RGB_COLORS
);
2442 release_frame_dc (f
, hdc
);
2444 #endif /* HAVE_NTGUI */
2447 xassert (ximg
== pixmap
);
2448 ns_retain_object(ximg
);
2453 /***********************************************************************
2455 ***********************************************************************/
2457 static unsigned char *slurp_file
P_ ((char *, int *));
2460 /* Find image file FILE. Look in data-directory/images, then
2461 x-bitmap-file-path. Value is the encoded full name of the file
2462 found, or nil if not found. */
2465 x_find_image_file (file
)
2468 Lisp_Object file_found
, search_path
;
2469 struct gcpro gcpro1
, gcpro2
;
2473 /* TODO I think this should use something like image-load-path
2474 instead. Unfortunately, that can contain non-string elements. */
2475 search_path
= Fcons (Fexpand_file_name (build_string ("images"),
2477 Vx_bitmap_file_path
);
2478 GCPRO2 (file_found
, search_path
);
2480 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2481 fd
= openp (search_path
, file
, Qnil
, &file_found
, Qnil
);
2487 file_found
= ENCODE_FILE (file_found
);
2496 /* Read FILE into memory. Value is a pointer to a buffer allocated
2497 with xmalloc holding FILE's contents. Value is null if an error
2498 occurred. *SIZE is set to the size of the file. */
2500 static unsigned char *
2501 slurp_file (file
, size
)
2506 unsigned char *buf
= NULL
;
2509 if (stat (file
, &st
) == 0
2510 && (fp
= fopen (file
, "rb")) != NULL
2511 && (buf
= (unsigned char *) xmalloc (st
.st_size
),
2512 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
2533 /***********************************************************************
2535 ***********************************************************************/
2537 static int xbm_scan
P_ ((unsigned char **, unsigned char *, char *, int *));
2538 static int xbm_load
P_ ((struct frame
*f
, struct image
*img
));
2539 static int xbm_load_image
P_ ((struct frame
*f
, struct image
*img
,
2540 unsigned char *, unsigned char *));
2541 static int xbm_image_p
P_ ((Lisp_Object object
));
2542 static int xbm_read_bitmap_data
P_ ((struct frame
*f
,
2543 unsigned char *, unsigned char *,
2544 int *, int *, unsigned char **));
2545 static int xbm_file_p
P_ ((Lisp_Object
));
2548 /* Indices of image specification fields in xbm_format, below. */
2550 enum xbm_keyword_index
2568 /* Vector of image_keyword structures describing the format
2569 of valid XBM image specifications. */
2571 static struct image_keyword xbm_format
[XBM_LAST
] =
2573 {":type", IMAGE_SYMBOL_VALUE
, 1},
2574 {":file", IMAGE_STRING_VALUE
, 0},
2575 {":width", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2576 {":height", IMAGE_POSITIVE_INTEGER_VALUE
, 0},
2577 {":data", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2578 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
2579 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
2580 {":ascent", IMAGE_ASCENT_VALUE
, 0},
2581 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
2582 {":relief", IMAGE_INTEGER_VALUE
, 0},
2583 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2584 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
2585 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0}
2588 /* Structure describing the image type XBM. */
2590 static struct image_type xbm_type
=
2599 /* Tokens returned from xbm_scan. */
2608 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2609 A valid specification is a list starting with the symbol `image'
2610 The rest of the list is a property list which must contain an
2613 If the specification specifies a file to load, it must contain
2614 an entry `:file FILENAME' where FILENAME is a string.
2616 If the specification is for a bitmap loaded from memory it must
2617 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2618 WIDTH and HEIGHT are integers > 0. DATA may be:
2620 1. a string large enough to hold the bitmap data, i.e. it must
2621 have a size >= (WIDTH + 7) / 8 * HEIGHT
2623 2. a bool-vector of size >= WIDTH * HEIGHT
2625 3. a vector of strings or bool-vectors, one for each line of the
2628 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2629 may not be specified in this case because they are defined in the
2632 Both the file and data forms may contain the additional entries
2633 `:background COLOR' and `:foreground COLOR'. If not present,
2634 foreground and background of the frame on which the image is
2635 displayed is used. */
2638 xbm_image_p (object
)
2641 struct image_keyword kw
[XBM_LAST
];
2643 bcopy (xbm_format
, kw
, sizeof kw
);
2644 if (!parse_image_spec (object
, kw
, XBM_LAST
, Qxbm
))
2647 xassert (EQ (kw
[XBM_TYPE
].value
, Qxbm
));
2649 if (kw
[XBM_FILE
].count
)
2651 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_DATA
].count
)
2654 else if (kw
[XBM_DATA
].count
&& xbm_file_p (kw
[XBM_DATA
].value
))
2656 /* In-memory XBM file. */
2657 if (kw
[XBM_WIDTH
].count
|| kw
[XBM_HEIGHT
].count
|| kw
[XBM_FILE
].count
)
2665 /* Entries for `:width', `:height' and `:data' must be present. */
2666 if (!kw
[XBM_WIDTH
].count
2667 || !kw
[XBM_HEIGHT
].count
2668 || !kw
[XBM_DATA
].count
)
2671 data
= kw
[XBM_DATA
].value
;
2672 width
= XFASTINT (kw
[XBM_WIDTH
].value
);
2673 height
= XFASTINT (kw
[XBM_HEIGHT
].value
);
2675 /* Check type of data, and width and height against contents of
2681 /* Number of elements of the vector must be >= height. */
2682 if (XVECTOR (data
)->size
< height
)
2685 /* Each string or bool-vector in data must be large enough
2686 for one line of the image. */
2687 for (i
= 0; i
< height
; ++i
)
2689 Lisp_Object elt
= XVECTOR (data
)->contents
[i
];
2694 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
)
2697 else if (BOOL_VECTOR_P (elt
))
2699 if (XBOOL_VECTOR (elt
)->size
< width
)
2706 else if (STRINGP (data
))
2709 < (width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
* height
)
2712 else if (BOOL_VECTOR_P (data
))
2714 if (XBOOL_VECTOR (data
)->size
< width
* height
)
2725 /* Scan a bitmap file. FP is the stream to read from. Value is
2726 either an enumerator from enum xbm_token, or a character for a
2727 single-character token, or 0 at end of file. If scanning an
2728 identifier, store the lexeme of the identifier in SVAL. If
2729 scanning a number, store its value in *IVAL. */
2732 xbm_scan (s
, end
, sval
, ival
)
2733 unsigned char **s
, *end
;
2741 /* Skip white space. */
2742 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
2747 else if (isdigit (c
))
2749 int value
= 0, digit
;
2751 if (c
== '0' && *s
< end
)
2754 if (c
== 'x' || c
== 'X')
2761 else if (c
>= 'a' && c
<= 'f')
2762 digit
= c
- 'a' + 10;
2763 else if (c
>= 'A' && c
<= 'F')
2764 digit
= c
- 'A' + 10;
2767 value
= 16 * value
+ digit
;
2770 else if (isdigit (c
))
2774 && (c
= *(*s
)++, isdigit (c
)))
2775 value
= 8 * value
+ c
- '0';
2782 && (c
= *(*s
)++, isdigit (c
)))
2783 value
= 10 * value
+ c
- '0';
2791 else if (isalpha (c
) || c
== '_')
2795 && (c
= *(*s
)++, (isalnum (c
) || c
== '_')))
2802 else if (c
== '/' && **s
== '*')
2804 /* C-style comment. */
2806 while (**s
&& (**s
!= '*' || *(*s
+ 1) != '/'))
2820 /* Create a Windows bitmap from X bitmap data. */
2822 w32_create_pixmap_from_bitmap_data (int width
, int height
, char *data
)
2824 static unsigned char swap_nibble
[16]
2825 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2826 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2827 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2828 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2830 unsigned char *bits
, *p
;
2833 w1
= (width
+ 7) / 8; /* nb of 8bits elt in X bitmap */
2834 w2
= ((width
+ 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2835 bits
= (unsigned char *) alloca (height
* w2
);
2836 bzero (bits
, height
* w2
);
2837 for (i
= 0; i
< height
; i
++)
2840 for (j
= 0; j
< w1
; j
++)
2842 /* Bitswap XBM bytes to match how Windows does things. */
2843 unsigned char c
= *data
++;
2844 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
2845 | (swap_nibble
[(c
>>4) & 0xf]));
2848 bmp
= CreateBitmap (width
, height
, 1, 1, (char *) bits
);
2854 convert_mono_to_color_image (f
, img
, foreground
, background
)
2857 COLORREF foreground
, background
;
2859 HDC hdc
, old_img_dc
, new_img_dc
;
2860 HGDIOBJ old_prev
, new_prev
;
2863 hdc
= get_frame_dc (f
);
2864 old_img_dc
= CreateCompatibleDC (hdc
);
2865 new_img_dc
= CreateCompatibleDC (hdc
);
2866 new_pixmap
= CreateCompatibleBitmap (hdc
, img
->width
, img
->height
);
2867 release_frame_dc (f
, hdc
);
2868 old_prev
= SelectObject (old_img_dc
, img
->pixmap
);
2869 new_prev
= SelectObject (new_img_dc
, new_pixmap
);
2870 /* Windows convention for mono bitmaps is black = background,
2871 white = foreground. */
2872 SetTextColor (new_img_dc
, background
);
2873 SetBkColor (new_img_dc
, foreground
);
2875 BitBlt (new_img_dc
, 0, 0, img
->width
, img
->height
, old_img_dc
,
2878 SelectObject (old_img_dc
, old_prev
);
2879 SelectObject (new_img_dc
, new_prev
);
2880 DeleteDC (old_img_dc
);
2881 DeleteDC (new_img_dc
);
2882 DeleteObject (img
->pixmap
);
2883 if (new_pixmap
== 0)
2884 fprintf (stderr
, "Failed to convert image to color.\n");
2886 img
->pixmap
= new_pixmap
;
2889 #define XBM_BIT_SHUFFLE(b) (~(b))
2893 #define XBM_BIT_SHUFFLE(b) (b)
2895 #endif /* HAVE_NTGUI */
2899 Create_Pixmap_From_Bitmap_Data (f
, img
, data
, fg
, bg
, non_default_colors
)
2903 RGB_PIXEL_COLOR fg
, bg
;
2904 int non_default_colors
;
2908 = w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
, data
);
2910 /* If colors were specified, transfer the bitmap to a color one. */
2911 if (non_default_colors
)
2912 convert_mono_to_color_image (f
, img
, fg
, bg
);
2914 #elif defined (HAVE_NS)
2915 img
->pixmap
= ns_image_from_XBM(data
, img
->width
, img
->height
);
2919 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f
),
2922 img
->width
, img
->height
,
2924 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
2925 #endif /* !HAVE_NTGUI && !HAVE_NS */
2930 /* Replacement for XReadBitmapFileData which isn't available under old
2931 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2932 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2933 the image. Return in *DATA the bitmap data allocated with xmalloc.
2934 Value is non-zero if successful. DATA null means just test if
2935 CONTENTS looks like an in-memory XBM file. */
2938 xbm_read_bitmap_data (f
, contents
, end
, width
, height
, data
)
2940 unsigned char *contents
, *end
;
2941 int *width
, *height
;
2942 unsigned char **data
;
2944 unsigned char *s
= contents
;
2945 char buffer
[BUFSIZ
];
2948 int bytes_per_line
, i
, nbytes
;
2954 LA1 = xbm_scan (&s, end, buffer, &value)
2956 #define expect(TOKEN) \
2957 if (LA1 != (TOKEN)) \
2962 #define expect_ident(IDENT) \
2963 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2968 *width
= *height
= -1;
2971 LA1
= xbm_scan (&s
, end
, buffer
, &value
);
2973 /* Parse defines for width, height and hot-spots. */
2977 expect_ident ("define");
2978 expect (XBM_TK_IDENT
);
2980 if (LA1
== XBM_TK_NUMBER
)
2982 char *p
= strrchr (buffer
, '_');
2983 p
= p
? p
+ 1 : buffer
;
2984 if (strcmp (p
, "width") == 0)
2986 else if (strcmp (p
, "height") == 0)
2989 expect (XBM_TK_NUMBER
);
2992 if (!check_image_size (f
, *width
, *height
))
2994 else if (data
== NULL
)
2997 /* Parse bits. Must start with `static'. */
2998 expect_ident ("static");
2999 if (LA1
== XBM_TK_IDENT
)
3001 if (strcmp (buffer
, "unsigned") == 0)
3004 expect_ident ("char");
3006 else if (strcmp (buffer
, "short") == 0)
3010 if (*width
% 16 && *width
% 16 < 9)
3013 else if (strcmp (buffer
, "char") == 0)
3021 expect (XBM_TK_IDENT
);
3027 bytes_per_line
= (*width
+ 7) / 8 + padding_p
;
3028 nbytes
= bytes_per_line
* *height
;
3029 p
= *data
= (unsigned char *) xmalloc (nbytes
);
3033 for (i
= 0; i
< nbytes
; i
+= 2)
3036 expect (XBM_TK_NUMBER
);
3038 *p
++ = XBM_BIT_SHUFFLE (val
);
3039 if (!padding_p
|| ((i
+ 2) % bytes_per_line
))
3040 *p
++ = XBM_BIT_SHUFFLE (value
>> 8);
3042 if (LA1
== ',' || LA1
== '}')
3050 for (i
= 0; i
< nbytes
; ++i
)
3053 expect (XBM_TK_NUMBER
);
3055 *p
++ = XBM_BIT_SHUFFLE (val
);
3057 if (LA1
== ',' || LA1
== '}')
3082 /* Load XBM image IMG which will be displayed on frame F from buffer
3083 CONTENTS. END is the end of the buffer. Value is non-zero if
3087 xbm_load_image (f
, img
, contents
, end
)
3090 unsigned char *contents
, *end
;
3093 unsigned char *data
;
3096 rc
= xbm_read_bitmap_data (f
, contents
, end
, &img
->width
, &img
->height
, &data
);
3099 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3100 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3101 int non_default_colors
= 0;
3104 xassert (img
->width
> 0 && img
->height
> 0);
3106 /* Get foreground and background colors, maybe allocate colors. */
3107 value
= image_spec_value (img
->spec
, QCforeground
, NULL
);
3110 foreground
= x_alloc_image_color (f
, img
, value
, foreground
);
3111 non_default_colors
= 1;
3113 value
= image_spec_value (img
->spec
, QCbackground
, NULL
);
3116 background
= x_alloc_image_color (f
, img
, value
, background
);
3117 img
->background
= background
;
3118 img
->background_valid
= 1;
3119 non_default_colors
= 1;
3122 Create_Pixmap_From_Bitmap_Data (f
, img
, data
,
3123 foreground
, background
,
3124 non_default_colors
);
3127 if (img
->pixmap
== NO_PIXMAP
)
3129 x_clear_image (f
, img
);
3130 image_error ("Unable to create X pixmap for `%s'", img
->spec
, Qnil
);
3136 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3142 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3149 return (STRINGP (data
)
3150 && xbm_read_bitmap_data (NULL
, SDATA (data
),
3157 /* Fill image IMG which is used on frame F with pixmap data. Value is
3158 non-zero if successful. */
3166 Lisp_Object file_name
;
3168 xassert (xbm_image_p (img
->spec
));
3170 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3171 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
3172 if (STRINGP (file_name
))
3175 unsigned char *contents
;
3177 struct gcpro gcpro1
;
3179 file
= x_find_image_file (file_name
);
3181 if (!STRINGP (file
))
3183 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
3188 contents
= slurp_file (SDATA (file
), &size
);
3189 if (contents
== NULL
)
3191 image_error ("Error loading XBM image `%s'", img
->spec
, Qnil
);
3196 success_p
= xbm_load_image (f
, img
, contents
, contents
+ size
);
3201 struct image_keyword fmt
[XBM_LAST
];
3203 unsigned long foreground
= FRAME_FOREGROUND_PIXEL (f
);
3204 unsigned long background
= FRAME_BACKGROUND_PIXEL (f
);
3205 int non_default_colors
= 0;
3208 int in_memory_file_p
= 0;
3210 /* See if data looks like an in-memory XBM file. */
3211 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
3212 in_memory_file_p
= xbm_file_p (data
);
3214 /* Parse the image specification. */
3215 bcopy (xbm_format
, fmt
, sizeof fmt
);
3216 parsed_p
= parse_image_spec (img
->spec
, fmt
, XBM_LAST
, Qxbm
);
3219 /* Get specified width, and height. */
3220 if (!in_memory_file_p
)
3222 img
->width
= XFASTINT (fmt
[XBM_WIDTH
].value
);
3223 img
->height
= XFASTINT (fmt
[XBM_HEIGHT
].value
);
3224 xassert (img
->width
> 0 && img
->height
> 0);
3227 /* Get foreground and background colors, maybe allocate colors. */
3228 if (fmt
[XBM_FOREGROUND
].count
3229 && STRINGP (fmt
[XBM_FOREGROUND
].value
))
3231 foreground
= x_alloc_image_color (f
, img
, fmt
[XBM_FOREGROUND
].value
,
3233 non_default_colors
= 1;
3236 if (fmt
[XBM_BACKGROUND
].count
3237 && STRINGP (fmt
[XBM_BACKGROUND
].value
))
3239 background
= x_alloc_image_color (f
, img
, fmt
[XBM_BACKGROUND
].value
,
3241 non_default_colors
= 1;
3244 if (in_memory_file_p
)
3245 success_p
= xbm_load_image (f
, img
, SDATA (data
),
3254 int nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
;
3256 p
= bits
= (char *) alloca (nbytes
* img
->height
);
3257 for (i
= 0; i
< img
->height
; ++i
, p
+= nbytes
)
3259 Lisp_Object line
= XVECTOR (data
)->contents
[i
];
3261 bcopy (SDATA (line
), p
, nbytes
);
3263 bcopy (XBOOL_VECTOR (line
)->data
, p
, nbytes
);
3266 else if (STRINGP (data
))
3267 bits
= SDATA (data
);
3269 bits
= XBOOL_VECTOR (data
)->data
;
3275 /* Windows mono bitmaps are reversed compared with X. */
3276 invertedBits
= bits
;
3277 nbytes
= (img
->width
+ BITS_PER_CHAR
- 1) / BITS_PER_CHAR
3279 bits
= (char *) alloca(nbytes
);
3280 for (i
= 0; i
< nbytes
; i
++)
3281 bits
[i
] = XBM_BIT_SHUFFLE (invertedBits
[i
]);
3284 /* Create the pixmap. */
3286 Create_Pixmap_From_Bitmap_Data (f
, img
, bits
,
3287 foreground
, background
,
3288 non_default_colors
);
3293 image_error ("Unable to create pixmap for XBM image `%s'",
3295 x_clear_image (f
, img
);
3305 /***********************************************************************
3307 ***********************************************************************/
3309 #if defined (HAVE_XPM) || defined (HAVE_NS)
3311 static int xpm_image_p
P_ ((Lisp_Object object
));
3312 static int xpm_load
P_ ((struct frame
*f
, struct image
*img
));
3313 static int xpm_valid_color_symbols_p
P_ ((Lisp_Object
));
3315 #endif /* HAVE_XPM || HAVE_NS */
3319 /* Indicate to xpm.h that we don't have Xlib. */
3321 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3322 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3323 #define XColor xpm_XColor
3324 #define XImage xpm_XImage
3325 #define Display xpm_Display
3326 #define PIXEL_ALREADY_TYPEDEFED
3327 #include "X11/xpm.h"
3332 #undef PIXEL_ALREADY_TYPEDEFED
3334 #include "X11/xpm.h"
3335 #endif /* HAVE_NTGUI */
3336 #endif /* HAVE_XPM */
3338 #if defined (HAVE_XPM) || defined (HAVE_NS)
3339 /* The symbol `xpm' identifying XPM-format images. */
3343 /* Indices of image specification fields in xpm_format, below. */
3345 enum xpm_keyword_index
3361 /* Vector of image_keyword structures describing the format
3362 of valid XPM image specifications. */
3364 static struct image_keyword xpm_format
[XPM_LAST
] =
3366 {":type", IMAGE_SYMBOL_VALUE
, 1},
3367 {":file", IMAGE_STRING_VALUE
, 0},
3368 {":data", IMAGE_STRING_VALUE
, 0},
3369 {":ascent", IMAGE_ASCENT_VALUE
, 0},
3370 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
3371 {":relief", IMAGE_INTEGER_VALUE
, 0},
3372 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3373 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3374 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3375 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
3376 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
3379 /* Structure describing the image type XPM. */
3381 static struct image_type xpm_type
=
3390 #ifdef HAVE_X_WINDOWS
3392 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3393 functions for allocating image colors. Our own functions handle
3394 color allocation failures more gracefully than the ones on the XPM
3397 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3398 #define ALLOC_XPM_COLORS
3400 #endif /* HAVE_X_WINDOWS */
3402 #ifdef ALLOC_XPM_COLORS
3404 static void xpm_init_color_cache
P_ ((struct frame
*, XpmAttributes
*));
3405 static void xpm_free_color_cache
P_ ((void));
3406 static int xpm_lookup_color
P_ ((struct frame
*, char *, XColor
*));
3407 static int xpm_color_bucket
P_ ((char *));
3408 static struct xpm_cached_color
*xpm_cache_color
P_ ((struct frame
*, char *,
3411 /* An entry in a hash table used to cache color definitions of named
3412 colors. This cache is necessary to speed up XPM image loading in
3413 case we do color allocations ourselves. Without it, we would need
3414 a call to XParseColor per pixel in the image. */
3416 struct xpm_cached_color
3418 /* Next in collision chain. */
3419 struct xpm_cached_color
*next
;
3421 /* Color definition (RGB and pixel color). */
3428 /* The hash table used for the color cache, and its bucket vector
3431 #define XPM_COLOR_CACHE_BUCKETS 1001
3432 struct xpm_cached_color
**xpm_color_cache
;
3434 /* Initialize the color cache. */
3437 xpm_init_color_cache (f
, attrs
)
3439 XpmAttributes
*attrs
;
3441 size_t nbytes
= XPM_COLOR_CACHE_BUCKETS
* sizeof *xpm_color_cache
;
3442 xpm_color_cache
= (struct xpm_cached_color
**) xmalloc (nbytes
);
3443 memset (xpm_color_cache
, 0, nbytes
);
3444 init_color_table ();
3446 if (attrs
->valuemask
& XpmColorSymbols
)
3451 for (i
= 0; i
< attrs
->numsymbols
; ++i
)
3452 if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3453 attrs
->colorsymbols
[i
].value
, &color
))
3455 color
.pixel
= lookup_rgb_color (f
, color
.red
, color
.green
,
3457 xpm_cache_color (f
, attrs
->colorsymbols
[i
].name
, &color
, -1);
3462 /* Free the color cache. */
3465 xpm_free_color_cache ()
3467 struct xpm_cached_color
*p
, *next
;
3470 for (i
= 0; i
< XPM_COLOR_CACHE_BUCKETS
; ++i
)
3471 for (p
= xpm_color_cache
[i
]; p
; p
= next
)
3477 xfree (xpm_color_cache
);
3478 xpm_color_cache
= NULL
;
3479 free_color_table ();
3482 /* Return the bucket index for color named COLOR_NAME in the color
3486 xpm_color_bucket (color_name
)
3492 for (s
= color_name
; *s
; ++s
)
3494 return h
%= XPM_COLOR_CACHE_BUCKETS
;
3498 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3499 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3502 static struct xpm_cached_color
*
3503 xpm_cache_color (f
, color_name
, color
, bucket
)
3510 struct xpm_cached_color
*p
;
3513 bucket
= xpm_color_bucket (color_name
);
3515 nbytes
= sizeof *p
+ strlen (color_name
);
3516 p
= (struct xpm_cached_color
*) xmalloc (nbytes
);
3517 strcpy (p
->name
, color_name
);
3519 p
->next
= xpm_color_cache
[bucket
];
3520 xpm_color_cache
[bucket
] = p
;
3524 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3525 return the cached definition in *COLOR. Otherwise, make a new
3526 entry in the cache and allocate the color. Value is zero if color
3527 allocation failed. */
3530 xpm_lookup_color (f
, color_name
, color
)
3535 struct xpm_cached_color
*p
;
3536 int h
= xpm_color_bucket (color_name
);
3538 for (p
= xpm_color_cache
[h
]; p
; p
= p
->next
)
3539 if (strcmp (p
->name
, color_name
) == 0)
3544 else if (XParseColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
),
3547 color
->pixel
= lookup_rgb_color (f
, color
->red
, color
->green
,
3549 p
= xpm_cache_color (f
, color_name
, color
, h
);
3551 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3552 with transparency, and it's useful. */
3553 else if (strcmp ("opaque", color_name
) == 0)
3555 bzero (color
, sizeof (XColor
)); /* Is this necessary/correct? */
3556 color
->pixel
= FRAME_FOREGROUND_PIXEL (f
);
3557 p
= xpm_cache_color (f
, color_name
, color
, h
);
3564 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3565 CLOSURE is a pointer to the frame on which we allocate the
3566 color. Return in *COLOR the allocated color. Value is non-zero
3570 xpm_alloc_color (dpy
, cmap
, color_name
, color
, closure
)
3577 return xpm_lookup_color ((struct frame
*) closure
, color_name
, color
);
3581 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3582 is a pointer to the frame on which we allocate the color. Value is
3583 non-zero if successful. */
3586 xpm_free_colors (dpy
, cmap
, pixels
, npixels
, closure
)
3596 #endif /* ALLOC_XPM_COLORS */
3601 /* XPM library details. */
3603 DEF_IMGLIB_FN (XpmFreeAttributes
);
3604 DEF_IMGLIB_FN (XpmCreateImageFromBuffer
);
3605 DEF_IMGLIB_FN (XpmReadFileToImage
);
3606 DEF_IMGLIB_FN (XImageFree
);
3609 init_xpm_functions (Lisp_Object libraries
)
3613 if (!(library
= w32_delayed_load (libraries
, Qxpm
)))
3616 LOAD_IMGLIB_FN (library
, XpmFreeAttributes
);
3617 LOAD_IMGLIB_FN (library
, XpmCreateImageFromBuffer
);
3618 LOAD_IMGLIB_FN (library
, XpmReadFileToImage
);
3619 LOAD_IMGLIB_FN (library
, XImageFree
);
3623 #endif /* HAVE_NTGUI */
3626 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3627 for XPM images. Such a list must consist of conses whose car and
3631 xpm_valid_color_symbols_p (color_symbols
)
3632 Lisp_Object color_symbols
;
3634 while (CONSP (color_symbols
))
3636 Lisp_Object sym
= XCAR (color_symbols
);
3638 || !STRINGP (XCAR (sym
))
3639 || !STRINGP (XCDR (sym
)))
3641 color_symbols
= XCDR (color_symbols
);
3644 return NILP (color_symbols
);
3648 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3651 xpm_image_p (object
)
3654 struct image_keyword fmt
[XPM_LAST
];
3655 bcopy (xpm_format
, fmt
, sizeof fmt
);
3656 return (parse_image_spec (object
, fmt
, XPM_LAST
, Qxpm
)
3657 /* Either `:file' or `:data' must be present. */
3658 && fmt
[XPM_FILE
].count
+ fmt
[XPM_DATA
].count
== 1
3659 /* Either no `:color-symbols' or it's a list of conses
3660 whose car and cdr are strings. */
3661 && (fmt
[XPM_COLOR_SYMBOLS
].count
== 0
3662 || xpm_valid_color_symbols_p (fmt
[XPM_COLOR_SYMBOLS
].value
)));
3665 #endif /* HAVE_XPM || HAVE_NS */
3667 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3669 x_create_bitmap_from_xpm_data (f
, bits
)
3673 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3675 XpmAttributes attrs
;
3676 Pixmap bitmap
, mask
;
3678 bzero (&attrs
, sizeof attrs
);
3680 attrs
.visual
= FRAME_X_VISUAL (f
);
3681 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3682 attrs
.valuemask
|= XpmVisual
;
3683 attrs
.valuemask
|= XpmColormap
;
3685 rc
= XpmCreatePixmapFromData (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3686 bits
, &bitmap
, &mask
, &attrs
);
3687 if (rc
!= XpmSuccess
)
3689 XpmFreeAttributes (&attrs
);
3693 id
= x_allocate_bitmap_record (f
);
3694 dpyinfo
->bitmaps
[id
- 1].pixmap
= bitmap
;
3695 dpyinfo
->bitmaps
[id
- 1].have_mask
= 1;
3696 dpyinfo
->bitmaps
[id
- 1].mask
= mask
;
3697 dpyinfo
->bitmaps
[id
- 1].file
= NULL
;
3698 dpyinfo
->bitmaps
[id
- 1].height
= attrs
.height
;
3699 dpyinfo
->bitmaps
[id
- 1].width
= attrs
.width
;
3700 dpyinfo
->bitmaps
[id
- 1].depth
= attrs
.depth
;
3701 dpyinfo
->bitmaps
[id
- 1].refcount
= 1;
3703 XpmFreeAttributes (&attrs
);
3706 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3708 /* Load image IMG which will be displayed on frame F. Value is
3709 non-zero if successful. */
3719 XpmAttributes attrs
;
3720 Lisp_Object specified_file
, color_symbols
;
3723 xpm_XImage
* xpm_image
= NULL
, * xpm_mask
= NULL
;
3724 #endif /* HAVE_NTGUI */
3726 /* Configure the XPM lib. Use the visual of frame F. Allocate
3727 close colors. Return colors allocated. */
3728 bzero (&attrs
, sizeof attrs
);
3731 attrs
.visual
= FRAME_X_VISUAL (f
);
3732 attrs
.colormap
= FRAME_X_COLORMAP (f
);
3733 attrs
.valuemask
|= XpmVisual
;
3734 attrs
.valuemask
|= XpmColormap
;
3735 #endif /* HAVE_NTGUI */
3737 #ifdef ALLOC_XPM_COLORS
3738 /* Allocate colors with our own functions which handle
3739 failing color allocation more gracefully. */
3740 attrs
.color_closure
= f
;
3741 attrs
.alloc_color
= xpm_alloc_color
;
3742 attrs
.free_colors
= xpm_free_colors
;
3743 attrs
.valuemask
|= XpmAllocColor
| XpmFreeColors
| XpmColorClosure
;
3744 #else /* not ALLOC_XPM_COLORS */
3745 /* Let the XPM lib allocate colors. */
3746 attrs
.valuemask
|= XpmReturnAllocPixels
;
3747 #ifdef XpmAllocCloseColors
3748 attrs
.alloc_close_colors
= 1;
3749 attrs
.valuemask
|= XpmAllocCloseColors
;
3750 #else /* not XpmAllocCloseColors */
3751 attrs
.closeness
= 600;
3752 attrs
.valuemask
|= XpmCloseness
;
3753 #endif /* not XpmAllocCloseColors */
3754 #endif /* ALLOC_XPM_COLORS */
3756 /* If image specification contains symbolic color definitions, add
3757 these to `attrs'. */
3758 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
3759 if (CONSP (color_symbols
))
3762 XpmColorSymbol
*xpm_syms
;
3765 attrs
.valuemask
|= XpmColorSymbols
;
3767 /* Count number of symbols. */
3768 attrs
.numsymbols
= 0;
3769 for (tail
= color_symbols
; CONSP (tail
); tail
= XCDR (tail
))
3772 /* Allocate an XpmColorSymbol array. */
3773 size
= attrs
.numsymbols
* sizeof *xpm_syms
;
3774 xpm_syms
= (XpmColorSymbol
*) alloca (size
);
3775 bzero (xpm_syms
, size
);
3776 attrs
.colorsymbols
= xpm_syms
;
3778 /* Fill the color symbol array. */
3779 for (tail
= color_symbols
, i
= 0;
3781 ++i
, tail
= XCDR (tail
))
3783 Lisp_Object name
= XCAR (XCAR (tail
));
3784 Lisp_Object color
= XCDR (XCAR (tail
));
3785 xpm_syms
[i
].name
= (char *) alloca (SCHARS (name
) + 1);
3786 strcpy (xpm_syms
[i
].name
, SDATA (name
));
3787 xpm_syms
[i
].value
= (char *) alloca (SCHARS (color
) + 1);
3788 strcpy (xpm_syms
[i
].value
, SDATA (color
));
3792 /* Create a pixmap for the image, either from a file, or from a
3793 string buffer containing data in the same format as an XPM file. */
3794 #ifdef ALLOC_XPM_COLORS
3795 xpm_init_color_cache (f
, &attrs
);
3798 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
3802 HDC frame_dc
= get_frame_dc (f
);
3803 hdc
= CreateCompatibleDC (frame_dc
);
3804 release_frame_dc (f
, frame_dc
);
3806 #endif /* HAVE_NTGUI */
3808 if (STRINGP (specified_file
))
3810 Lisp_Object file
= x_find_image_file (specified_file
);
3811 if (!STRINGP (file
))
3813 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
3818 /* XpmReadFileToPixmap is not available in the Windows port of
3819 libxpm. But XpmReadFileToImage almost does what we want. */
3820 rc
= fn_XpmReadFileToImage (&hdc
, SDATA (file
),
3821 &xpm_image
, &xpm_mask
,
3824 rc
= XpmReadFileToPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3825 SDATA (file
), &img
->pixmap
, &img
->mask
,
3827 #endif /* HAVE_NTGUI */
3831 Lisp_Object buffer
= image_spec_value (img
->spec
, QCdata
, NULL
);
3833 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3834 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3835 rc
= fn_XpmCreateImageFromBuffer (&hdc
, SDATA (buffer
),
3836 &xpm_image
, &xpm_mask
,
3839 rc
= XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3841 &img
->pixmap
, &img
->mask
,
3843 #endif /* HAVE_NTGUI */
3846 if (rc
== XpmSuccess
)
3848 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3849 img
->colors
= colors_in_color_table (&img
->ncolors
);
3850 #else /* not ALLOC_XPM_COLORS */
3854 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3855 plus some duplicate attributes. */
3856 if (xpm_image
&& xpm_image
->bitmap
)
3858 img
->pixmap
= xpm_image
->bitmap
;
3859 /* XImageFree in libXpm frees XImage struct without destroying
3860 the bitmap, which is what we want. */
3861 fn_XImageFree (xpm_image
);
3863 if (xpm_mask
&& xpm_mask
->bitmap
)
3865 /* The mask appears to be inverted compared with what we expect.
3866 TODO: invert our expectations. See other places where we
3867 have to invert bits because our idea of masks is backwards. */
3869 old_obj
= SelectObject (hdc
, xpm_mask
->bitmap
);
3871 PatBlt (hdc
, 0, 0, xpm_mask
->width
, xpm_mask
->height
, DSTINVERT
);
3872 SelectObject (hdc
, old_obj
);
3874 img
->mask
= xpm_mask
->bitmap
;
3875 fn_XImageFree (xpm_mask
);
3880 #endif /* HAVE_NTGUI */
3882 /* Remember allocated colors. */
3883 img
->ncolors
= attrs
.nalloc_pixels
;
3884 img
->colors
= (unsigned long *) xmalloc (img
->ncolors
3885 * sizeof *img
->colors
);
3886 for (i
= 0; i
< attrs
.nalloc_pixels
; ++i
)
3888 img
->colors
[i
] = attrs
.alloc_pixels
[i
];
3889 #ifdef DEBUG_X_COLORS
3890 register_color (img
->colors
[i
]);
3893 #endif /* not ALLOC_XPM_COLORS */
3895 img
->width
= attrs
.width
;
3896 img
->height
= attrs
.height
;
3897 xassert (img
->width
> 0 && img
->height
> 0);
3899 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3901 fn_XpmFreeAttributes (&attrs
);
3903 XpmFreeAttributes (&attrs
);
3904 #endif /* HAVE_NTGUI */
3910 #endif /* HAVE_NTGUI */
3915 image_error ("Error opening XPM file (%s)", img
->spec
, Qnil
);
3918 case XpmFileInvalid
:
3919 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
3923 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
3926 case XpmColorFailed
:
3927 image_error ("Color allocation error (%s)", img
->spec
, Qnil
);
3931 image_error ("Unknown error (%s)", img
->spec
, Qnil
);
3936 #ifdef ALLOC_XPM_COLORS
3937 xpm_free_color_cache ();
3939 return rc
== XpmSuccess
;
3942 #endif /* HAVE_XPM */
3944 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3946 /* XPM support functions for NS where libxpm is not available.
3947 Only XPM version 3 (without any extensions) is supported. */
3949 static int xpm_scan
P_ ((const unsigned char **, const unsigned char *,
3950 const unsigned char **, int *));
3951 static Lisp_Object xpm_make_color_table_v
3952 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3953 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3954 static void xpm_put_color_table_v
P_ ((Lisp_Object
, const unsigned char *,
3956 static Lisp_Object xpm_get_color_table_v
P_ ((Lisp_Object
,
3957 const unsigned char *, int));
3958 static Lisp_Object xpm_make_color_table_h
3959 P_ ((void (**) (Lisp_Object
, const unsigned char *, int, Lisp_Object
),
3960 Lisp_Object (**) (Lisp_Object
, const unsigned char *, int)));
3961 static void xpm_put_color_table_h
P_ ((Lisp_Object
, const unsigned char *,
3963 static Lisp_Object xpm_get_color_table_h
P_ ((Lisp_Object
,
3964 const unsigned char *, int));
3965 static int xpm_str_to_color_key
P_ ((const char *));
3966 static int xpm_load_image
P_ ((struct frame
*, struct image
*,
3967 const unsigned char *, const unsigned char *));
3969 /* Tokens returned from xpm_scan. */
3978 /* Scan an XPM data and return a character (< 256) or a token defined
3979 by enum xpm_token above. *S and END are the start (inclusive) and
3980 the end (exclusive) addresses of the data, respectively. Advance
3981 *S while scanning. If token is either XPM_TK_IDENT or
3982 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3983 length of the corresponding token, respectively. */
3986 xpm_scan (s
, end
, beg
, len
)
3987 const unsigned char **s
, *end
, **beg
;
3994 /* Skip white-space. */
3995 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
3998 /* gnus-pointer.xpm uses '-' in its identifier.
3999 sb-dir-plus.xpm uses '+' in its identifier. */
4000 if (isalpha (c
) || c
== '_' || c
== '-' || c
== '+')
4004 && (c
= **s
, isalnum (c
) || c
== '_' || c
== '-' || c
== '+'))
4007 return XPM_TK_IDENT
;
4012 while (*s
< end
&& **s
!= '"')
4017 return XPM_TK_STRING
;
4021 if (*s
< end
&& **s
== '*')
4023 /* C-style comment. */
4027 while (*s
< end
&& *(*s
)++ != '*')
4030 while (*s
< end
&& **s
!= '/');
4044 /* Functions for color table lookup in XPM data. A key is a string
4045 specifying the color of each pixel in XPM data. A value is either
4046 an integer that specifies a pixel color, Qt that specifies
4047 transparency, or Qnil for the unspecified color. If the length of
4048 the key string is one, a vector is used as a table. Otherwise, a
4049 hash table is used. */
4052 xpm_make_color_table_v (put_func
, get_func
)
4053 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4054 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4056 *put_func
= xpm_put_color_table_v
;
4057 *get_func
= xpm_get_color_table_v
;
4058 return Fmake_vector (make_number (256), Qnil
);
4062 xpm_put_color_table_v (color_table
, chars_start
, chars_len
, color
)
4063 Lisp_Object color_table
;
4064 const unsigned char *chars_start
;
4068 XVECTOR (color_table
)->contents
[*chars_start
] = color
;
4072 xpm_get_color_table_v (color_table
, chars_start
, chars_len
)
4073 Lisp_Object color_table
;
4074 const unsigned char *chars_start
;
4077 return XVECTOR (color_table
)->contents
[*chars_start
];
4081 xpm_make_color_table_h (put_func
, get_func
)
4082 void (**put_func
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4083 Lisp_Object (**get_func
) (Lisp_Object
, const unsigned char *, int);
4085 *put_func
= xpm_put_color_table_h
;
4086 *get_func
= xpm_get_color_table_h
;
4087 return make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
4088 make_float (DEFAULT_REHASH_SIZE
),
4089 make_float (DEFAULT_REHASH_THRESHOLD
),
4094 xpm_put_color_table_h (color_table
, chars_start
, chars_len
, color
)
4095 Lisp_Object color_table
;
4096 const unsigned char *chars_start
;
4100 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4102 Lisp_Object chars
= make_unibyte_string (chars_start
, chars_len
);
4104 hash_lookup (table
, chars
, &hash_code
);
4105 hash_put (table
, chars
, color
, hash_code
);
4109 xpm_get_color_table_h (color_table
, chars_start
, chars_len
)
4110 Lisp_Object color_table
;
4111 const unsigned char *chars_start
;
4114 struct Lisp_Hash_Table
*table
= XHASH_TABLE (color_table
);
4115 int i
= hash_lookup (table
, make_unibyte_string (chars_start
, chars_len
),
4118 return i
>= 0 ? HASH_VALUE (table
, i
) : Qnil
;
4121 enum xpm_color_key
{
4129 static const char xpm_color_key_strings
[][4] = {"s", "m", "g4", "g", "c"};
4132 xpm_str_to_color_key (s
)
4138 i
< sizeof xpm_color_key_strings
/ sizeof xpm_color_key_strings
[0];
4140 if (strcmp (xpm_color_key_strings
[i
], s
) == 0)
4146 xpm_load_image (f
, img
, contents
, end
)
4149 const unsigned char *contents
, *end
;
4151 const unsigned char *s
= contents
, *beg
, *str
;
4152 unsigned char buffer
[BUFSIZ
];
4153 int width
, height
, x
, y
;
4154 int num_colors
, chars_per_pixel
;
4156 void (*put_color_table
) (Lisp_Object
, const unsigned char *, int, Lisp_Object
);
4157 Lisp_Object (*get_color_table
) (Lisp_Object
, const unsigned char *, int);
4158 Lisp_Object frame
, color_symbols
, color_table
;
4159 int best_key
, have_mask
= 0;
4160 XImagePtr ximg
= NULL
, mask_img
= NULL
;
4163 LA1 = xpm_scan (&s, end, &beg, &len)
4165 #define expect(TOKEN) \
4166 if (LA1 != (TOKEN)) \
4171 #define expect_ident(IDENT) \
4172 if (LA1 == XPM_TK_IDENT \
4173 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4178 if (!(end
- s
>= 9 && memcmp (s
, "/* XPM */", 9) == 0))
4182 expect_ident ("static");
4183 expect_ident ("char");
4185 expect (XPM_TK_IDENT
);
4190 expect (XPM_TK_STRING
);
4193 memcpy (buffer
, beg
, len
);
4195 if (sscanf (buffer
, "%d %d %d %d", &width
, &height
,
4196 &num_colors
, &chars_per_pixel
) != 4
4197 || width
<= 0 || height
<= 0
4198 || num_colors
<= 0 || chars_per_pixel
<= 0)
4201 if (!check_image_size (f
, width
, height
))
4203 image_error ("Invalid image size", Qnil
, Qnil
);
4209 XSETFRAME (frame
, f
);
4210 if (!NILP (Fxw_display_color_p (frame
)))
4211 best_key
= XPM_COLOR_KEY_C
;
4212 else if (!NILP (Fx_display_grayscale_p (frame
)))
4213 best_key
= (XFASTINT (Fx_display_planes (frame
)) > 2
4214 ? XPM_COLOR_KEY_G
: XPM_COLOR_KEY_G4
);
4216 best_key
= XPM_COLOR_KEY_M
;
4218 color_symbols
= image_spec_value (img
->spec
, QCcolor_symbols
, NULL
);
4219 if (chars_per_pixel
== 1)
4220 color_table
= xpm_make_color_table_v (&put_color_table
,
4223 color_table
= xpm_make_color_table_h (&put_color_table
,
4226 while (num_colors
-- > 0)
4228 unsigned char *color
, *max_color
;
4229 int key
, next_key
, max_key
= 0;
4230 Lisp_Object symbol_color
= Qnil
, color_val
;
4233 expect (XPM_TK_STRING
);
4234 if (len
<= chars_per_pixel
|| len
>= BUFSIZ
+ chars_per_pixel
)
4236 memcpy (buffer
, beg
+ chars_per_pixel
, len
- chars_per_pixel
);
4237 buffer
[len
- chars_per_pixel
] = '\0';
4239 str
= strtok (buffer
, " \t");
4242 key
= xpm_str_to_color_key (str
);
4247 color
= strtok (NULL
, " \t");
4251 while ((str
= strtok (NULL
, " \t")) != NULL
)
4253 next_key
= xpm_str_to_color_key (str
);
4256 color
[strlen (color
)] = ' ';
4259 if (key
== XPM_COLOR_KEY_S
)
4261 if (NILP (symbol_color
))
4262 symbol_color
= build_string (color
);
4264 else if (max_key
< key
&& key
<= best_key
)
4274 if (!NILP (color_symbols
) && !NILP (symbol_color
))
4276 Lisp_Object specified_color
= Fassoc (symbol_color
, color_symbols
);
4278 if (CONSP (specified_color
) && STRINGP (XCDR (specified_color
)))
4280 if (xstrcasecmp (SDATA (XCDR (specified_color
)), "None") == 0)
4282 else if (x_defined_color (f
, SDATA (XCDR (specified_color
)),
4284 color_val
= make_number (cdef
.pixel
);
4287 if (NILP (color_val
) && max_key
> 0)
4289 if (xstrcasecmp (max_color
, "None") == 0)
4291 else if (x_defined_color (f
, max_color
, &cdef
, 0))
4292 color_val
= make_number (cdef
.pixel
);
4294 if (!NILP (color_val
))
4295 (*put_color_table
) (color_table
, beg
, chars_per_pixel
, color_val
);
4300 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
4301 &ximg
, &img
->pixmap
)
4303 || !x_create_x_image_and_pixmap (f
, width
, height
, 1,
4304 &mask_img
, &img
->mask
)
4308 image_error ("Out of memory (%s)", img
->spec
, Qnil
);
4312 for (y
= 0; y
< height
; y
++)
4314 expect (XPM_TK_STRING
);
4316 if (len
< width
* chars_per_pixel
)
4318 for (x
= 0; x
< width
; x
++, str
+= chars_per_pixel
)
4320 Lisp_Object color_val
=
4321 (*get_color_table
) (color_table
, str
, chars_per_pixel
);
4323 XPutPixel (ximg
, x
, y
,
4324 (INTEGERP (color_val
) ? XINT (color_val
)
4325 : FRAME_FOREGROUND_PIXEL (f
)));
4327 XPutPixel (mask_img
, x
, y
,
4328 (!EQ (color_val
, Qt
) ? PIX_MASK_DRAW
4329 : (have_mask
= 1, PIX_MASK_RETAIN
)));
4331 if (EQ(color_val
, Qt
))
4332 ns_set_alpha(ximg
, x
, y
, 0);
4340 img
->height
= height
;
4342 /* Maybe fill in the background field while we have ximg handy. */
4343 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
4344 IMAGE_BACKGROUND (img
, f
, ximg
);
4346 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
4347 x_destroy_x_image (ximg
);
4351 /* Fill in the background_transparent field while we have the
4353 image_background_transparent (img
, f
, mask_img
);
4355 x_put_x_image (f
, mask_img
, img
->mask
, width
, height
);
4356 x_destroy_x_image (mask_img
);
4360 x_destroy_x_image (mask_img
);
4361 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
4362 img
->mask
= NO_PIXMAP
;
4368 image_error ("Invalid XPM file (%s)", img
->spec
, Qnil
);
4370 x_destroy_x_image (ximg
);
4371 x_destroy_x_image (mask_img
);
4372 x_clear_image (f
, img
);
4386 Lisp_Object file_name
;
4388 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4389 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
4390 if (STRINGP (file_name
))
4393 unsigned char *contents
;
4395 struct gcpro gcpro1
;
4397 file
= x_find_image_file (file_name
);
4399 if (!STRINGP (file
))
4401 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
4406 contents
= slurp_file (SDATA (file
), &size
);
4407 if (contents
== NULL
)
4409 image_error ("Error loading XPM image `%s'", img
->spec
, Qnil
);
4414 success_p
= xpm_load_image (f
, img
, contents
, contents
+ size
);
4422 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
4423 success_p
= xpm_load_image (f
, img
, SDATA (data
),
4424 SDATA (data
) + SBYTES (data
));
4430 #endif /* HAVE_NS && !HAVE_XPM */
4434 /***********************************************************************
4436 ***********************************************************************/
4438 #ifdef COLOR_TABLE_SUPPORT
4440 /* An entry in the color table mapping an RGB color to a pixel color. */
4445 unsigned long pixel
;
4447 /* Next in color table collision list. */
4448 struct ct_color
*next
;
4451 /* The bucket vector size to use. Must be prime. */
4455 /* Value is a hash of the RGB color given by R, G, and B. */
4457 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4459 /* The color hash table. */
4461 struct ct_color
**ct_table
;
4463 /* Number of entries in the color table. */
4465 int ct_colors_allocated
;
4467 /* Initialize the color table. */
4472 int size
= CT_SIZE
* sizeof (*ct_table
);
4473 ct_table
= (struct ct_color
**) xmalloc (size
);
4474 bzero (ct_table
, size
);
4475 ct_colors_allocated
= 0;
4479 /* Free memory associated with the color table. */
4485 struct ct_color
*p
, *next
;
4487 for (i
= 0; i
< CT_SIZE
; ++i
)
4488 for (p
= ct_table
[i
]; p
; p
= next
)
4499 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4500 entry for that color already is in the color table, return the
4501 pixel color of that entry. Otherwise, allocate a new color for R,
4502 G, B, and make an entry in the color table. */
4504 static unsigned long
4505 lookup_rgb_color (f
, r
, g
, b
)
4509 unsigned hash
= CT_HASH_RGB (r
, g
, b
);
4510 int i
= hash
% CT_SIZE
;
4512 Display_Info
*dpyinfo
;
4514 /* Handle TrueColor visuals specially, which improves performance by
4515 two orders of magnitude. Freeing colors on TrueColor visuals is
4516 a nop, and pixel colors specify RGB values directly. See also
4517 the Xlib spec, chapter 3.1. */
4518 dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
4519 if (dpyinfo
->red_bits
> 0)
4521 unsigned long pr
, pg
, pb
;
4523 /* Apply gamma-correction like normal color allocation does. */
4527 color
.red
= r
, color
.green
= g
, color
.blue
= b
;
4528 gamma_correct (f
, &color
);
4529 r
= color
.red
, g
= color
.green
, b
= color
.blue
;
4532 /* Scale down RGB values to the visual's bits per RGB, and shift
4533 them to the right position in the pixel color. Note that the
4534 original RGB values are 16-bit values, as usual in X. */
4535 pr
= (r
>> (16 - dpyinfo
->red_bits
)) << dpyinfo
->red_offset
;
4536 pg
= (g
>> (16 - dpyinfo
->green_bits
)) << dpyinfo
->green_offset
;
4537 pb
= (b
>> (16 - dpyinfo
->blue_bits
)) << dpyinfo
->blue_offset
;
4539 /* Assemble the pixel color. */
4540 return pr
| pg
| pb
;
4543 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4544 if (p
->r
== r
&& p
->g
== g
&& p
->b
== b
)
4550 #ifdef HAVE_X_WINDOWS
4559 cmap
= FRAME_X_COLORMAP (f
);
4560 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4563 ++ct_colors_allocated
;
4564 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4568 p
->pixel
= color
.pixel
;
4569 p
->next
= ct_table
[i
];
4573 return FRAME_FOREGROUND_PIXEL (f
);
4578 color
= PALETTERGB (r
, g
, b
);
4580 color
= RGB_TO_ULONG (r
, g
, b
);
4581 #endif /* HAVE_NTGUI */
4582 ++ct_colors_allocated
;
4583 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4588 p
->next
= ct_table
[i
];
4590 #endif /* HAVE_X_WINDOWS */
4598 /* Look up pixel color PIXEL which is used on frame F in the color
4599 table. If not already present, allocate it. Value is PIXEL. */
4601 static unsigned long
4602 lookup_pixel_color (f
, pixel
)
4604 unsigned long pixel
;
4606 int i
= pixel
% CT_SIZE
;
4609 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4610 if (p
->pixel
== pixel
)
4619 #ifdef HAVE_X_WINDOWS
4620 cmap
= FRAME_X_COLORMAP (f
);
4621 color
.pixel
= pixel
;
4622 x_query_color (f
, &color
);
4623 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4626 cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
4627 color
.pixel
= pixel
;
4628 XQueryColor (NULL
, cmap
, &color
);
4629 rc
= x_alloc_nearest_color (f
, cmap
, &color
);
4631 #endif /* HAVE_X_WINDOWS */
4635 ++ct_colors_allocated
;
4637 p
= (struct ct_color
*) xmalloc (sizeof *p
);
4642 p
->next
= ct_table
[i
];
4646 return FRAME_FOREGROUND_PIXEL (f
);
4652 /* Value is a vector of all pixel colors contained in the color table,
4653 allocated via xmalloc. Set *N to the number of colors. */
4655 static unsigned long *
4656 colors_in_color_table (n
)
4661 unsigned long *colors
;
4663 if (ct_colors_allocated
== 0)
4670 colors
= (unsigned long *) xmalloc (ct_colors_allocated
4672 *n
= ct_colors_allocated
;
4674 for (i
= j
= 0; i
< CT_SIZE
; ++i
)
4675 for (p
= ct_table
[i
]; p
; p
= p
->next
)
4676 colors
[j
++] = p
->pixel
;
4682 #else /* COLOR_TABLE_SUPPORT */
4684 static unsigned long
4685 lookup_rgb_color (f
, r
, g
, b
)
4689 unsigned long pixel
;
4692 pixel
= PALETTERGB (r
>> 8, g
>> 8, b
>> 8);
4693 #endif /* HAVE_NTGUI */
4696 pixel
= RGB_TO_ULONG (r
>> 8, g
>> 8, b
>> 8);
4697 #endif /* HAVE_NS */
4705 #endif /* COLOR_TABLE_SUPPORT */
4708 /***********************************************************************
4710 ***********************************************************************/
4712 static XColor
*x_to_xcolors
P_ ((struct frame
*, struct image
*, int));
4713 static void x_from_xcolors
P_ ((struct frame
*, struct image
*, XColor
*));
4714 static void x_detect_edges
P_ ((struct frame
*, struct image
*, int[9], int));
4717 static void XPutPixel (XImagePtr
, int, int, COLORREF
);
4718 #endif /* HAVE_NTGUI */
4720 /* Non-zero means draw a cross on images having `:conversion
4723 int cross_disabled_images
;
4725 /* Edge detection matrices for different edge-detection
4728 static int emboss_matrix
[9] = {
4730 2, -1, 0, /* y - 1 */
4732 0, 1, -2 /* y + 1 */
4735 static int laplace_matrix
[9] = {
4737 1, 0, 0, /* y - 1 */
4739 0, 0, -1 /* y + 1 */
4742 /* Value is the intensity of the color whose red/green/blue values
4745 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4748 /* On frame F, return an array of XColor structures describing image
4749 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4750 non-zero means also fill the red/green/blue members of the XColor
4751 structures. Value is a pointer to the array of XColors structures,
4752 allocated with xmalloc; it must be freed by the caller. */
4755 x_to_xcolors (f
, img
, rgb_p
)
4762 XImagePtr_or_DC ximg
;
4766 #endif /* HAVE_NTGUI */
4768 colors
= (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *colors
);
4771 /* Get the X image IMG->pixmap. */
4772 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
4773 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
4775 /* Load the image into a memory device context. */
4776 hdc
= get_frame_dc (f
);
4777 ximg
= CreateCompatibleDC (hdc
);
4778 release_frame_dc (f
, hdc
);
4779 prev
= SelectObject (ximg
, img
->pixmap
);
4780 #endif /* HAVE_NTGUI */
4782 /* Fill the `pixel' members of the XColor array. I wished there
4783 were an easy and portable way to circumvent XGetPixel. */
4785 for (y
= 0; y
< img
->height
; ++y
)
4789 #ifdef HAVE_X_WINDOWS
4790 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4791 p
->pixel
= XGetPixel (ximg
, x
, y
);
4793 x_query_colors (f
, row
, img
->width
);
4797 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4799 /* W32_TODO: palette support needed here? */
4800 p
->pixel
= GET_PIXEL (ximg
, x
, y
);
4803 #if defined (HAVE_NS)
4804 p
->red
= RED16_FROM_ULONG (p
->pixel
);
4805 p
->green
= GREEN16_FROM_ULONG (p
->pixel
);
4806 p
->blue
= BLUE16_FROM_ULONG (p
->pixel
);
4807 #endif /* HAVE_NS */
4809 p
->red
= 256 * GetRValue (p
->pixel
);
4810 p
->green
= 256 * GetGValue (p
->pixel
);
4811 p
->blue
= 256 * GetBValue (p
->pixel
);
4812 #endif /* HAVE_NTGUI */
4815 #endif /* HAVE_X_WINDOWS */
4818 Destroy_Image (ximg
, prev
);
4825 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4826 created with CreateDIBSection, with the pointer to the bit values
4827 stored in ximg->data. */
4830 XPutPixel (ximg
, x
, y
, color
)
4835 int width
= ximg
->info
.bmiHeader
.biWidth
;
4836 int height
= ximg
->info
.bmiHeader
.biHeight
;
4837 unsigned char * pixel
;
4839 /* True color images. */
4840 if (ximg
->info
.bmiHeader
.biBitCount
== 24)
4842 int rowbytes
= width
* 3;
4843 /* Ensure scanlines are aligned on 4 byte boundaries. */
4845 rowbytes
+= 4 - (rowbytes
% 4);
4847 pixel
= ximg
->data
+ y
* rowbytes
+ x
* 3;
4848 /* Windows bitmaps are in BGR order. */
4849 *pixel
= GetBValue (color
);
4850 *(pixel
+ 1) = GetGValue (color
);
4851 *(pixel
+ 2) = GetRValue (color
);
4853 /* Monochrome images. */
4854 else if (ximg
->info
.bmiHeader
.biBitCount
== 1)
4856 int rowbytes
= width
/ 8;
4857 /* Ensure scanlines are aligned on 4 byte boundaries. */
4859 rowbytes
+= 4 - (rowbytes
% 4);
4860 pixel
= ximg
->data
+ y
* rowbytes
+ x
/ 8;
4861 /* Filter out palette info. */
4862 if (color
& 0x00ffffff)
4863 *pixel
= *pixel
| (1 << x
% 8);
4865 *pixel
= *pixel
& ~(1 << x
% 8);
4868 image_error ("XPutPixel: palette image not supported", Qnil
, Qnil
);
4871 #endif /* HAVE_NTGUI */
4873 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4874 RGB members are set. F is the frame on which this all happens.
4875 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4878 x_from_xcolors (f
, img
, colors
)
4884 XImagePtr oimg
= NULL
;
4888 init_color_table ();
4890 x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 0,
4893 for (y
= 0; y
< img
->height
; ++y
)
4894 for (x
= 0; x
< img
->width
; ++x
, ++p
)
4896 unsigned long pixel
;
4897 pixel
= lookup_rgb_color (f
, p
->red
, p
->green
, p
->blue
);
4898 XPutPixel (oimg
, x
, y
, pixel
);
4902 x_clear_image_1 (f
, img
, 1, 0, 1);
4904 x_put_x_image (f
, oimg
, pixmap
, img
->width
, img
->height
);
4905 x_destroy_x_image (oimg
);
4906 img
->pixmap
= pixmap
;
4907 #ifdef COLOR_TABLE_SUPPORT
4908 img
->colors
= colors_in_color_table (&img
->ncolors
);
4909 free_color_table ();
4910 #endif /* COLOR_TABLE_SUPPORT */
4914 /* On frame F, perform edge-detection on image IMG.
4916 MATRIX is a nine-element array specifying the transformation
4917 matrix. See emboss_matrix for an example.
4919 COLOR_ADJUST is a color adjustment added to each pixel of the
4923 x_detect_edges (f
, img
, matrix
, color_adjust
)
4926 int matrix
[9], color_adjust
;
4928 XColor
*colors
= x_to_xcolors (f
, img
, 1);
4932 for (i
= sum
= 0; i
< 9; ++i
)
4933 sum
+= eabs (matrix
[i
]);
4935 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4937 new = (XColor
*) xmalloc (img
->width
* img
->height
* sizeof *new);
4939 for (y
= 0; y
< img
->height
; ++y
)
4941 p
= COLOR (new, 0, y
);
4942 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4943 p
= COLOR (new, img
->width
- 1, y
);
4944 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4947 for (x
= 1; x
< img
->width
- 1; ++x
)
4949 p
= COLOR (new, x
, 0);
4950 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4951 p
= COLOR (new, x
, img
->height
- 1);
4952 p
->red
= p
->green
= p
->blue
= 0xffff/2;
4955 for (y
= 1; y
< img
->height
- 1; ++y
)
4957 p
= COLOR (new, 1, y
);
4959 for (x
= 1; x
< img
->width
- 1; ++x
, ++p
)
4961 int r
, g
, b
, y1
, x1
;
4964 for (y1
= y
- 1; y1
< y
+ 2; ++y1
)
4965 for (x1
= x
- 1; x1
< x
+ 2; ++x1
, ++i
)
4968 XColor
*t
= COLOR (colors
, x1
, y1
);
4969 r
+= matrix
[i
] * t
->red
;
4970 g
+= matrix
[i
] * t
->green
;
4971 b
+= matrix
[i
] * t
->blue
;
4974 r
= (r
/ sum
+ color_adjust
) & 0xffff;
4975 g
= (g
/ sum
+ color_adjust
) & 0xffff;
4976 b
= (b
/ sum
+ color_adjust
) & 0xffff;
4977 p
->red
= p
->green
= p
->blue
= COLOR_INTENSITY (r
, g
, b
);
4982 x_from_xcolors (f
, img
, new);
4988 /* Perform the pre-defined `emboss' edge-detection on image IMG
4996 x_detect_edges (f
, img
, emboss_matrix
, 0xffff / 2);
5000 /* Transform image IMG which is used on frame F with a Laplace
5001 edge-detection algorithm. The result is an image that can be used
5002 to draw disabled buttons, for example. */
5009 x_detect_edges (f
, img
, laplace_matrix
, 45000);
5013 /* Perform edge-detection on image IMG on frame F, with specified
5014 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5016 MATRIX must be either
5018 - a list of at least 9 numbers in row-major form
5019 - a vector of at least 9 numbers
5021 COLOR_ADJUST nil means use a default; otherwise it must be a
5025 x_edge_detection (f
, img
, matrix
, color_adjust
)
5028 Lisp_Object matrix
, color_adjust
;
5036 i
< 9 && CONSP (matrix
) && NUMBERP (XCAR (matrix
));
5037 ++i
, matrix
= XCDR (matrix
))
5038 trans
[i
] = XFLOATINT (XCAR (matrix
));
5040 else if (VECTORP (matrix
) && ASIZE (matrix
) >= 9)
5042 for (i
= 0; i
< 9 && NUMBERP (AREF (matrix
, i
)); ++i
)
5043 trans
[i
] = XFLOATINT (AREF (matrix
, i
));
5046 if (NILP (color_adjust
))
5047 color_adjust
= make_number (0xffff / 2);
5049 if (i
== 9 && NUMBERP (color_adjust
))
5050 x_detect_edges (f
, img
, trans
, (int) XFLOATINT (color_adjust
));
5054 /* Transform image IMG on frame F so that it looks disabled. */
5057 x_disable_image (f
, img
)
5061 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5063 int n_planes
= dpyinfo
->n_planes
* dpyinfo
->n_cbits
;
5065 int n_planes
= dpyinfo
->n_planes
;
5066 #endif /* HAVE_NTGUI */
5070 /* Color (or grayscale). Convert to gray, and equalize. Just
5071 drawing such images with a stipple can look very odd, so
5072 we're using this method instead. */
5073 XColor
*colors
= x_to_xcolors (f
, img
, 1);
5075 const int h
= 15000;
5076 const int l
= 30000;
5078 for (p
= colors
, end
= colors
+ img
->width
* img
->height
;
5082 int i
= COLOR_INTENSITY (p
->red
, p
->green
, p
->blue
);
5083 int i2
= (0xffff - h
- l
) * i
/ 0xffff + l
;
5084 p
->red
= p
->green
= p
->blue
= i2
;
5087 x_from_xcolors (f
, img
, colors
);
5090 /* Draw a cross over the disabled image, if we must or if we
5092 if (n_planes
< 2 || cross_disabled_images
)
5095 Display
*dpy
= FRAME_X_DISPLAY (f
);
5098 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5100 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5102 gc
= XCreateGC (dpy
, img
->pixmap
, 0, NULL
);
5103 XSetForeground (dpy
, gc
, BLACK_PIX_DEFAULT (f
));
5104 XDrawLine (dpy
, img
->pixmap
, gc
, 0, 0,
5105 img
->width
- 1, img
->height
- 1);
5106 XDrawLine (dpy
, img
->pixmap
, gc
, 0, img
->height
- 1,
5112 gc
= XCreateGC (dpy
, img
->mask
, 0, NULL
);
5113 XSetForeground (dpy
, gc
, MaskForeground (f
));
5114 XDrawLine (dpy
, img
->mask
, gc
, 0, 0,
5115 img
->width
- 1, img
->height
- 1);
5116 XDrawLine (dpy
, img
->mask
, gc
, 0, img
->height
- 1,
5120 #endif /* !HAVE_NS */
5125 hdc
= get_frame_dc (f
);
5126 bmpdc
= CreateCompatibleDC (hdc
);
5127 release_frame_dc (f
, hdc
);
5129 prev
= SelectObject (bmpdc
, img
->pixmap
);
5131 SetTextColor (bmpdc
, BLACK_PIX_DEFAULT (f
));
5132 MoveToEx (bmpdc
, 0, 0, NULL
);
5133 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5134 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5135 LineTo (bmpdc
, img
->width
- 1, 0);
5139 SelectObject (bmpdc
, img
->mask
);
5140 SetTextColor (bmpdc
, WHITE_PIX_DEFAULT (f
));
5141 MoveToEx (bmpdc
, 0, 0, NULL
);
5142 LineTo (bmpdc
, img
->width
- 1, img
->height
- 1);
5143 MoveToEx (bmpdc
, 0, img
->height
- 1, NULL
);
5144 LineTo (bmpdc
, img
->width
- 1, 0);
5146 SelectObject (bmpdc
, prev
);
5148 #endif /* HAVE_NTGUI */
5153 /* Build a mask for image IMG which is used on frame F. FILE is the
5154 name of an image file, for error messages. HOW determines how to
5155 determine the background color of IMG. If it is a list '(R G B)',
5156 with R, G, and B being integers >= 0, take that as the color of the
5157 background. Otherwise, determine the background color of IMG
5158 heuristically. Value is non-zero if successful. */
5161 x_build_heuristic_mask (f
, img
, how
)
5166 XImagePtr_or_DC ximg
;
5174 #endif /* HAVE_NTGUI */
5175 int x
, y
, rc
, use_img_background
;
5176 unsigned long bg
= 0;
5180 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->mask
);
5181 img
->mask
= NO_PIXMAP
;
5182 img
->background_transparent_valid
= 0;
5187 /* Create an image and pixmap serving as mask. */
5188 rc
= x_create_x_image_and_pixmap (f
, img
->width
, img
->height
, 1,
5189 &mask_img
, &img
->mask
);
5192 #endif /* !HAVE_NS */
5194 /* Get the X image of IMG->pixmap. */
5195 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
, 0, 0,
5196 img
->width
, img
->height
,
5199 /* Create the bit array serving as mask. */
5200 row_width
= (img
->width
+ 7) / 8;
5201 mask_img
= xmalloc (row_width
* img
->height
);
5202 bzero (mask_img
, row_width
* img
->height
);
5204 /* Create a memory device context for IMG->pixmap. */
5205 frame_dc
= get_frame_dc (f
);
5206 ximg
= CreateCompatibleDC (frame_dc
);
5207 release_frame_dc (f
, frame_dc
);
5208 prev
= SelectObject (ximg
, img
->pixmap
);
5209 #endif /* HAVE_NTGUI */
5211 /* Determine the background color of ximg. If HOW is `(R G B)'
5212 take that as color. Otherwise, use the image's background color. */
5213 use_img_background
= 1;
5219 for (i
= 0; i
< 3 && CONSP (how
) && NATNUMP (XCAR (how
)); ++i
)
5221 rgb
[i
] = XFASTINT (XCAR (how
)) & 0xffff;
5225 if (i
== 3 && NILP (how
))
5227 char color_name
[30];
5228 sprintf (color_name
, "#%04x%04x%04x", rgb
[0], rgb
[1], rgb
[2]);
5231 0x00ffffff & /* Filter out palette info. */
5232 #endif /* HAVE_NTGUI */
5233 x_alloc_image_color (f
, img
, build_string (color_name
), 0));
5234 use_img_background
= 0;
5238 if (use_img_background
)
5239 bg
= four_corners_best (ximg
, img
->corners
, img
->width
, img
->height
);
5241 /* Set all bits in mask_img to 1 whose color in ximg is different
5242 from the background color bg. */
5244 for (y
= 0; y
< img
->height
; ++y
)
5245 for (x
= 0; x
< img
->width
; ++x
)
5247 XPutPixel (mask_img
, x
, y
, (XGetPixel (ximg
, x
, y
) != bg
5248 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
));
5250 if (XGetPixel (ximg
, x
, y
) == bg
)
5251 ns_set_alpha(ximg
, x
, y
, 0);
5252 #endif /* HAVE_NS */
5254 /* Fill in the background_transparent field while we have the mask handy. */
5255 image_background_transparent (img
, f
, mask_img
);
5257 /* Put mask_img into img->mask. */
5258 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
5259 x_destroy_x_image (mask_img
);
5260 #endif /* !HAVE_NS */
5262 for (y
= 0; y
< img
->height
; ++y
)
5263 for (x
= 0; x
< img
->width
; ++x
)
5265 COLORREF p
= GetPixel (ximg
, x
, y
);
5267 mask_img
[y
* row_width
+ x
/ 8] |= 1 << (x
% 8);
5270 /* Create the mask image. */
5271 img
->mask
= w32_create_pixmap_from_bitmap_data (img
->width
, img
->height
,
5273 /* Fill in the background_transparent field while we have the mask handy. */
5274 SelectObject (ximg
, img
->mask
);
5275 image_background_transparent (img
, f
, ximg
);
5277 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5279 #endif /* HAVE_NTGUI */
5281 Destroy_Image (ximg
, prev
);
5287 /***********************************************************************
5288 PBM (mono, gray, color)
5289 ***********************************************************************/
5291 static int pbm_image_p
P_ ((Lisp_Object object
));
5292 static int pbm_load
P_ ((struct frame
*f
, struct image
*img
));
5293 static int pbm_scan_number
P_ ((unsigned char **, unsigned char *));
5295 /* The symbol `pbm' identifying images of this type. */
5299 /* Indices of image specification fields in gs_format, below. */
5301 enum pbm_keyword_index
5317 /* Vector of image_keyword structures describing the format
5318 of valid user-defined image specifications. */
5320 static struct image_keyword pbm_format
[PBM_LAST
] =
5322 {":type", IMAGE_SYMBOL_VALUE
, 1},
5323 {":file", IMAGE_STRING_VALUE
, 0},
5324 {":data", IMAGE_STRING_VALUE
, 0},
5325 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5326 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5327 {":relief", IMAGE_INTEGER_VALUE
, 0},
5328 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5329 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5330 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5331 {":foreground", IMAGE_STRING_OR_NIL_VALUE
, 0},
5332 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5335 /* Structure describing the image type `pbm'. */
5337 static struct image_type pbm_type
=
5347 /* Return non-zero if OBJECT is a valid PBM image specification. */
5350 pbm_image_p (object
)
5353 struct image_keyword fmt
[PBM_LAST
];
5355 bcopy (pbm_format
, fmt
, sizeof fmt
);
5357 if (!parse_image_spec (object
, fmt
, PBM_LAST
, Qpbm
))
5360 /* Must specify either :data or :file. */
5361 return fmt
[PBM_DATA
].count
+ fmt
[PBM_FILE
].count
== 1;
5365 /* Scan a decimal number from *S and return it. Advance *S while
5366 reading the number. END is the end of the string. Value is -1 at
5370 pbm_scan_number (s
, end
)
5371 unsigned char **s
, *end
;
5373 int c
= 0, val
= -1;
5377 /* Skip white-space. */
5378 while (*s
< end
&& (c
= *(*s
)++, isspace (c
)))
5383 /* Skip comment to end of line. */
5384 while (*s
< end
&& (c
= *(*s
)++, c
!= '\n'))
5387 else if (isdigit (c
))
5389 /* Read decimal number. */
5391 while (*s
< end
&& (c
= *(*s
)++, isdigit (c
)))
5392 val
= 10 * val
+ c
- '0';
5404 #if 0 /* Unused. ++kfs */
5406 /* Read FILE into memory. Value is a pointer to a buffer allocated
5407 with xmalloc holding FILE's contents. Value is null if an error
5408 occurred. *SIZE is set to the size of the file. */
5411 pbm_read_file (file
, size
)
5419 if (stat (SDATA (file
), &st
) == 0
5420 && (fp
= fopen (SDATA (file
), "rb")) != NULL
5421 && (buf
= (char *) xmalloc (st
.st_size
),
5422 fread (buf
, 1, st
.st_size
, fp
) == st
.st_size
))
5441 #endif /* HAVE_NTGUI */
5443 /* Load PBM image IMG for use on frame F. */
5451 int width
, height
, max_color_idx
= 0;
5453 Lisp_Object file
, specified_file
;
5454 enum {PBM_MONO
, PBM_GRAY
, PBM_COLOR
} type
;
5455 struct gcpro gcpro1
;
5456 unsigned char *contents
= NULL
;
5457 unsigned char *end
, *p
;
5460 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5464 if (STRINGP (specified_file
))
5466 file
= x_find_image_file (specified_file
);
5467 if (!STRINGP (file
))
5469 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5474 contents
= slurp_file (SDATA (file
), &size
);
5475 if (contents
== NULL
)
5477 image_error ("Error reading `%s'", file
, Qnil
);
5483 end
= contents
+ size
;
5488 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5490 end
= p
+ SBYTES (data
);
5493 /* Check magic number. */
5494 if (end
- p
< 2 || *p
++ != 'P')
5496 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5506 raw_p
= 0, type
= PBM_MONO
;
5510 raw_p
= 0, type
= PBM_GRAY
;
5514 raw_p
= 0, type
= PBM_COLOR
;
5518 raw_p
= 1, type
= PBM_MONO
;
5522 raw_p
= 1, type
= PBM_GRAY
;
5526 raw_p
= 1, type
= PBM_COLOR
;
5530 image_error ("Not a PBM image: `%s'", img
->spec
, Qnil
);
5534 /* Read width, height, maximum color-component. Characters
5535 starting with `#' up to the end of a line are ignored. */
5536 width
= pbm_scan_number (&p
, end
);
5537 height
= pbm_scan_number (&p
, end
);
5539 if (type
!= PBM_MONO
)
5541 max_color_idx
= pbm_scan_number (&p
, end
);
5542 if (max_color_idx
> 65535 || max_color_idx
< 0)
5544 image_error ("Unsupported maximum PBM color value", Qnil
, Qnil
);
5549 if (!check_image_size (f
, width
, height
))
5551 image_error ("Invalid image size", Qnil
, Qnil
);
5555 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0,
5556 &ximg
, &img
->pixmap
))
5559 /* Initialize the color hash table. */
5560 init_color_table ();
5562 if (type
== PBM_MONO
)
5565 struct image_keyword fmt
[PBM_LAST
];
5566 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
5567 unsigned long bg
= FRAME_BACKGROUND_PIXEL (f
);
5569 /* Parse the image specification. */
5570 bcopy (pbm_format
, fmt
, sizeof fmt
);
5571 parse_image_spec (img
->spec
, fmt
, PBM_LAST
, Qpbm
);
5573 /* Get foreground and background colors, maybe allocate colors. */
5574 if (fmt
[PBM_FOREGROUND
].count
5575 && STRINGP (fmt
[PBM_FOREGROUND
].value
))
5576 fg
= x_alloc_image_color (f
, img
, fmt
[PBM_FOREGROUND
].value
, fg
);
5577 if (fmt
[PBM_BACKGROUND
].count
5578 && STRINGP (fmt
[PBM_BACKGROUND
].value
))
5580 bg
= x_alloc_image_color (f
, img
, fmt
[PBM_BACKGROUND
].value
, bg
);
5581 img
->background
= bg
;
5582 img
->background_valid
= 1;
5585 for (y
= 0; y
< height
; ++y
)
5586 for (x
= 0; x
< width
; ++x
)
5594 x_destroy_x_image (ximg
);
5595 x_clear_image (f
, img
);
5596 image_error ("Invalid image size in image `%s'",
5606 g
= pbm_scan_number (&p
, end
);
5608 XPutPixel (ximg
, x
, y
, g
? fg
: bg
);
5613 int expected_size
= height
* width
;
5614 if (max_color_idx
> 255)
5616 if (type
== PBM_COLOR
)
5619 if (raw_p
&& p
+ expected_size
> end
)
5621 x_destroy_x_image (ximg
);
5622 x_clear_image (f
, img
);
5623 image_error ("Invalid image size in image `%s'",
5628 for (y
= 0; y
< height
; ++y
)
5629 for (x
= 0; x
< width
; ++x
)
5633 if (type
== PBM_GRAY
&& raw_p
)
5636 if (max_color_idx
> 255)
5637 r
= g
= b
= r
* 256 + *p
++;
5639 else if (type
== PBM_GRAY
)
5640 r
= g
= b
= pbm_scan_number (&p
, end
);
5644 if (max_color_idx
> 255)
5647 if (max_color_idx
> 255)
5650 if (max_color_idx
> 255)
5655 r
= pbm_scan_number (&p
, end
);
5656 g
= pbm_scan_number (&p
, end
);
5657 b
= pbm_scan_number (&p
, end
);
5660 if (r
< 0 || g
< 0 || b
< 0)
5662 x_destroy_x_image (ximg
);
5663 image_error ("Invalid pixel value in image `%s'",
5668 /* RGB values are now in the range 0..max_color_idx.
5669 Scale this to the range 0..0xffff supported by X. */
5670 r
= (double) r
* 65535 / max_color_idx
;
5671 g
= (double) g
* 65535 / max_color_idx
;
5672 b
= (double) b
* 65535 / max_color_idx
;
5673 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
5677 #ifdef COLOR_TABLE_SUPPORT
5678 /* Store in IMG->colors the colors allocated for the image, and
5679 free the color table. */
5680 img
->colors
= colors_in_color_table (&img
->ncolors
);
5681 free_color_table ();
5682 #endif /* COLOR_TABLE_SUPPORT */
5685 img
->height
= height
;
5687 /* Maybe fill in the background field while we have ximg handy. */
5689 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
5690 /* Casting avoids a GCC warning. */
5691 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
5693 /* Put the image into a pixmap. */
5694 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
5695 x_destroy_x_image (ximg
);
5697 /* X and W32 versions did it here, MAC version above. ++kfs
5699 img->height = height; */
5707 /***********************************************************************
5709 ***********************************************************************/
5711 #if defined (HAVE_PNG) || defined (HAVE_NS)
5713 /* Function prototypes. */
5715 static int png_image_p
P_ ((Lisp_Object object
));
5716 static int png_load
P_ ((struct frame
*f
, struct image
*img
));
5718 /* The symbol `png' identifying images of this type. */
5722 /* Indices of image specification fields in png_format, below. */
5724 enum png_keyword_index
5739 /* Vector of image_keyword structures describing the format
5740 of valid user-defined image specifications. */
5742 static struct image_keyword png_format
[PNG_LAST
] =
5744 {":type", IMAGE_SYMBOL_VALUE
, 1},
5745 {":data", IMAGE_STRING_VALUE
, 0},
5746 {":file", IMAGE_STRING_VALUE
, 0},
5747 {":ascent", IMAGE_ASCENT_VALUE
, 0},
5748 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
5749 {":relief", IMAGE_INTEGER_VALUE
, 0},
5750 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5751 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5752 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
5753 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
5756 /* Structure describing the image type `png'. */
5758 static struct image_type png_type
=
5767 /* Return non-zero if OBJECT is a valid PNG image specification. */
5770 png_image_p (object
)
5773 struct image_keyword fmt
[PNG_LAST
];
5774 bcopy (png_format
, fmt
, sizeof fmt
);
5776 if (!parse_image_spec (object
, fmt
, PNG_LAST
, Qpng
))
5779 /* Must specify either the :data or :file keyword. */
5780 return fmt
[PNG_FILE
].count
+ fmt
[PNG_DATA
].count
== 1;
5783 #endif /* HAVE_PNG || HAVE_NS */
5788 #if defined HAVE_LIBPNG_PNG_H
5789 # include <libpng/png.h>
5795 /* PNG library details. */
5797 DEF_IMGLIB_FN (png_get_io_ptr
);
5798 DEF_IMGLIB_FN (png_check_sig
);
5799 DEF_IMGLIB_FN (png_create_read_struct
);
5800 DEF_IMGLIB_FN (png_create_info_struct
);
5801 DEF_IMGLIB_FN (png_destroy_read_struct
);
5802 DEF_IMGLIB_FN (png_set_read_fn
);
5803 DEF_IMGLIB_FN (png_set_sig_bytes
);
5804 DEF_IMGLIB_FN (png_read_info
);
5805 DEF_IMGLIB_FN (png_get_IHDR
);
5806 DEF_IMGLIB_FN (png_get_valid
);
5807 DEF_IMGLIB_FN (png_set_strip_16
);
5808 DEF_IMGLIB_FN (png_set_expand
);
5809 DEF_IMGLIB_FN (png_set_gray_to_rgb
);
5810 DEF_IMGLIB_FN (png_set_background
);
5811 DEF_IMGLIB_FN (png_get_bKGD
);
5812 DEF_IMGLIB_FN (png_read_update_info
);
5813 DEF_IMGLIB_FN (png_get_channels
);
5814 DEF_IMGLIB_FN (png_get_rowbytes
);
5815 DEF_IMGLIB_FN (png_read_image
);
5816 DEF_IMGLIB_FN (png_read_end
);
5817 DEF_IMGLIB_FN (png_error
);
5820 init_png_functions (Lisp_Object libraries
)
5824 /* Try loading libpng under probable names. */
5825 if (!(library
= w32_delayed_load (libraries
, Qpng
)))
5828 LOAD_IMGLIB_FN (library
, png_get_io_ptr
);
5829 LOAD_IMGLIB_FN (library
, png_check_sig
);
5830 LOAD_IMGLIB_FN (library
, png_create_read_struct
);
5831 LOAD_IMGLIB_FN (library
, png_create_info_struct
);
5832 LOAD_IMGLIB_FN (library
, png_destroy_read_struct
);
5833 LOAD_IMGLIB_FN (library
, png_set_read_fn
);
5834 LOAD_IMGLIB_FN (library
, png_set_sig_bytes
);
5835 LOAD_IMGLIB_FN (library
, png_read_info
);
5836 LOAD_IMGLIB_FN (library
, png_get_IHDR
);
5837 LOAD_IMGLIB_FN (library
, png_get_valid
);
5838 LOAD_IMGLIB_FN (library
, png_set_strip_16
);
5839 LOAD_IMGLIB_FN (library
, png_set_expand
);
5840 LOAD_IMGLIB_FN (library
, png_set_gray_to_rgb
);
5841 LOAD_IMGLIB_FN (library
, png_set_background
);
5842 LOAD_IMGLIB_FN (library
, png_get_bKGD
);
5843 LOAD_IMGLIB_FN (library
, png_read_update_info
);
5844 LOAD_IMGLIB_FN (library
, png_get_channels
);
5845 LOAD_IMGLIB_FN (library
, png_get_rowbytes
);
5846 LOAD_IMGLIB_FN (library
, png_read_image
);
5847 LOAD_IMGLIB_FN (library
, png_read_end
);
5848 LOAD_IMGLIB_FN (library
, png_error
);
5853 #define fn_png_get_io_ptr png_get_io_ptr
5854 #define fn_png_check_sig png_check_sig
5855 #define fn_png_create_read_struct png_create_read_struct
5856 #define fn_png_create_info_struct png_create_info_struct
5857 #define fn_png_destroy_read_struct png_destroy_read_struct
5858 #define fn_png_set_read_fn png_set_read_fn
5859 #define fn_png_set_sig_bytes png_set_sig_bytes
5860 #define fn_png_read_info png_read_info
5861 #define fn_png_get_IHDR png_get_IHDR
5862 #define fn_png_get_valid png_get_valid
5863 #define fn_png_set_strip_16 png_set_strip_16
5864 #define fn_png_set_expand png_set_expand
5865 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5866 #define fn_png_set_background png_set_background
5867 #define fn_png_get_bKGD png_get_bKGD
5868 #define fn_png_read_update_info png_read_update_info
5869 #define fn_png_get_channels png_get_channels
5870 #define fn_png_get_rowbytes png_get_rowbytes
5871 #define fn_png_read_image png_read_image
5872 #define fn_png_read_end png_read_end
5873 #define fn_png_error png_error
5875 #endif /* HAVE_NTGUI */
5877 /* Error and warning handlers installed when the PNG library
5881 my_png_error (png_ptr
, msg
)
5882 png_struct
*png_ptr
;
5885 xassert (png_ptr
!= NULL
);
5886 image_error ("PNG error: %s", build_string (msg
), Qnil
);
5887 longjmp (png_ptr
->jmpbuf
, 1);
5892 my_png_warning (png_ptr
, msg
)
5893 png_struct
*png_ptr
;
5896 xassert (png_ptr
!= NULL
);
5897 image_error ("PNG warning: %s", build_string (msg
), Qnil
);
5900 /* Memory source for PNG decoding. */
5902 struct png_memory_storage
5904 unsigned char *bytes
; /* The data */
5905 size_t len
; /* How big is it? */
5906 int index
; /* Where are we? */
5910 /* Function set as reader function when reading PNG image from memory.
5911 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5912 bytes from the input to DATA. */
5915 png_read_from_memory (png_ptr
, data
, length
)
5916 png_structp png_ptr
;
5920 struct png_memory_storage
*tbr
5921 = (struct png_memory_storage
*) fn_png_get_io_ptr (png_ptr
);
5923 if (length
> tbr
->len
- tbr
->index
)
5924 fn_png_error (png_ptr
, "Read error");
5926 bcopy (tbr
->bytes
+ tbr
->index
, data
, length
);
5927 tbr
->index
= tbr
->index
+ length
;
5931 /* Function set as reader function when reading PNG image from a file.
5932 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5933 bytes from the input to DATA. */
5936 png_read_from_file (png_ptr
, data
, length
)
5937 png_structp png_ptr
;
5941 FILE *fp
= (FILE *) fn_png_get_io_ptr (png_ptr
);
5943 if (fread (data
, 1, length
, fp
) < length
)
5944 fn_png_error (png_ptr
, "Read error");
5948 /* Load PNG image IMG for use on frame F. Value is non-zero if
5956 Lisp_Object file
, specified_file
;
5957 Lisp_Object specified_data
;
5959 XImagePtr ximg
, mask_img
= NULL
;
5960 struct gcpro gcpro1
;
5961 png_struct
*png_ptr
= NULL
;
5962 png_info
*info_ptr
= NULL
, *end_info
= NULL
;
5963 FILE *volatile fp
= NULL
;
5965 png_byte
* volatile pixels
= NULL
;
5966 png_byte
** volatile rows
= NULL
;
5967 png_uint_32 width
, height
;
5968 int bit_depth
, color_type
, interlace_type
;
5970 png_uint_32 row_bytes
;
5972 struct png_memory_storage tbr
; /* Data to be read */
5974 /* Find out what file to load. */
5975 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
5976 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
5980 if (NILP (specified_data
))
5982 file
= x_find_image_file (specified_file
);
5983 if (!STRINGP (file
))
5985 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
5990 /* Open the image file. */
5991 fp
= fopen (SDATA (file
), "rb");
5994 image_error ("Cannot open image file `%s'", file
, Qnil
);
5999 /* Check PNG signature. */
6000 if (fread (sig
, 1, sizeof sig
, fp
) != sizeof sig
6001 || !fn_png_check_sig (sig
, sizeof sig
))
6003 image_error ("Not a PNG file: `%s'", file
, Qnil
);
6011 /* Read from memory. */
6012 tbr
.bytes
= SDATA (specified_data
);
6013 tbr
.len
= SBYTES (specified_data
);
6016 /* Check PNG signature. */
6017 if (tbr
.len
< sizeof sig
6018 || !fn_png_check_sig (tbr
.bytes
, sizeof sig
))
6020 image_error ("Not a PNG image: `%s'", img
->spec
, Qnil
);
6025 /* Need to skip past the signature. */
6026 tbr
.bytes
+= sizeof (sig
);
6029 /* Initialize read and info structs for PNG lib. Casting return
6030 value avoids a GCC warning on W32. */
6031 png_ptr
= (png_structp
)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING
,
6036 if (fp
) fclose (fp
);
6041 /* Casting return value avoids a GCC warning on W32. */
6042 info_ptr
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6045 fn_png_destroy_read_struct (&png_ptr
, NULL
, NULL
);
6046 if (fp
) fclose (fp
);
6051 /* Casting return value avoids a GCC warning on W32. */
6052 end_info
= (png_infop
)fn_png_create_info_struct (png_ptr
);
6055 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, NULL
);
6056 if (fp
) fclose (fp
);
6061 /* Set error jump-back. We come back here when the PNG library
6062 detects an error. */
6063 if (setjmp (png_ptr
->jmpbuf
))
6067 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6070 if (fp
) fclose (fp
);
6075 /* Read image info. */
6076 if (!NILP (specified_data
))
6077 fn_png_set_read_fn (png_ptr
, (void *) &tbr
, png_read_from_memory
);
6079 fn_png_set_read_fn (png_ptr
, (void *) fp
, png_read_from_file
);
6081 fn_png_set_sig_bytes (png_ptr
, sizeof sig
);
6082 fn_png_read_info (png_ptr
, info_ptr
);
6083 fn_png_get_IHDR (png_ptr
, info_ptr
, &width
, &height
, &bit_depth
, &color_type
,
6084 &interlace_type
, NULL
, NULL
);
6086 if (!check_image_size (f
, width
, height
))
6089 /* If image contains simply transparency data, we prefer to
6090 construct a clipping mask. */
6091 if (fn_png_get_valid (png_ptr
, info_ptr
, PNG_INFO_tRNS
))
6096 /* This function is easier to write if we only have to handle
6097 one data format: RGB or RGBA with 8 bits per channel. Let's
6098 transform other formats into that format. */
6100 /* Strip more than 8 bits per channel. */
6101 if (bit_depth
== 16)
6102 fn_png_set_strip_16 (png_ptr
);
6104 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6106 fn_png_set_expand (png_ptr
);
6108 /* Convert grayscale images to RGB. */
6109 if (color_type
== PNG_COLOR_TYPE_GRAY
6110 || color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6111 fn_png_set_gray_to_rgb (png_ptr
);
6113 /* Handle alpha channel by combining the image with a background
6114 color. Do this only if a real alpha channel is supplied. For
6115 simple transparency, we prefer a clipping mask. */
6118 /* png_color_16 *image_bg; */
6119 Lisp_Object specified_bg
6120 = image_spec_value (img
->spec
, QCbackground
, NULL
);
6121 int shift
= (bit_depth
== 16) ? 0 : 8;
6123 if (STRINGP (specified_bg
))
6124 /* The user specified `:background', use that. */
6126 /* W32 version incorrectly used COLORREF here!! ++kfs */
6128 if (x_defined_color (f
, SDATA (specified_bg
), &color
, 0))
6130 png_color_16 user_bg
;
6132 bzero (&user_bg
, sizeof user_bg
);
6133 user_bg
.red
= color
.red
>> shift
;
6134 user_bg
.green
= color
.green
>> shift
;
6135 user_bg
.blue
= color
.blue
>> shift
;
6137 fn_png_set_background (png_ptr
, &user_bg
,
6138 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6143 /* We use the current frame background, ignoring any default
6144 background color set by the image. */
6145 #ifdef HAVE_X_WINDOWS
6147 png_color_16 frame_background
;
6149 color
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
6150 x_query_color (f
, &color
);
6152 bzero (&frame_background
, sizeof frame_background
);
6153 frame_background
.red
= color
.red
>> shift
;
6154 frame_background
.green
= color
.green
>> shift
;
6155 frame_background
.blue
= color
.blue
>> shift
;
6156 #endif /* HAVE_X_WINDOWS */
6160 png_color_16 frame_background
;
6161 color
= FRAME_BACKGROUND_PIXEL (f
);
6162 #if 0 /* W32 TODO : Colormap support. */
6163 x_query_color (f
, &color
);
6165 bzero (&frame_background
, sizeof frame_background
);
6166 frame_background
.red
= GetRValue (color
);
6167 frame_background
.green
= GetGValue (color
);
6168 frame_background
.blue
= GetBValue (color
);
6169 #endif /* HAVE_NTGUI */
6171 fn_png_set_background (png_ptr
, &frame_background
,
6172 PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
6176 /* Update info structure. */
6177 fn_png_read_update_info (png_ptr
, info_ptr
);
6179 /* Get number of channels. Valid values are 1 for grayscale images
6180 and images with a palette, 2 for grayscale images with transparency
6181 information (alpha channel), 3 for RGB images, and 4 for RGB
6182 images with alpha channel, i.e. RGBA. If conversions above were
6183 sufficient we should only have 3 or 4 channels here. */
6184 channels
= fn_png_get_channels (png_ptr
, info_ptr
);
6185 xassert (channels
== 3 || channels
== 4);
6187 /* Number of bytes needed for one row of the image. */
6188 row_bytes
= fn_png_get_rowbytes (png_ptr
, info_ptr
);
6190 /* Allocate memory for the image. */
6191 pixels
= (png_byte
*) xmalloc (row_bytes
* height
* sizeof *pixels
);
6192 rows
= (png_byte
**) xmalloc (height
* sizeof *rows
);
6193 for (i
= 0; i
< height
; ++i
)
6194 rows
[i
] = pixels
+ i
* row_bytes
;
6196 /* Read the entire image. */
6197 fn_png_read_image (png_ptr
, rows
);
6198 fn_png_read_end (png_ptr
, info_ptr
);
6205 /* Create the X image and pixmap. */
6206 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
,
6210 /* Create an image and pixmap serving as mask if the PNG image
6211 contains an alpha channel. */
6214 && !x_create_x_image_and_pixmap (f
, width
, height
, 1,
6215 &mask_img
, &img
->mask
))
6217 x_destroy_x_image (ximg
);
6218 Free_Pixmap (FRAME_X_DISPLAY (f
), img
->pixmap
);
6219 img
->pixmap
= NO_PIXMAP
;
6223 /* Fill the X image and mask from PNG data. */
6224 init_color_table ();
6226 for (y
= 0; y
< height
; ++y
)
6228 png_byte
*p
= rows
[y
];
6230 for (x
= 0; x
< width
; ++x
)
6237 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, r
, g
, b
));
6238 /* An alpha channel, aka mask channel, associates variable
6239 transparency with an image. Where other image formats
6240 support binary transparency---fully transparent or fully
6241 opaque---PNG allows up to 254 levels of partial transparency.
6242 The PNG library implements partial transparency by combining
6243 the image with a specified background color.
6245 I'm not sure how to handle this here nicely: because the
6246 background on which the image is displayed may change, for
6247 real alpha channel support, it would be necessary to create
6248 a new image for each possible background.
6250 What I'm doing now is that a mask is created if we have
6251 boolean transparency information. Otherwise I'm using
6252 the frame's background color to combine the image with. */
6257 XPutPixel (mask_img
, x
, y
, *p
> 0 ? PIX_MASK_DRAW
: PIX_MASK_RETAIN
);
6263 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6264 /* Set IMG's background color from the PNG image, unless the user
6268 if (fn_png_get_bKGD (png_ptr
, info_ptr
, &bg
))
6270 img
->background
= lookup_rgb_color (f
, bg
->red
, bg
->green
, bg
->blue
);
6271 img
->background_valid
= 1;
6275 #ifdef COLOR_TABLE_SUPPORT
6276 /* Remember colors allocated for this image. */
6277 img
->colors
= colors_in_color_table (&img
->ncolors
);
6278 free_color_table ();
6279 #endif /* COLOR_TABLE_SUPPORT */
6282 fn_png_destroy_read_struct (&png_ptr
, &info_ptr
, &end_info
);
6287 img
->height
= height
;
6289 /* Maybe fill in the background field while we have ximg handy.
6290 Casting avoids a GCC warning. */
6291 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6293 /* Put the image into the pixmap, then free the X image and its buffer. */
6294 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6295 x_destroy_x_image (ximg
);
6297 /* Same for the mask. */
6300 /* Fill in the background_transparent field while we have the
6301 mask handy. Casting avoids a GCC warning. */
6302 image_background_transparent (img
, f
, (XImagePtr_or_DC
)mask_img
);
6304 x_put_x_image (f
, mask_img
, img
->mask
, img
->width
, img
->height
);
6305 x_destroy_x_image (mask_img
);
6312 #else /* HAVE_PNG */
6316 png_load (struct frame
*f
, struct image
*img
)
6318 return ns_load_image(f
, img
,
6319 image_spec_value (img
->spec
, QCfile
, NULL
),
6320 image_spec_value (img
->spec
, QCdata
, NULL
));
6322 #endif /* HAVE_NS */
6325 #endif /* !HAVE_PNG */
6329 /***********************************************************************
6331 ***********************************************************************/
6333 #if defined (HAVE_JPEG) || defined (HAVE_NS)
6335 static int jpeg_image_p
P_ ((Lisp_Object object
));
6336 static int jpeg_load
P_ ((struct frame
*f
, struct image
*img
));
6338 /* The symbol `jpeg' identifying images of this type. */
6342 /* Indices of image specification fields in gs_format, below. */
6344 enum jpeg_keyword_index
6353 JPEG_HEURISTIC_MASK
,
6359 /* Vector of image_keyword structures describing the format
6360 of valid user-defined image specifications. */
6362 static struct image_keyword jpeg_format
[JPEG_LAST
] =
6364 {":type", IMAGE_SYMBOL_VALUE
, 1},
6365 {":data", IMAGE_STRING_VALUE
, 0},
6366 {":file", IMAGE_STRING_VALUE
, 0},
6367 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6368 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6369 {":relief", IMAGE_INTEGER_VALUE
, 0},
6370 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6371 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6372 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6373 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
6376 /* Structure describing the image type `jpeg'. */
6378 static struct image_type jpeg_type
=
6387 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6390 jpeg_image_p (object
)
6393 struct image_keyword fmt
[JPEG_LAST
];
6395 bcopy (jpeg_format
, fmt
, sizeof fmt
);
6397 if (!parse_image_spec (object
, fmt
, JPEG_LAST
, Qjpeg
))
6400 /* Must specify either the :data or :file keyword. */
6401 return fmt
[JPEG_FILE
].count
+ fmt
[JPEG_DATA
].count
== 1;
6404 #endif /* HAVE_JPEG || HAVE_NS */
6408 /* Work around a warning about HAVE_STDLIB_H being redefined in
6410 #ifdef HAVE_STDLIB_H
6411 #define HAVE_STDLIB_H_1
6412 #undef HAVE_STDLIB_H
6413 #endif /* HAVE_STLIB_H */
6415 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6416 /* In older releases of the jpeg library, jpeglib.h will define boolean
6417 differently depending on __WIN32__, so make sure it is defined. */
6421 #include <jpeglib.h>
6425 #ifdef HAVE_STLIB_H_1
6426 #define HAVE_STDLIB_H 1
6431 /* JPEG library details. */
6432 DEF_IMGLIB_FN (jpeg_CreateDecompress
);
6433 DEF_IMGLIB_FN (jpeg_start_decompress
);
6434 DEF_IMGLIB_FN (jpeg_finish_decompress
);
6435 DEF_IMGLIB_FN (jpeg_destroy_decompress
);
6436 DEF_IMGLIB_FN (jpeg_read_header
);
6437 DEF_IMGLIB_FN (jpeg_read_scanlines
);
6438 DEF_IMGLIB_FN (jpeg_std_error
);
6439 DEF_IMGLIB_FN (jpeg_resync_to_restart
);
6442 init_jpeg_functions (Lisp_Object libraries
)
6446 if (!(library
= w32_delayed_load (libraries
, Qjpeg
)))
6449 LOAD_IMGLIB_FN (library
, jpeg_finish_decompress
);
6450 LOAD_IMGLIB_FN (library
, jpeg_read_scanlines
);
6451 LOAD_IMGLIB_FN (library
, jpeg_start_decompress
);
6452 LOAD_IMGLIB_FN (library
, jpeg_read_header
);
6453 LOAD_IMGLIB_FN (library
, jpeg_CreateDecompress
);
6454 LOAD_IMGLIB_FN (library
, jpeg_destroy_decompress
);
6455 LOAD_IMGLIB_FN (library
, jpeg_std_error
);
6456 LOAD_IMGLIB_FN (library
, jpeg_resync_to_restart
);
6460 /* Wrapper since we can't directly assign the function pointer
6461 to another function pointer that was declared more completely easily. */
6463 jpeg_resync_to_restart_wrapper (cinfo
, desired
)
6464 j_decompress_ptr cinfo
;
6467 return fn_jpeg_resync_to_restart (cinfo
, desired
);
6472 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6473 #define fn_jpeg_start_decompress jpeg_start_decompress
6474 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6475 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6476 #define fn_jpeg_read_header jpeg_read_header
6477 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6478 #define fn_jpeg_std_error jpeg_std_error
6479 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6481 #endif /* HAVE_NTGUI */
6483 struct my_jpeg_error_mgr
6485 struct jpeg_error_mgr pub
;
6486 jmp_buf setjmp_buffer
;
6491 my_error_exit (cinfo
)
6494 struct my_jpeg_error_mgr
*mgr
= (struct my_jpeg_error_mgr
*) cinfo
->err
;
6495 longjmp (mgr
->setjmp_buffer
, 1);
6499 /* Init source method for JPEG data source manager. Called by
6500 jpeg_read_header() before any data is actually read. See
6501 libjpeg.doc from the JPEG lib distribution. */
6504 our_common_init_source (cinfo
)
6505 j_decompress_ptr cinfo
;
6510 /* Method to terminate data source. Called by
6511 jpeg_finish_decompress() after all data has been processed. */
6514 our_common_term_source (cinfo
)
6515 j_decompress_ptr cinfo
;
6520 /* Fill input buffer method for JPEG data source manager. Called
6521 whenever more data is needed. We read the whole image in one step,
6522 so this only adds a fake end of input marker at the end. */
6524 static JOCTET our_memory_buffer
[2];
6527 our_memory_fill_input_buffer (cinfo
)
6528 j_decompress_ptr cinfo
;
6530 /* Insert a fake EOI marker. */
6531 struct jpeg_source_mgr
*src
= cinfo
->src
;
6533 our_memory_buffer
[0] = (JOCTET
) 0xFF;
6534 our_memory_buffer
[1] = (JOCTET
) JPEG_EOI
;
6536 src
->next_input_byte
= our_memory_buffer
;
6537 src
->bytes_in_buffer
= 2;
6542 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6543 is the JPEG data source manager. */
6546 our_memory_skip_input_data (cinfo
, num_bytes
)
6547 j_decompress_ptr cinfo
;
6550 struct jpeg_source_mgr
*src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6554 if (num_bytes
> src
->bytes_in_buffer
)
6555 ERREXIT (cinfo
, JERR_INPUT_EOF
);
6557 src
->bytes_in_buffer
-= num_bytes
;
6558 src
->next_input_byte
+= num_bytes
;
6563 /* Set up the JPEG lib for reading an image from DATA which contains
6564 LEN bytes. CINFO is the decompression info structure created for
6565 reading the image. */
6568 jpeg_memory_src (cinfo
, data
, len
)
6569 j_decompress_ptr cinfo
;
6573 struct jpeg_source_mgr
*src
;
6575 if (cinfo
->src
== NULL
)
6577 /* First time for this JPEG object? */
6578 cinfo
->src
= (struct jpeg_source_mgr
*)
6579 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6580 sizeof (struct jpeg_source_mgr
));
6581 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6582 src
->next_input_byte
= data
;
6585 src
= (struct jpeg_source_mgr
*) cinfo
->src
;
6586 src
->init_source
= our_common_init_source
;
6587 src
->fill_input_buffer
= our_memory_fill_input_buffer
;
6588 src
->skip_input_data
= our_memory_skip_input_data
;
6589 src
->resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6590 src
->term_source
= our_common_term_source
;
6591 src
->bytes_in_buffer
= len
;
6592 src
->next_input_byte
= data
;
6596 struct jpeg_stdio_mgr
6598 struct jpeg_source_mgr mgr
;
6605 /* Size of buffer to read JPEG from file.
6606 Not too big, as we want to use alloc_small. */
6607 #define JPEG_STDIO_BUFFER_SIZE 8192
6610 /* Fill input buffer method for JPEG data source manager. Called
6611 whenever more data is needed. The data is read from a FILE *. */
6614 our_stdio_fill_input_buffer (cinfo
)
6615 j_decompress_ptr cinfo
;
6617 struct jpeg_stdio_mgr
*src
;
6619 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6624 bytes
= fread (src
->buffer
, 1, JPEG_STDIO_BUFFER_SIZE
, src
->file
);
6626 src
->mgr
.bytes_in_buffer
= bytes
;
6629 WARNMS (cinfo
, JWRN_JPEG_EOF
);
6631 src
->buffer
[0] = (JOCTET
) 0xFF;
6632 src
->buffer
[1] = (JOCTET
) JPEG_EOI
;
6633 src
->mgr
.bytes_in_buffer
= 2;
6635 src
->mgr
.next_input_byte
= src
->buffer
;
6642 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6643 is the JPEG data source manager. */
6646 our_stdio_skip_input_data (cinfo
, num_bytes
)
6647 j_decompress_ptr cinfo
;
6650 struct jpeg_stdio_mgr
*src
;
6651 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6653 while (num_bytes
> 0 && !src
->finished
)
6655 if (num_bytes
<= src
->mgr
.bytes_in_buffer
)
6657 src
->mgr
.bytes_in_buffer
-= num_bytes
;
6658 src
->mgr
.next_input_byte
+= num_bytes
;
6663 num_bytes
-= src
->mgr
.bytes_in_buffer
;
6664 src
->mgr
.bytes_in_buffer
= 0;
6665 src
->mgr
.next_input_byte
= NULL
;
6667 our_stdio_fill_input_buffer (cinfo
);
6673 /* Set up the JPEG lib for reading an image from a FILE *.
6674 CINFO is the decompression info structure created for
6675 reading the image. */
6678 jpeg_file_src (cinfo
, fp
)
6679 j_decompress_ptr cinfo
;
6682 struct jpeg_stdio_mgr
*src
;
6684 if (cinfo
->src
!= NULL
)
6685 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6688 /* First time for this JPEG object? */
6689 cinfo
->src
= (struct jpeg_source_mgr
*)
6690 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6691 sizeof (struct jpeg_stdio_mgr
));
6692 src
= (struct jpeg_stdio_mgr
*) cinfo
->src
;
6693 src
->buffer
= (JOCTET
*)
6694 (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
,
6695 JPEG_STDIO_BUFFER_SIZE
);
6700 src
->mgr
.init_source
= our_common_init_source
;
6701 src
->mgr
.fill_input_buffer
= our_stdio_fill_input_buffer
;
6702 src
->mgr
.skip_input_data
= our_stdio_skip_input_data
;
6703 src
->mgr
.resync_to_restart
= jpeg_resync_to_restart_wrapper
; /* Use default method. */
6704 src
->mgr
.term_source
= our_common_term_source
;
6705 src
->mgr
.bytes_in_buffer
= 0;
6706 src
->mgr
.next_input_byte
= NULL
;
6710 /* Load image IMG for use on frame F. Patterned after example.c
6711 from the JPEG lib. */
6718 struct jpeg_decompress_struct cinfo
;
6719 struct my_jpeg_error_mgr mgr
;
6720 Lisp_Object file
, specified_file
;
6721 Lisp_Object specified_data
;
6722 FILE * volatile fp
= NULL
;
6724 int row_stride
, x
, y
;
6725 XImagePtr ximg
= NULL
;
6727 unsigned long *colors
;
6729 struct gcpro gcpro1
;
6731 /* Open the JPEG file. */
6732 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
6733 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
6737 if (NILP (specified_data
))
6739 file
= x_find_image_file (specified_file
);
6740 if (!STRINGP (file
))
6742 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
6747 fp
= fopen (SDATA (file
), "rb");
6750 image_error ("Cannot open `%s'", file
, Qnil
);
6756 /* Customize libjpeg's error handling to call my_error_exit when an
6757 error is detected. This function will perform a longjmp.
6758 Casting return value avoids a GCC warning on W32. */
6759 cinfo
.err
= (struct jpeg_error_mgr
*)fn_jpeg_std_error (&mgr
.pub
);
6760 mgr
.pub
.error_exit
= my_error_exit
;
6762 if ((rc
= setjmp (mgr
.setjmp_buffer
)) != 0)
6766 /* Called from my_error_exit. Display a JPEG error. */
6767 char buffer
[JMSG_LENGTH_MAX
];
6768 cinfo
.err
->format_message ((j_common_ptr
) &cinfo
, buffer
);
6769 image_error ("Error reading JPEG image `%s': %s", img
->spec
,
6770 build_string (buffer
));
6773 /* Close the input file and destroy the JPEG object. */
6775 fclose ((FILE *) fp
);
6776 fn_jpeg_destroy_decompress (&cinfo
);
6778 /* If we already have an XImage, free that. */
6779 x_destroy_x_image (ximg
);
6781 /* Free pixmap and colors. */
6782 x_clear_image (f
, img
);
6788 /* Create the JPEG decompression object. Let it read from fp.
6789 Read the JPEG image header. */
6790 fn_jpeg_CreateDecompress (&cinfo
, JPEG_LIB_VERSION
, sizeof (cinfo
));
6792 if (NILP (specified_data
))
6793 jpeg_file_src (&cinfo
, (FILE *) fp
);
6795 jpeg_memory_src (&cinfo
, SDATA (specified_data
),
6796 SBYTES (specified_data
));
6798 fn_jpeg_read_header (&cinfo
, 1);
6800 /* Customize decompression so that color quantization will be used.
6801 Start decompression. */
6802 cinfo
.quantize_colors
= 1;
6803 fn_jpeg_start_decompress (&cinfo
);
6804 width
= img
->width
= cinfo
.output_width
;
6805 height
= img
->height
= cinfo
.output_height
;
6807 if (!check_image_size (f
, width
, height
))
6809 image_error ("Invalid image size", Qnil
, Qnil
);
6810 longjmp (mgr
.setjmp_buffer
, 2);
6813 /* Create X image and pixmap. */
6814 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
6815 longjmp (mgr
.setjmp_buffer
, 2);
6817 /* Allocate colors. When color quantization is used,
6818 cinfo.actual_number_of_colors has been set with the number of
6819 colors generated, and cinfo.colormap is a two-dimensional array
6820 of color indices in the range 0..cinfo.actual_number_of_colors.
6821 No more than 255 colors will be generated. */
6825 if (cinfo
.out_color_components
> 2)
6826 ir
= 0, ig
= 1, ib
= 2;
6827 else if (cinfo
.out_color_components
> 1)
6828 ir
= 0, ig
= 1, ib
= 0;
6830 ir
= 0, ig
= 0, ib
= 0;
6832 /* Use the color table mechanism because it handles colors that
6833 cannot be allocated nicely. Such colors will be replaced with
6834 a default color, and we don't have to care about which colors
6835 can be freed safely, and which can't. */
6836 init_color_table ();
6837 colors
= (unsigned long *) alloca (cinfo
.actual_number_of_colors
6840 for (i
= 0; i
< cinfo
.actual_number_of_colors
; ++i
)
6842 /* Multiply RGB values with 255 because X expects RGB values
6843 in the range 0..0xffff. */
6844 int r
= cinfo
.colormap
[ir
][i
] << 8;
6845 int g
= cinfo
.colormap
[ig
][i
] << 8;
6846 int b
= cinfo
.colormap
[ib
][i
] << 8;
6847 colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
6850 #ifdef COLOR_TABLE_SUPPORT
6851 /* Remember those colors actually allocated. */
6852 img
->colors
= colors_in_color_table (&img
->ncolors
);
6853 free_color_table ();
6854 #endif /* COLOR_TABLE_SUPPORT */
6858 row_stride
= width
* cinfo
.output_components
;
6859 buffer
= cinfo
.mem
->alloc_sarray ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
,
6861 for (y
= 0; y
< height
; ++y
)
6863 fn_jpeg_read_scanlines (&cinfo
, buffer
, 1);
6864 for (x
= 0; x
< cinfo
.output_width
; ++x
)
6865 XPutPixel (ximg
, x
, y
, colors
[buffer
[0][x
]]);
6869 fn_jpeg_finish_decompress (&cinfo
);
6870 fn_jpeg_destroy_decompress (&cinfo
);
6872 fclose ((FILE *) fp
);
6874 /* Maybe fill in the background field while we have ximg handy. */
6875 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
6876 /* Casting avoids a GCC warning. */
6877 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
6879 /* Put the image into the pixmap. */
6880 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
6881 x_destroy_x_image (ximg
);
6886 #else /* HAVE_JPEG */
6890 jpeg_load (struct frame
*f
, struct image
*img
)
6892 return ns_load_image(f
, img
,
6893 image_spec_value (img
->spec
, QCfile
, NULL
),
6894 image_spec_value (img
->spec
, QCdata
, NULL
));
6896 #endif /* HAVE_NS */
6898 #endif /* !HAVE_JPEG */
6902 /***********************************************************************
6904 ***********************************************************************/
6906 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6908 static int tiff_image_p
P_ ((Lisp_Object object
));
6909 static int tiff_load
P_ ((struct frame
*f
, struct image
*img
));
6911 /* The symbol `tiff' identifying images of this type. */
6915 /* Indices of image specification fields in tiff_format, below. */
6917 enum tiff_keyword_index
6926 TIFF_HEURISTIC_MASK
,
6933 /* Vector of image_keyword structures describing the format
6934 of valid user-defined image specifications. */
6936 static struct image_keyword tiff_format
[TIFF_LAST
] =
6938 {":type", IMAGE_SYMBOL_VALUE
, 1},
6939 {":data", IMAGE_STRING_VALUE
, 0},
6940 {":file", IMAGE_STRING_VALUE
, 0},
6941 {":ascent", IMAGE_ASCENT_VALUE
, 0},
6942 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
6943 {":relief", IMAGE_INTEGER_VALUE
, 0},
6944 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6945 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6946 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
6947 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0},
6948 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0}
6951 /* Structure describing the image type `tiff'. */
6953 static struct image_type tiff_type
=
6962 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6965 tiff_image_p (object
)
6968 struct image_keyword fmt
[TIFF_LAST
];
6969 bcopy (tiff_format
, fmt
, sizeof fmt
);
6971 if (!parse_image_spec (object
, fmt
, TIFF_LAST
, Qtiff
))
6974 /* Must specify either the :data or :file keyword. */
6975 return fmt
[TIFF_FILE
].count
+ fmt
[TIFF_DATA
].count
== 1;
6978 #endif /* HAVE_TIFF || HAVE_NS */
6986 /* TIFF library details. */
6987 DEF_IMGLIB_FN (TIFFSetErrorHandler
);
6988 DEF_IMGLIB_FN (TIFFSetWarningHandler
);
6989 DEF_IMGLIB_FN (TIFFOpen
);
6990 DEF_IMGLIB_FN (TIFFClientOpen
);
6991 DEF_IMGLIB_FN (TIFFGetField
);
6992 DEF_IMGLIB_FN (TIFFReadRGBAImage
);
6993 DEF_IMGLIB_FN (TIFFClose
);
6994 DEF_IMGLIB_FN (TIFFSetDirectory
);
6997 init_tiff_functions (Lisp_Object libraries
)
7001 if (!(library
= w32_delayed_load (libraries
, Qtiff
)))
7004 LOAD_IMGLIB_FN (library
, TIFFSetErrorHandler
);
7005 LOAD_IMGLIB_FN (library
, TIFFSetWarningHandler
);
7006 LOAD_IMGLIB_FN (library
, TIFFOpen
);
7007 LOAD_IMGLIB_FN (library
, TIFFClientOpen
);
7008 LOAD_IMGLIB_FN (library
, TIFFGetField
);
7009 LOAD_IMGLIB_FN (library
, TIFFReadRGBAImage
);
7010 LOAD_IMGLIB_FN (library
, TIFFClose
);
7011 LOAD_IMGLIB_FN (library
, TIFFSetDirectory
);
7017 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7018 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7019 #define fn_TIFFOpen TIFFOpen
7020 #define fn_TIFFClientOpen TIFFClientOpen
7021 #define fn_TIFFGetField TIFFGetField
7022 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7023 #define fn_TIFFClose TIFFClose
7024 #define fn_TIFFSetDirectory TIFFSetDirectory
7025 #endif /* HAVE_NTGUI */
7028 /* Reading from a memory buffer for TIFF images Based on the PNG
7029 memory source, but we have to provide a lot of extra functions.
7032 We really only need to implement read and seek, but I am not
7033 convinced that the TIFF library is smart enough not to destroy
7034 itself if we only hand it the function pointers we need to
7039 unsigned char *bytes
;
7046 tiff_read_from_memory (data
, buf
, size
)
7051 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7053 if (size
> src
->len
- src
->index
)
7055 bcopy (src
->bytes
+ src
->index
, buf
, size
);
7061 tiff_write_from_memory (data
, buf
, size
)
7070 tiff_seek_in_memory (data
, off
, whence
)
7075 tiff_memory_source
*src
= (tiff_memory_source
*) data
;
7080 case SEEK_SET
: /* Go from beginning of source. */
7084 case SEEK_END
: /* Go from end of source. */
7085 idx
= src
->len
+ off
;
7088 case SEEK_CUR
: /* Go from current position. */
7089 idx
= src
->index
+ off
;
7092 default: /* Invalid `whence'. */
7096 if (idx
> src
->len
|| idx
< 0)
7104 tiff_close_memory (data
)
7112 tiff_mmap_memory (data
, pbase
, psize
)
7117 /* It is already _IN_ memory. */
7122 tiff_unmap_memory (data
, base
, size
)
7127 /* We don't need to do this. */
7131 tiff_size_of_memory (data
)
7134 return ((tiff_memory_source
*) data
)->len
;
7139 tiff_error_handler (title
, format
, ap
)
7140 const char *title
, *format
;
7146 len
= sprintf (buf
, "TIFF error: %s ", title
);
7147 vsprintf (buf
+ len
, format
, ap
);
7148 add_to_log (buf
, Qnil
, Qnil
);
7153 tiff_warning_handler (title
, format
, ap
)
7154 const char *title
, *format
;
7160 len
= sprintf (buf
, "TIFF warning: %s ", title
);
7161 vsprintf (buf
+ len
, format
, ap
);
7162 add_to_log (buf
, Qnil
, Qnil
);
7166 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7174 Lisp_Object file
, specified_file
;
7175 Lisp_Object specified_data
;
7177 int width
, height
, x
, y
, count
;
7181 struct gcpro gcpro1
;
7182 tiff_memory_source memsrc
;
7185 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7186 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7190 fn_TIFFSetErrorHandler (tiff_error_handler
);
7191 fn_TIFFSetWarningHandler (tiff_warning_handler
);
7193 if (NILP (specified_data
))
7195 /* Read from a file */
7196 file
= x_find_image_file (specified_file
);
7197 if (!STRINGP (file
))
7199 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7204 /* Try to open the image file. Casting return value avoids a
7205 GCC warning on W32. */
7206 tiff
= (TIFF
*)fn_TIFFOpen (SDATA (file
), "r");
7209 image_error ("Cannot open `%s'", file
, Qnil
);
7216 /* Memory source! */
7217 memsrc
.bytes
= SDATA (specified_data
);
7218 memsrc
.len
= SBYTES (specified_data
);
7221 /* Casting return value avoids a GCC warning on W32. */
7222 tiff
= (TIFF
*)fn_TIFFClientOpen ("memory_source", "r", &memsrc
,
7223 (TIFFReadWriteProc
) tiff_read_from_memory
,
7224 (TIFFReadWriteProc
) tiff_write_from_memory
,
7225 tiff_seek_in_memory
,
7227 tiff_size_of_memory
,
7233 image_error ("Cannot open memory source for `%s'", img
->spec
, Qnil
);
7239 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7240 if (INTEGERP (image
))
7242 int ino
= XFASTINT (image
);
7243 if (!fn_TIFFSetDirectory (tiff
, ino
))
7245 image_error ("Invalid image number `%s' in image `%s'",
7247 fn_TIFFClose (tiff
);
7253 /* Get width and height of the image, and allocate a raster buffer
7254 of width x height 32-bit values. */
7255 fn_TIFFGetField (tiff
, TIFFTAG_IMAGEWIDTH
, &width
);
7256 fn_TIFFGetField (tiff
, TIFFTAG_IMAGELENGTH
, &height
);
7258 if (!check_image_size (f
, width
, height
))
7260 image_error ("Invalid image size", Qnil
, Qnil
);
7261 fn_TIFFClose (tiff
);
7266 buf
= (uint32
*) xmalloc (width
* height
* sizeof *buf
);
7268 rc
= fn_TIFFReadRGBAImage (tiff
, width
, height
, buf
, 0);
7270 /* Count the number of images in the file. */
7271 for (count
= 1, rc2
= 1; rc2
; count
++)
7272 rc2
= fn_TIFFSetDirectory (tiff
, count
);
7275 img
->data
.lisp_val
= Fcons (Qcount
,
7276 Fcons (make_number (count
),
7277 img
->data
.lisp_val
));
7279 fn_TIFFClose (tiff
);
7282 image_error ("Error reading TIFF image `%s'", img
->spec
, Qnil
);
7288 /* Create the X image and pixmap. */
7289 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7296 /* Initialize the color table. */
7297 init_color_table ();
7299 /* Process the pixel raster. Origin is in the lower-left corner. */
7300 for (y
= 0; y
< height
; ++y
)
7302 uint32
*row
= buf
+ y
* width
;
7304 for (x
= 0; x
< width
; ++x
)
7306 uint32 abgr
= row
[x
];
7307 int r
= TIFFGetR (abgr
) << 8;
7308 int g
= TIFFGetG (abgr
) << 8;
7309 int b
= TIFFGetB (abgr
) << 8;
7310 XPutPixel (ximg
, x
, height
- 1 - y
, lookup_rgb_color (f
, r
, g
, b
));
7314 #ifdef COLOR_TABLE_SUPPORT
7315 /* Remember the colors allocated for the image. Free the color table. */
7316 img
->colors
= colors_in_color_table (&img
->ncolors
);
7317 free_color_table ();
7318 #endif /* COLOR_TABLE_SUPPORT */
7321 img
->height
= height
;
7323 /* Maybe fill in the background field while we have ximg handy. */
7324 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7325 /* Casting avoids a GCC warning on W32. */
7326 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7328 /* Put the image into the pixmap, then free the X image and its buffer. */
7329 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7330 x_destroy_x_image (ximg
);
7337 #else /* HAVE_TIFF */
7341 tiff_load (struct frame
*f
, struct image
*img
)
7343 return ns_load_image(f
, img
,
7344 image_spec_value (img
->spec
, QCfile
, NULL
),
7345 image_spec_value (img
->spec
, QCdata
, NULL
));
7347 #endif /* HAVE_NS */
7349 #endif /* !HAVE_TIFF */
7353 /***********************************************************************
7355 ***********************************************************************/
7357 #if defined (HAVE_GIF) || defined (HAVE_NS)
7359 static int gif_image_p
P_ ((Lisp_Object object
));
7360 static int gif_load
P_ ((struct frame
*f
, struct image
*img
));
7361 static void gif_clear_image
P_ ((struct frame
*f
, struct image
*img
));
7363 /* The symbol `gif' identifying images of this type. */
7367 /* Indices of image specification fields in gif_format, below. */
7369 enum gif_keyword_index
7385 /* Vector of image_keyword structures describing the format
7386 of valid user-defined image specifications. */
7388 static struct image_keyword gif_format
[GIF_LAST
] =
7390 {":type", IMAGE_SYMBOL_VALUE
, 1},
7391 {":data", IMAGE_STRING_VALUE
, 0},
7392 {":file", IMAGE_STRING_VALUE
, 0},
7393 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7394 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7395 {":relief", IMAGE_INTEGER_VALUE
, 0},
7396 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7397 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7398 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7399 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE
, 0},
7400 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7403 /* Structure describing the image type `gif'. */
7405 static struct image_type gif_type
=
7414 /* Free X resources of GIF image IMG which is used on frame F. */
7417 gif_clear_image (f
, img
)
7421 /* IMG->data.ptr_val may contain extension data. */
7422 img
->data
.lisp_val
= Qnil
;
7423 x_clear_image (f
, img
);
7426 /* Return non-zero if OBJECT is a valid GIF image specification. */
7429 gif_image_p (object
)
7432 struct image_keyword fmt
[GIF_LAST
];
7433 bcopy (gif_format
, fmt
, sizeof fmt
);
7435 if (!parse_image_spec (object
, fmt
, GIF_LAST
, Qgif
))
7438 /* Must specify either the :data or :file keyword. */
7439 return fmt
[GIF_FILE
].count
+ fmt
[GIF_DATA
].count
== 1;
7442 #endif /* HAVE_GIF */
7446 #if defined (HAVE_NTGUI)
7447 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7448 Undefine before redefining to avoid a preprocessor warning. */
7452 /* avoid conflict with QuickdrawText.h */
7453 #define DrawText gif_DrawText
7454 #include <gif_lib.h>
7457 #else /* HAVE_NTGUI */
7459 #include <gif_lib.h>
7461 #endif /* HAVE_NTGUI */
7466 /* GIF library details. */
7467 DEF_IMGLIB_FN (DGifCloseFile
);
7468 DEF_IMGLIB_FN (DGifSlurp
);
7469 DEF_IMGLIB_FN (DGifOpen
);
7470 DEF_IMGLIB_FN (DGifOpenFileName
);
7473 init_gif_functions (Lisp_Object libraries
)
7477 if (!(library
= w32_delayed_load (libraries
, Qgif
)))
7480 LOAD_IMGLIB_FN (library
, DGifCloseFile
);
7481 LOAD_IMGLIB_FN (library
, DGifSlurp
);
7482 LOAD_IMGLIB_FN (library
, DGifOpen
);
7483 LOAD_IMGLIB_FN (library
, DGifOpenFileName
);
7489 #define fn_DGifCloseFile DGifCloseFile
7490 #define fn_DGifSlurp DGifSlurp
7491 #define fn_DGifOpen DGifOpen
7492 #define fn_DGifOpenFileName DGifOpenFileName
7494 #endif /* HAVE_NTGUI */
7496 /* Reading a GIF image from memory
7497 Based on the PNG memory stuff to a certain extent. */
7501 unsigned char *bytes
;
7507 /* Make the current memory source available to gif_read_from_memory.
7508 It's done this way because not all versions of libungif support
7509 a UserData field in the GifFileType structure. */
7510 static gif_memory_source
*current_gif_memory_src
;
7513 gif_read_from_memory (file
, buf
, len
)
7518 gif_memory_source
*src
= current_gif_memory_src
;
7520 if (len
> src
->len
- src
->index
)
7523 bcopy (src
->bytes
+ src
->index
, buf
, len
);
7529 /* Load GIF image IMG for use on frame F. Value is non-zero if
7532 static int interlace_start
[] = {0, 4, 2, 1};
7533 static int interlace_increment
[] = {8, 8, 4, 2};
7540 Lisp_Object file
, specified_file
;
7541 Lisp_Object specified_data
;
7542 int rc
, width
, height
, x
, y
, i
;
7544 ColorMapObject
*gif_color_map
;
7545 unsigned long pixel_colors
[256];
7547 struct gcpro gcpro1
;
7549 int ino
, image_height
, image_width
;
7550 gif_memory_source memsrc
;
7551 unsigned char *raster
;
7553 specified_file
= image_spec_value (img
->spec
, QCfile
, NULL
);
7554 specified_data
= image_spec_value (img
->spec
, QCdata
, NULL
);
7558 if (NILP (specified_data
))
7560 file
= x_find_image_file (specified_file
);
7561 if (!STRINGP (file
))
7563 image_error ("Cannot find image file `%s'", specified_file
, Qnil
);
7568 /* Open the GIF file. Casting return value avoids a GCC warning
7570 gif
= (GifFileType
*)fn_DGifOpenFileName (SDATA (file
));
7573 image_error ("Cannot open `%s'", file
, Qnil
);
7580 /* Read from memory! */
7581 current_gif_memory_src
= &memsrc
;
7582 memsrc
.bytes
= SDATA (specified_data
);
7583 memsrc
.len
= SBYTES (specified_data
);
7586 /* Casting return value avoids a GCC warning on W32. */
7587 gif
= (GifFileType
*) fn_DGifOpen (&memsrc
, gif_read_from_memory
);
7590 image_error ("Cannot open memory source `%s'", img
->spec
, Qnil
);
7596 /* Before reading entire contents, check the declared image size. */
7597 if (!check_image_size (f
, gif
->SWidth
, gif
->SHeight
))
7599 image_error ("Invalid image size", Qnil
, Qnil
);
7600 fn_DGifCloseFile (gif
);
7605 /* Read entire contents. */
7606 rc
= fn_DGifSlurp (gif
);
7607 if (rc
== GIF_ERROR
)
7609 image_error ("Error reading `%s'", img
->spec
, Qnil
);
7610 fn_DGifCloseFile (gif
);
7615 image
= image_spec_value (img
->spec
, QCindex
, NULL
);
7616 ino
= INTEGERP (image
) ? XFASTINT (image
) : 0;
7617 if (ino
>= gif
->ImageCount
)
7619 image_error ("Invalid image number `%s' in image `%s'",
7621 fn_DGifCloseFile (gif
);
7626 img
->corners
[TOP_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Top
;
7627 img
->corners
[LEFT_CORNER
] = gif
->SavedImages
[ino
].ImageDesc
.Left
;
7628 image_height
= gif
->SavedImages
[ino
].ImageDesc
.Height
;
7629 img
->corners
[BOT_CORNER
] = img
->corners
[TOP_CORNER
] + image_height
;
7630 image_width
= gif
->SavedImages
[ino
].ImageDesc
.Width
;
7631 img
->corners
[RIGHT_CORNER
] = img
->corners
[LEFT_CORNER
] + image_width
;
7633 width
= img
->width
= max (gif
->SWidth
,
7634 max (gif
->Image
.Left
+ gif
->Image
.Width
,
7635 img
->corners
[RIGHT_CORNER
]));
7636 height
= img
->height
= max (gif
->SHeight
,
7637 max (gif
->Image
.Top
+ gif
->Image
.Height
,
7638 img
->corners
[BOT_CORNER
]));
7640 if (!check_image_size (f
, width
, height
))
7642 image_error ("Invalid image size", Qnil
, Qnil
);
7643 fn_DGifCloseFile (gif
);
7648 /* Create the X image and pixmap. */
7649 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
7651 fn_DGifCloseFile (gif
);
7656 /* Allocate colors. */
7657 gif_color_map
= gif
->SavedImages
[ino
].ImageDesc
.ColorMap
;
7659 gif_color_map
= gif
->SColorMap
;
7660 init_color_table ();
7661 bzero (pixel_colors
, sizeof pixel_colors
);
7664 for (i
= 0; i
< gif_color_map
->ColorCount
; ++i
)
7666 int r
= gif_color_map
->Colors
[i
].Red
<< 8;
7667 int g
= gif_color_map
->Colors
[i
].Green
<< 8;
7668 int b
= gif_color_map
->Colors
[i
].Blue
<< 8;
7669 pixel_colors
[i
] = lookup_rgb_color (f
, r
, g
, b
);
7672 #ifdef COLOR_TABLE_SUPPORT
7673 img
->colors
= colors_in_color_table (&img
->ncolors
);
7674 free_color_table ();
7675 #endif /* COLOR_TABLE_SUPPORT */
7677 /* Clear the part of the screen image that are not covered by
7678 the image from the GIF file. Full animated GIF support
7679 requires more than can be done here (see the gif89 spec,
7680 disposal methods). Let's simply assume that the part
7681 not covered by a sub-image is in the frame's background color. */
7682 for (y
= 0; y
< img
->corners
[TOP_CORNER
]; ++y
)
7683 for (x
= 0; x
< width
; ++x
)
7684 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7686 for (y
= img
->corners
[BOT_CORNER
]; y
< height
; ++y
)
7687 for (x
= 0; x
< width
; ++x
)
7688 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7690 for (y
= img
->corners
[TOP_CORNER
]; y
< img
->corners
[BOT_CORNER
]; ++y
)
7692 for (x
= 0; x
< img
->corners
[LEFT_CORNER
]; ++x
)
7693 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7694 for (x
= img
->corners
[RIGHT_CORNER
]; x
< width
; ++x
)
7695 XPutPixel (ximg
, x
, y
, FRAME_BACKGROUND_PIXEL (f
));
7698 /* Read the GIF image into the X image. We use a local variable
7699 `raster' here because RasterBits below is a char *, and invites
7700 problems with bytes >= 0x80. */
7701 raster
= (unsigned char *) gif
->SavedImages
[ino
].RasterBits
;
7703 if (gif
->SavedImages
[ino
].ImageDesc
.Interlace
)
7706 int row
= interlace_start
[0];
7710 for (y
= 0; y
< image_height
; y
++)
7712 if (row
>= image_height
)
7714 row
= interlace_start
[++pass
];
7715 while (row
>= image_height
)
7716 row
= interlace_start
[++pass
];
7719 for (x
= 0; x
< image_width
; x
++)
7721 int i
= raster
[(y
* image_width
) + x
];
7722 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7723 row
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7726 row
+= interlace_increment
[pass
];
7731 for (y
= 0; y
< image_height
; ++y
)
7732 for (x
= 0; x
< image_width
; ++x
)
7734 int i
= raster
[y
* image_width
+ x
];
7735 XPutPixel (ximg
, x
+ img
->corners
[LEFT_CORNER
],
7736 y
+ img
->corners
[TOP_CORNER
], pixel_colors
[i
]);
7740 /* Save GIF image extension data for `image-extension-data'.
7741 Format is (count IMAGES FUNCTION "BYTES" ...). */
7742 img
->data
.lisp_val
= Qnil
;
7743 if (gif
->SavedImages
[ino
].ExtensionBlockCount
> 0)
7745 ExtensionBlock
*ext
= gif
->SavedImages
[ino
].ExtensionBlocks
;
7746 for (i
= 0; i
< gif
->SavedImages
[ino
].ExtensionBlockCount
; i
++, ext
++)
7747 /* Append (... FUNCTION "BYTES") */
7748 img
->data
.lisp_val
= Fcons (make_unibyte_string (ext
->Bytes
, ext
->ByteCount
),
7749 Fcons (make_number (ext
->Function
),
7750 img
->data
.lisp_val
));
7751 img
->data
.lisp_val
= Fnreverse (img
->data
.lisp_val
);
7753 if (gif
->ImageCount
> 1)
7754 img
->data
.lisp_val
= Fcons (Qcount
,
7755 Fcons (make_number (gif
->ImageCount
),
7756 img
->data
.lisp_val
));
7758 fn_DGifCloseFile (gif
);
7760 /* Maybe fill in the background field while we have ximg handy. */
7761 if (NILP (image_spec_value (img
->spec
, QCbackground
, NULL
)))
7762 /* Casting avoids a GCC warning. */
7763 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
7765 /* Put the image into the pixmap, then free the X image and its buffer. */
7766 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
7767 x_destroy_x_image (ximg
);
7773 #else /* !HAVE_GIF */
7777 gif_load (struct frame
*f
, struct image
*img
)
7779 return ns_load_image(f
, img
,
7780 image_spec_value (img
->spec
, QCfile
, NULL
),
7781 image_spec_value (img
->spec
, QCdata
, NULL
));
7783 #endif /* HAVE_NS */
7785 #endif /* HAVE_GIF */
7789 /***********************************************************************
7791 ***********************************************************************/
7793 #if defined (HAVE_RSVG)
7795 /* Function prototypes. */
7797 static int svg_image_p
P_ ((Lisp_Object object
));
7798 static int svg_load
P_ ((struct frame
*f
, struct image
*img
));
7800 static int svg_load_image
P_ ((struct frame
*, struct image
*,
7801 unsigned char *, unsigned int));
7803 /* The symbol `svg' identifying images of this type. */
7807 /* Indices of image specification fields in svg_format, below. */
7809 enum svg_keyword_index
7824 /* Vector of image_keyword structures describing the format
7825 of valid user-defined image specifications. */
7827 static struct image_keyword svg_format
[SVG_LAST
] =
7829 {":type", IMAGE_SYMBOL_VALUE
, 1},
7830 {":data", IMAGE_STRING_VALUE
, 0},
7831 {":file", IMAGE_STRING_VALUE
, 0},
7832 {":ascent", IMAGE_ASCENT_VALUE
, 0},
7833 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
7834 {":relief", IMAGE_INTEGER_VALUE
, 0},
7835 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7836 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7837 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
7838 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
7841 /* Structure describing the image type `svg'. Its the same type of
7842 structure defined for all image formats, handled by emacs image
7843 functions. See struct image_type in dispextern.h. */
7845 static struct image_type svg_type
=
7847 /* An identifier showing that this is an image structure for the SVG format. */
7849 /* Handle to a function that can be used to identify a SVG file. */
7851 /* Handle to function used to load a SVG file. */
7853 /* Handle to function to free sresources for SVG. */
7855 /* An internal field to link to the next image type in a list of
7856 image types, will be filled in when registering the format. */
7861 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7862 this by calling parse_image_spec and supplying the keywords that
7863 identify the SVG format. */
7866 svg_image_p (object
)
7869 struct image_keyword fmt
[SVG_LAST
];
7870 bcopy (svg_format
, fmt
, sizeof fmt
);
7872 if (!parse_image_spec (object
, fmt
, SVG_LAST
, Qsvg
))
7875 /* Must specify either the :data or :file keyword. */
7876 return fmt
[SVG_FILE
].count
+ fmt
[SVG_DATA
].count
== 1;
7879 #include <librsvg/rsvg.h>
7883 /* SVG library functions. */
7884 DEF_IMGLIB_FN (rsvg_handle_new
);
7885 DEF_IMGLIB_FN (rsvg_handle_get_dimensions
);
7886 DEF_IMGLIB_FN (rsvg_handle_write
);
7887 DEF_IMGLIB_FN (rsvg_handle_close
);
7888 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf
);
7889 DEF_IMGLIB_FN (rsvg_handle_free
);
7891 DEF_IMGLIB_FN (gdk_pixbuf_get_width
);
7892 DEF_IMGLIB_FN (gdk_pixbuf_get_height
);
7893 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels
);
7894 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride
);
7895 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace
);
7896 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels
);
7897 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha
);
7898 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample
);
7900 DEF_IMGLIB_FN (g_type_init
);
7901 DEF_IMGLIB_FN (g_object_unref
);
7902 DEF_IMGLIB_FN (g_error_free
);
7904 Lisp_Object Qgdk_pixbuf
, Qglib
;
7907 init_svg_functions (Lisp_Object libraries
)
7909 HMODULE library
, gdklib
, glib
;
7911 if (!(glib
= w32_delayed_load (libraries
, Qglib
))
7912 || !(gdklib
= w32_delayed_load (libraries
, Qgdk_pixbuf
))
7913 || !(library
= w32_delayed_load (libraries
, Qsvg
)))
7916 LOAD_IMGLIB_FN (library
, rsvg_handle_new
);
7917 LOAD_IMGLIB_FN (library
, rsvg_handle_get_dimensions
);
7918 LOAD_IMGLIB_FN (library
, rsvg_handle_write
);
7919 LOAD_IMGLIB_FN (library
, rsvg_handle_close
);
7920 LOAD_IMGLIB_FN (library
, rsvg_handle_get_pixbuf
);
7921 LOAD_IMGLIB_FN (library
, rsvg_handle_free
);
7923 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_width
);
7924 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_height
);
7925 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_pixels
);
7926 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_rowstride
);
7927 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_colorspace
);
7928 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_n_channels
);
7929 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_has_alpha
);
7930 LOAD_IMGLIB_FN (gdklib
, gdk_pixbuf_get_bits_per_sample
);
7932 LOAD_IMGLIB_FN (glib
, g_type_init
);
7933 LOAD_IMGLIB_FN (glib
, g_object_unref
);
7934 LOAD_IMGLIB_FN (glib
, g_error_free
);
7939 /* The following aliases for library functions allow dynamic loading
7940 to be used on some platforms. */
7941 #define fn_rsvg_handle_new rsvg_handle_new
7942 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7943 #define fn_rsvg_handle_write rsvg_handle_write
7944 #define fn_rsvg_handle_close rsvg_handle_close
7945 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7946 #define fn_rsvg_handle_free rsvg_handle_free
7948 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7949 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7950 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7951 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7952 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7953 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7954 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7955 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7957 #define fn_g_type_init g_type_init
7958 #define fn_g_object_unref g_object_unref
7959 #define fn_g_error_free g_error_free
7960 #endif /* !HAVE_NTGUI */
7962 /* Load SVG image IMG for use on frame F. Value is non-zero if
7963 successful. this function will go into the svg_type structure, and
7964 the prototype thus needs to be compatible with that structure. */
7972 Lisp_Object file_name
;
7974 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7975 file_name
= image_spec_value (img
->spec
, QCfile
, NULL
);
7976 if (STRINGP (file_name
))
7979 unsigned char *contents
;
7981 struct gcpro gcpro1
;
7983 file
= x_find_image_file (file_name
);
7985 if (!STRINGP (file
))
7987 image_error ("Cannot find image file `%s'", file_name
, Qnil
);
7992 /* Read the entire file into memory. */
7993 contents
= slurp_file (SDATA (file
), &size
);
7994 if (contents
== NULL
)
7996 image_error ("Error loading SVG image `%s'", img
->spec
, Qnil
);
8000 /* If the file was slurped into memory properly, parse it. */
8001 success_p
= svg_load_image (f
, img
, contents
, size
);
8005 /* Else its not a file, its a lisp object. Load the image from a
8006 lisp object rather than a file. */
8011 data
= image_spec_value (img
->spec
, QCdata
, NULL
);
8012 success_p
= svg_load_image (f
, img
, SDATA (data
), SBYTES (data
));
8018 /* svg_load_image is a helper function for svg_load, which does the
8019 actual loading given contents and size, apart from frame and image
8020 structures, passed from svg_load.
8022 Uses librsvg to do most of the image processing.
8024 Returns non-zero when successful. */
8026 svg_load_image (f
, img
, contents
, size
)
8027 /* Pointer to emacs frame structure. */
8029 /* Pointer to emacs image structure. */
8031 /* String containing the SVG XML data to be parsed. */
8032 unsigned char *contents
;
8033 /* Size of data in bytes. */
8036 RsvgHandle
*rsvg_handle
;
8037 RsvgDimensionData dimension_data
;
8038 GError
*error
= NULL
;
8042 const guint8
*pixels
;
8045 Lisp_Object specified_bg
;
8050 /* g_type_init is a glib function that must be called prior to using
8051 gnome type library functions. */
8053 /* Make a handle to a new rsvg object. */
8054 rsvg_handle
= fn_rsvg_handle_new ();
8056 /* Parse the contents argument and fill in the rsvg_handle. */
8057 fn_rsvg_handle_write (rsvg_handle
, contents
, size
, &error
);
8058 if (error
) goto rsvg_error
;
8060 /* The parsing is complete, rsvg_handle is ready to used, close it
8061 for further writes. */
8062 fn_rsvg_handle_close (rsvg_handle
, &error
);
8063 if (error
) goto rsvg_error
;
8065 fn_rsvg_handle_get_dimensions (rsvg_handle
, &dimension_data
);
8066 if (! check_image_size (f
, dimension_data
.width
, dimension_data
.height
))
8069 /* We can now get a valid pixel buffer from the svg file, if all
8071 pixbuf
= fn_rsvg_handle_get_pixbuf (rsvg_handle
);
8072 if (!pixbuf
) goto rsvg_error
;
8073 fn_g_object_unref (rsvg_handle
);
8075 /* Extract some meta data from the svg handle. */
8076 width
= fn_gdk_pixbuf_get_width (pixbuf
);
8077 height
= fn_gdk_pixbuf_get_height (pixbuf
);
8078 pixels
= fn_gdk_pixbuf_get_pixels (pixbuf
);
8079 rowstride
= fn_gdk_pixbuf_get_rowstride (pixbuf
);
8081 /* Validate the svg meta data. */
8082 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf
) == GDK_COLORSPACE_RGB
);
8083 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf
) == 4);
8084 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf
));
8085 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
8087 /* Try to create a x pixmap to hold the svg pixmap. */
8088 if (!x_create_x_image_and_pixmap (f
, width
, height
, 0, &ximg
, &img
->pixmap
))
8090 fn_g_object_unref (pixbuf
);
8094 init_color_table ();
8096 /* Handle alpha channel by combining the image with a background
8098 specified_bg
= image_spec_value (img
->spec
, QCbackground
, NULL
);
8099 if (STRINGP (specified_bg
)
8100 && x_defined_color (f
, SDATA (specified_bg
), &background
, 0))
8102 background
.red
>>= 8;
8103 background
.green
>>= 8;
8104 background
.blue
>>= 8;
8108 #ifdef HAVE_X_WINDOWS
8109 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8110 x_query_color (f
, &background
);
8112 /* SVG pixmaps specify transparency in the last byte, so right
8113 shift 8 bits to get rid of it, since emacs doesn't support
8115 background
.red
>>= 8;
8116 background
.green
>>= 8;
8117 background
.blue
>>= 8;
8118 #elif defined (HAVE_NTGUI)
8119 background
.pixel
= FRAME_BACKGROUND_PIXEL (f
);
8120 #if 0 /* W32 TODO : Colormap support. */
8121 x_query_color (f
, &background
);
8124 /* SVG pixmaps specify transparency in the last byte, so right
8125 shift 8 bits to get rid of it, since emacs doesn't support
8127 background
.red
>>= 8;
8128 background
.green
>>= 8;
8129 background
.blue
>>= 8;
8130 #else /* not HAVE_X_WINDOWS*/
8135 /* This loop handles opacity values, since Emacs assumes
8136 non-transparent images. Each pixel must be "flattened" by
8137 calculating the resulting color, given the transparency of the
8138 pixel, and the image background color. */
8139 for (y
= 0; y
< height
; ++y
)
8141 for (x
= 0; x
< width
; ++x
)
8151 opacity
= *pixels
++;
8153 red
= ((red
* opacity
)
8154 + (background
.red
* ((1 << 8) - opacity
)));
8155 green
= ((green
* opacity
)
8156 + (background
.green
* ((1 << 8) - opacity
)));
8157 blue
= ((blue
* opacity
)
8158 + (background
.blue
* ((1 << 8) - opacity
)));
8160 XPutPixel (ximg
, x
, y
, lookup_rgb_color (f
, red
, green
, blue
));
8163 pixels
+= rowstride
- 4 * width
;
8166 #ifdef COLOR_TABLE_SUPPORT
8167 /* Remember colors allocated for this image. */
8168 img
->colors
= colors_in_color_table (&img
->ncolors
);
8169 free_color_table ();
8170 #endif /* COLOR_TABLE_SUPPORT */
8172 fn_g_object_unref (pixbuf
);
8175 img
->height
= height
;
8177 /* Maybe fill in the background field while we have ximg handy.
8178 Casting avoids a GCC warning. */
8179 IMAGE_BACKGROUND (img
, f
, (XImagePtr_or_DC
)ximg
);
8181 /* Put the image into the pixmap, then free the X image and its
8183 x_put_x_image (f
, ximg
, img
->pixmap
, width
, height
);
8184 x_destroy_x_image (ximg
);
8189 fn_g_object_unref (rsvg_handle
);
8190 /* FIXME: Use error->message so the user knows what is the actual
8191 problem with the image. */
8192 image_error ("Error parsing SVG image `%s'", img
->spec
, Qnil
);
8193 fn_g_error_free (error
);
8197 #endif /* defined (HAVE_RSVG) */
8202 /***********************************************************************
8204 ***********************************************************************/
8206 #ifdef HAVE_X_WINDOWS
8207 #define HAVE_GHOSTSCRIPT 1
8208 #endif /* HAVE_X_WINDOWS */
8210 /* The symbol `postscript' identifying images of this type. */
8212 Lisp_Object Qpostscript
;
8214 #ifdef HAVE_GHOSTSCRIPT
8216 static int gs_image_p
P_ ((Lisp_Object object
));
8217 static int gs_load
P_ ((struct frame
*f
, struct image
*img
));
8218 static void gs_clear_image
P_ ((struct frame
*f
, struct image
*img
));
8220 /* Keyword symbols. */
8222 Lisp_Object QCloader
, QCbounding_box
, QCpt_width
, QCpt_height
;
8224 /* Indices of image specification fields in gs_format, below. */
8226 enum gs_keyword_index
8244 /* Vector of image_keyword structures describing the format
8245 of valid user-defined image specifications. */
8247 static struct image_keyword gs_format
[GS_LAST
] =
8249 {":type", IMAGE_SYMBOL_VALUE
, 1},
8250 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8251 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE
, 1},
8252 {":file", IMAGE_STRING_VALUE
, 1},
8253 {":loader", IMAGE_FUNCTION_VALUE
, 0},
8254 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE
, 1},
8255 {":ascent", IMAGE_ASCENT_VALUE
, 0},
8256 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR
, 0},
8257 {":relief", IMAGE_INTEGER_VALUE
, 0},
8258 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8259 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8260 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE
, 0},
8261 {":background", IMAGE_STRING_OR_NIL_VALUE
, 0}
8264 /* Structure describing the image type `ghostscript'. */
8266 static struct image_type gs_type
=
8276 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8279 gs_clear_image (f
, img
)
8283 /* IMG->data.ptr_val may contain a recorded colormap. */
8284 xfree (img
->data
.ptr_val
);
8285 x_clear_image (f
, img
);
8289 /* Return non-zero if OBJECT is a valid Ghostscript image
8296 struct image_keyword fmt
[GS_LAST
];
8300 bcopy (gs_format
, fmt
, sizeof fmt
);
8302 if (!parse_image_spec (object
, fmt
, GS_LAST
, Qpostscript
))
8305 /* Bounding box must be a list or vector containing 4 integers. */
8306 tem
= fmt
[GS_BOUNDING_BOX
].value
;
8309 for (i
= 0; i
< 4; ++i
, tem
= XCDR (tem
))
8310 if (!CONSP (tem
) || !INTEGERP (XCAR (tem
)))
8315 else if (VECTORP (tem
))
8317 if (XVECTOR (tem
)->size
!= 4)
8319 for (i
= 0; i
< 4; ++i
)
8320 if (!INTEGERP (XVECTOR (tem
)->contents
[i
]))
8330 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8339 Lisp_Object window_and_pixmap_id
= Qnil
, loader
, pt_height
, pt_width
;
8340 struct gcpro gcpro1
, gcpro2
;
8342 double in_width
, in_height
;
8343 Lisp_Object pixel_colors
= Qnil
;
8345 /* Compute pixel size of pixmap needed from the given size in the
8346 image specification. Sizes in the specification are in pt. 1 pt
8347 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8349 pt_width
= image_spec_value (img
->spec
, QCpt_width
, NULL
);
8350 in_width
= XFASTINT (pt_width
) / 72.0;
8351 img
->width
= in_width
* FRAME_X_DISPLAY_INFO (f
)->resx
;
8352 pt_height
= image_spec_value (img
->spec
, QCpt_height
, NULL
);
8353 in_height
= XFASTINT (pt_height
) / 72.0;
8354 img
->height
= in_height
* FRAME_X_DISPLAY_INFO (f
)->resy
;
8356 if (!check_image_size (f
, img
->width
, img
->height
))
8358 image_error ("Invalid image size", Qnil
, Qnil
);
8362 /* Create the pixmap. */
8363 xassert (img
->pixmap
== NO_PIXMAP
);
8365 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8367 img
->pixmap
= XCreatePixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8368 img
->width
, img
->height
,
8369 DefaultDepthOfScreen (FRAME_X_SCREEN (f
)));
8374 image_error ("Unable to create pixmap for `%s'", img
->spec
, Qnil
);
8378 /* Call the loader to fill the pixmap. It returns a process object
8379 if successful. We do not record_unwind_protect here because
8380 other places in redisplay like calling window scroll functions
8381 don't either. Let the Lisp loader use `unwind-protect' instead. */
8382 GCPRO2 (window_and_pixmap_id
, pixel_colors
);
8384 sprintf (buffer
, "%lu %lu",
8385 (unsigned long) FRAME_X_WINDOW (f
),
8386 (unsigned long) img
->pixmap
);
8387 window_and_pixmap_id
= build_string (buffer
);
8389 sprintf (buffer
, "%lu %lu",
8390 FRAME_FOREGROUND_PIXEL (f
),
8391 FRAME_BACKGROUND_PIXEL (f
));
8392 pixel_colors
= build_string (buffer
);
8394 XSETFRAME (frame
, f
);
8395 loader
= image_spec_value (img
->spec
, QCloader
, NULL
);
8397 loader
= intern ("gs-load-image");
8399 img
->data
.lisp_val
= call6 (loader
, frame
, img
->spec
,
8400 make_number (img
->width
),
8401 make_number (img
->height
),
8402 window_and_pixmap_id
,
8405 return PROCESSP (img
->data
.lisp_val
);
8409 /* Kill the Ghostscript process that was started to fill PIXMAP on
8410 frame F. Called from XTread_socket when receiving an event
8411 telling Emacs that Ghostscript has finished drawing. */
8414 x_kill_gs_process (pixmap
, f
)
8418 struct image_cache
*c
= FRAME_IMAGE_CACHE (f
);
8422 /* Find the image containing PIXMAP. */
8423 for (i
= 0; i
< c
->used
; ++i
)
8424 if (c
->images
[i
]->pixmap
== pixmap
)
8427 /* Should someone in between have cleared the image cache, for
8428 instance, give up. */
8432 /* Kill the GS process. We should have found PIXMAP in the image
8433 cache and its image should contain a process object. */
8435 xassert (PROCESSP (img
->data
.lisp_val
));
8436 Fkill_process (img
->data
.lisp_val
, Qnil
);
8437 img
->data
.lisp_val
= Qnil
;
8439 #if defined (HAVE_X_WINDOWS)
8441 /* On displays with a mutable colormap, figure out the colors
8442 allocated for the image by looking at the pixels of an XImage for
8444 class = FRAME_X_VISUAL (f
)->class;
8445 if (class != StaticColor
&& class != StaticGray
&& class != TrueColor
)
8451 /* Try to get an XImage for img->pixmep. */
8452 ximg
= XGetImage (FRAME_X_DISPLAY (f
), img
->pixmap
,
8453 0, 0, img
->width
, img
->height
, ~0, ZPixmap
);
8458 /* Initialize the color table. */
8459 init_color_table ();
8461 /* For each pixel of the image, look its color up in the
8462 color table. After having done so, the color table will
8463 contain an entry for each color used by the image. */
8464 for (y
= 0; y
< img
->height
; ++y
)
8465 for (x
= 0; x
< img
->width
; ++x
)
8467 unsigned long pixel
= XGetPixel (ximg
, x
, y
);
8468 lookup_pixel_color (f
, pixel
);
8471 /* Record colors in the image. Free color table and XImage. */
8472 #ifdef COLOR_TABLE_SUPPORT
8473 img
->colors
= colors_in_color_table (&img
->ncolors
);
8474 free_color_table ();
8476 XDestroyImage (ximg
);
8478 #if 0 /* This doesn't seem to be the case. If we free the colors
8479 here, we get a BadAccess later in x_clear_image when
8480 freeing the colors. */
8481 /* We have allocated colors once, but Ghostscript has also
8482 allocated colors on behalf of us. So, to get the
8483 reference counts right, free them once. */
8485 x_free_colors (f
, img
->colors
, img
->ncolors
);
8489 image_error ("Cannot get X image of `%s'; colors will not be freed",
8494 #endif /* HAVE_X_WINDOWS */
8496 /* Now that we have the pixmap, compute mask and transform the
8497 image if requested. */
8499 postprocess_image (f
, img
);
8503 #endif /* HAVE_GHOSTSCRIPT */
8506 /***********************************************************************
8508 ***********************************************************************/
8512 DEFUN ("imagep", Fimagep
, Simagep
, 1, 1, 0,
8513 doc
: /* Value is non-nil if SPEC is a valid image specification. */)
8517 return valid_image_p (spec
) ? Qt
: Qnil
;
8521 DEFUN ("lookup-image", Flookup_image
, Slookup_image
, 1, 1, 0, "")
8527 if (valid_image_p (spec
))
8528 id
= lookup_image (SELECTED_FRAME (), spec
);
8531 return make_number (id
);
8534 #endif /* GLYPH_DEBUG != 0 */
8537 /***********************************************************************
8539 ***********************************************************************/
8542 /* Image types that rely on external libraries are loaded dynamically
8543 if the library is available. */
8544 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8545 define_image_type (image_type, init_lib_fn (libraries))
8547 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8548 define_image_type (image_type, 1)
8549 #endif /* HAVE_NTGUI */
8551 DEFUN ("init-image-library", Finit_image_library
, Sinit_image_library
, 2, 2, 0,
8552 doc
: /* Initialize image library implementing image type TYPE.
8553 Return non-nil if TYPE is a supported image type.
8555 Image types pbm and xbm are prebuilt; other types are loaded here.
8556 Libraries to load are specified in alist LIBRARIES (usually, the value
8557 of `image-library-alist', which see). */)
8559 Lisp_Object type
, libraries
;
8563 /* Don't try to reload the library. */
8564 tested
= Fassq (type
, Vimage_type_cache
);
8566 return XCDR (tested
);
8568 #if defined (HAVE_XPM) || defined (HAVE_NS)
8569 if (EQ (type
, Qxpm
))
8570 return CHECK_LIB_AVAILABLE (&xpm_type
, init_xpm_functions
, libraries
);
8573 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8574 if (EQ (type
, Qjpeg
))
8575 return CHECK_LIB_AVAILABLE (&jpeg_type
, init_jpeg_functions
, libraries
);
8578 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8579 if (EQ (type
, Qtiff
))
8580 return CHECK_LIB_AVAILABLE (&tiff_type
, init_tiff_functions
, libraries
);
8583 #if defined (HAVE_GIF) || defined (HAVE_NS)
8584 if (EQ (type
, Qgif
))
8585 return CHECK_LIB_AVAILABLE (&gif_type
, init_gif_functions
, libraries
);
8588 #if defined (HAVE_PNG) || defined (HAVE_NS)
8589 if (EQ (type
, Qpng
))
8590 return CHECK_LIB_AVAILABLE (&png_type
, init_png_functions
, libraries
);
8593 #if defined (HAVE_RSVG)
8594 if (EQ (type
, Qsvg
))
8595 return CHECK_LIB_AVAILABLE (&svg_type
, init_svg_functions
, libraries
);
8598 #ifdef HAVE_GHOSTSCRIPT
8599 if (EQ (type
, Qpostscript
))
8600 return CHECK_LIB_AVAILABLE (&gs_type
, init_gs_functions
, libraries
);
8603 /* If the type is not recognized, avoid testing it ever again. */
8604 CACHE_IMAGE_TYPE (type
, Qnil
);
8611 extern Lisp_Object Qrisky_local_variable
; /* Syms_of_xdisp has already run. */
8613 /* Initialize this only once, since that's what we do with Vimage_types
8614 and they are supposed to be in sync. Initializing here gives correct
8615 operation on GNU/Linux of calling dump-emacs after loading some images. */
8618 /* Must be defined now becase we're going to update it below, while
8619 defining the supported image types. */
8620 DEFVAR_LISP ("image-types", &Vimage_types
,
8621 doc
: /* List of potentially supported image types.
8622 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8623 To check whether it is really supported, use `image-type-available-p'. */);
8624 Vimage_types
= Qnil
;
8626 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist
,
8627 doc
: /* Alist of image types vs external libraries needed to display them.
8629 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8630 representing a supported image type, and the rest are strings giving
8631 alternate filenames for the corresponding external libraries.
8633 Emacs tries to load the libraries in the order they appear on the
8634 list; if none is loaded, the running session of Emacs won't
8635 support the image type. Types 'pbm and 'xbm don't need to be
8636 listed; they are always supported. */);
8637 Vimage_library_alist
= Qnil
;
8638 Fput (intern ("image-library-alist"), Qrisky_local_variable
, Qt
);
8640 DEFVAR_LISP ("max-image-size", &Vmax_image_size
,
8641 doc
: /* Maximum size of images.
8642 Emacs will not load an image into memory if its pixel width or
8643 pixel height exceeds this limit.
8645 If the value is an integer, it directly specifies the maximum
8646 image height and width, measured in pixels. If it is a floating
8647 point number, it specifies the maximum image height and width
8648 as a ratio to the frame height and width. If the value is
8649 non-numeric, there is no explicit limit on the size of images. */);
8650 Vmax_image_size
= make_float (MAX_IMAGE_SIZE
);
8652 Vimage_type_cache
= Qnil
;
8653 staticpro (&Vimage_type_cache
);
8655 Qpbm
= intern ("pbm");
8657 ADD_IMAGE_TYPE (Qpbm
);
8659 Qxbm
= intern ("xbm");
8661 ADD_IMAGE_TYPE (Qxbm
);
8663 define_image_type (&xbm_type
, 1);
8664 define_image_type (&pbm_type
, 1);
8666 Qcount
= intern ("count");
8667 staticpro (&Qcount
);
8669 QCascent
= intern (":ascent");
8670 staticpro (&QCascent
);
8671 QCmargin
= intern (":margin");
8672 staticpro (&QCmargin
);
8673 QCrelief
= intern (":relief");
8674 staticpro (&QCrelief
);
8675 QCconversion
= intern (":conversion");
8676 staticpro (&QCconversion
);
8677 QCcolor_symbols
= intern (":color-symbols");
8678 staticpro (&QCcolor_symbols
);
8679 QCheuristic_mask
= intern (":heuristic-mask");
8680 staticpro (&QCheuristic_mask
);
8681 QCindex
= intern (":index");
8682 staticpro (&QCindex
);
8683 QCmatrix
= intern (":matrix");
8684 staticpro (&QCmatrix
);
8685 QCcolor_adjustment
= intern (":color-adjustment");
8686 staticpro (&QCcolor_adjustment
);
8687 QCmask
= intern (":mask");
8688 staticpro (&QCmask
);
8690 Qlaplace
= intern ("laplace");
8691 staticpro (&Qlaplace
);
8692 Qemboss
= intern ("emboss");
8693 staticpro (&Qemboss
);
8694 Qedge_detection
= intern ("edge-detection");
8695 staticpro (&Qedge_detection
);
8696 Qheuristic
= intern ("heuristic");
8697 staticpro (&Qheuristic
);
8699 Qpostscript
= intern ("postscript");
8700 staticpro (&Qpostscript
);
8701 #ifdef HAVE_GHOSTSCRIPT
8702 ADD_IMAGE_TYPE (Qpostscript
);
8703 QCloader
= intern (":loader");
8704 staticpro (&QCloader
);
8705 QCbounding_box
= intern (":bounding-box");
8706 staticpro (&QCbounding_box
);
8707 QCpt_width
= intern (":pt-width");
8708 staticpro (&QCpt_width
);
8709 QCpt_height
= intern (":pt-height");
8710 staticpro (&QCpt_height
);
8711 #endif /* HAVE_GHOSTSCRIPT */
8713 #if defined (HAVE_XPM) || defined (HAVE_NS)
8714 Qxpm
= intern ("xpm");
8716 ADD_IMAGE_TYPE (Qxpm
);
8719 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8720 Qjpeg
= intern ("jpeg");
8722 ADD_IMAGE_TYPE (Qjpeg
);
8725 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8726 Qtiff
= intern ("tiff");
8728 ADD_IMAGE_TYPE (Qtiff
);
8731 #if defined (HAVE_GIF) || defined (HAVE_NS)
8732 Qgif
= intern ("gif");
8734 ADD_IMAGE_TYPE (Qgif
);
8737 #if defined (HAVE_PNG) || defined (HAVE_NS)
8738 Qpng
= intern ("png");
8740 ADD_IMAGE_TYPE (Qpng
);
8743 #if defined (HAVE_RSVG)
8744 Qsvg
= intern ("svg");
8746 ADD_IMAGE_TYPE (Qsvg
);
8748 Qgdk_pixbuf
= intern ("gdk-pixbuf");
8749 staticpro (&Qgdk_pixbuf
);
8750 Qglib
= intern ("glib");
8752 #endif /* HAVE_NTGUI */
8753 #endif /* HAVE_RSVG */
8755 defsubr (&Sinit_image_library
);
8756 defsubr (&Sclear_image_cache
);
8757 defsubr (&Simage_refresh
);
8758 defsubr (&Simage_size
);
8759 defsubr (&Simage_mask_p
);
8760 defsubr (&Simage_extension_data
);
8764 defsubr (&Slookup_image
);
8767 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images
,
8768 doc
: /* Non-nil means always draw a cross over disabled images.
8769 Disabled images are those having a `:conversion disabled' property.
8770 A cross is always drawn on black & white displays. */);
8771 cross_disabled_images
= 0;
8773 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
8774 doc
: /* List of directories to search for window system bitmap files. */);
8775 Vx_bitmap_file_path
= decode_env_path ((char *) 0, PATH_BITMAPS
);
8777 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay
,
8778 doc
: /* Time after which cached images are removed from the cache.
8779 When an image has not been displayed this many seconds, remove it
8780 from the image cache. Value must be an integer or nil with nil
8781 meaning don't clear the cache. */);
8782 Vimage_cache_eviction_delay
= make_number (30 * 60);
8790 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8791 (do not change this comment) */