(custom-group-value-create): Insert some
[emacs.git] / src / image.c
blob3323a68d33f16b5337374617f4d311db5a8966b7
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <ctype.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
30 /* This makes the fields of a Display accessible, in Xlib header files. */
32 #define XLIB_ILLEGAL_ACCESS
34 #include "lisp.h"
35 #include "frame.h"
36 #include "window.h"
37 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "systime.h"
40 #include <epaths.h>
41 #include "character.h"
42 #include "coding.h"
43 #include "termhooks.h"
44 #include "font.h"
46 #ifdef HAVE_X_WINDOWS
47 #include "xterm.h"
48 #include <sys/types.h>
49 #include <sys/stat.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 */
64 #ifdef HAVE_NTGUI
65 #include "w32term.h"
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)
72 #define NO_PIXMAP 0
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 /* Functions from w32term.c that depend on XColor (so can't go in w32term.h
84 without modifying lots of files). */
85 extern void x_query_colors (struct frame *f, XColor *colors, int ncolors);
86 extern void x_query_color (struct frame *f, XColor *color);
87 #endif /* HAVE_NTGUI */
89 #ifdef HAVE_NS
90 #include "nsterm.h"
91 #include <sys/types.h>
92 #include <sys/stat.h>
94 #undef COLOR_TABLE_SUPPORT
96 typedef struct ns_bitmap_record Bitmap_Record;
98 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
99 #define NO_PIXMAP 0
101 #define RGB_PIXEL_COLOR unsigned long
102 #define ZPixmap 0
104 #define PIX_MASK_RETAIN 0
105 #define PIX_MASK_DRAW 1
107 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
108 #define x_defined_color(f, name, color_def, alloc) \
109 ns_defined_color (f, name, color_def, alloc, 0)
110 #define FRAME_X_SCREEN(f) 0
111 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
112 #endif /* HAVE_NS */
115 /* Search path for bitmap files. */
117 Lisp_Object Vx_bitmap_file_path;
120 static void x_disable_image P_ ((struct frame *, struct image *));
121 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
122 Lisp_Object));
124 static void init_color_table P_ ((void));
125 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
126 #ifdef COLOR_TABLE_SUPPORT
127 static void free_color_table P_ ((void));
128 static unsigned long *colors_in_color_table P_ ((int *n));
129 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
130 #endif
132 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
133 id, which is just an int that this section returns. Bitmaps are
134 reference counted so they can be shared among frames.
136 Bitmap indices are guaranteed to be > 0, so a negative number can
137 be used to indicate no bitmap.
139 If you use x_create_bitmap_from_data, then you must keep track of
140 the bitmaps yourself. That is, creating a bitmap from the same
141 data more than once will not be caught. */
143 #ifdef MAC_OS
145 static XImagePtr
146 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
147 Display *display; /* not used */
148 Pixmap pixmap;
149 int x, y; /* not used */
150 unsigned int width, height; /* not used */
151 unsigned long plane_mask; /* not used */
152 int format; /* not used */
154 #if !USE_MAC_IMAGE_IO
155 #if GLYPH_DEBUG
156 xassert (x == 0 && y == 0);
158 Rect ri, rp;
159 SetRect (&ri, 0, 0, width, height);
160 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
162 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
163 #endif
165 LockPixels (GetGWorldPixMap (pixmap));
166 #endif
168 return pixmap;
171 static void
172 XPutPixel (ximage, x, y, pixel)
173 XImagePtr ximage;
174 int x, y;
175 unsigned long pixel;
177 #if USE_MAC_IMAGE_IO
178 if (ximage->bits_per_pixel == 32)
179 ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
180 else
181 ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
182 #else
183 PixMapHandle pixmap = GetGWorldPixMap (ximage);
184 short depth = GetPixDepth (pixmap);
186 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
187 if (depth == 32)
189 char *base_addr = GetPixBaseAddr (pixmap);
190 short row_bytes = GetPixRowBytes (pixmap);
192 ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
194 else
195 #endif
196 if (depth == 1)
198 char *base_addr = GetPixBaseAddr (pixmap);
199 short row_bytes = GetPixRowBytes (pixmap);
201 if (pixel == PIX_MASK_DRAW)
202 base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
203 else
204 base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
206 else
208 CGrafPtr old_port;
209 GDHandle old_gdh;
210 RGBColor color;
212 GetGWorld (&old_port, &old_gdh);
213 SetGWorld (ximage, NULL);
215 color.red = RED16_FROM_ULONG (pixel);
216 color.green = GREEN16_FROM_ULONG (pixel);
217 color.blue = BLUE16_FROM_ULONG (pixel);
219 SetCPixel (x, y, &color);
221 SetGWorld (old_port, old_gdh);
223 #endif
226 static unsigned long
227 XGetPixel (ximage, x, y)
228 XImagePtr ximage;
229 int x, y;
231 #if USE_MAC_IMAGE_IO
232 if (ximage->bits_per_pixel == 32)
233 return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
234 else
235 return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
236 #else
237 PixMapHandle pixmap = GetGWorldPixMap (ximage);
238 short depth = GetPixDepth (pixmap);
240 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
241 if (depth == 32)
243 char *base_addr = GetPixBaseAddr (pixmap);
244 short row_bytes = GetPixRowBytes (pixmap);
246 return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
248 else
249 #endif
250 if (depth == 1)
252 char *base_addr = GetPixBaseAddr (pixmap);
253 short row_bytes = GetPixRowBytes (pixmap);
255 if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
256 return PIX_MASK_DRAW;
257 else
258 return PIX_MASK_RETAIN;
260 else
262 CGrafPtr old_port;
263 GDHandle old_gdh;
264 RGBColor color;
266 GetGWorld (&old_port, &old_gdh);
267 SetGWorld (ximage, NULL);
269 GetCPixel (x, y, &color);
271 SetGWorld (old_port, old_gdh);
272 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
274 #endif
277 static void
278 XDestroyImage (ximg)
279 XImagePtr ximg;
281 #if !USE_MAC_IMAGE_IO
282 UnlockPixels (GetGWorldPixMap (ximg));
283 #endif
286 #if USE_CG_DRAWING
287 #if USE_MAC_IMAGE_IO
288 void
289 mac_data_provider_release_data (info, data, size)
290 void *info;
291 const void *data;
292 size_t size;
294 xfree ((void *)data);
296 #endif
298 static CGImageRef
299 mac_create_cg_image_from_image (f, img)
300 struct frame *f;
301 struct image *img;
303 #if USE_MAC_IMAGE_IO
304 XImagePtr ximg = img->pixmap;
305 CGDataProviderRef provider;
306 CGImageRef result;
308 if (img->mask)
310 int x, y;
311 unsigned long color, alpha;
313 for (y = 0; y < ximg->height; y++)
314 for (x = 0; x < ximg->width; x++)
316 color = XGetPixel (ximg, x, y);
317 alpha = XGetPixel (img->mask, x, y);
318 XPutPixel (ximg, x, y,
319 ARGB_TO_ULONG (alpha,
320 RED_FROM_ULONG (color)
321 * alpha / PIX_MASK_DRAW,
322 GREEN_FROM_ULONG (color)
323 * alpha / PIX_MASK_DRAW,
324 BLUE_FROM_ULONG (color)
325 * alpha / PIX_MASK_DRAW));
327 xfree (img->mask->data);
328 img->mask->data = NULL;
330 BLOCK_INPUT;
331 provider = CGDataProviderCreateWithData (NULL, ximg->data,
332 ximg->bytes_per_line * ximg->height,
333 mac_data_provider_release_data);
334 ximg->data = NULL;
335 result = CGImageCreate (ximg->width, ximg->height, 8, 32,
336 ximg->bytes_per_line, mac_cg_color_space_rgb,
337 ((img->mask ? kCGImageAlphaPremultipliedFirst
338 : kCGImageAlphaNoneSkipFirst)
339 | kCGBitmapByteOrder32Host),
340 provider, NULL, 0, kCGRenderingIntentDefault);
341 CGDataProviderRelease (provider);
342 UNBLOCK_INPUT;
344 return result;
345 #else
346 Pixmap mask;
347 CGImageRef result = NULL;
349 BLOCK_INPUT;
350 if (img->mask)
351 mask = img->mask;
352 else
354 mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
355 img->width, img->height, 1);
356 if (mask)
358 CGrafPtr old_port;
359 GDHandle old_gdh;
360 Rect r;
362 GetGWorld (&old_port, &old_gdh);
363 SetGWorld (mask, NULL);
364 BackColor (blackColor); /* Don't mask. */
365 SetRect (&r, 0, 0, img->width, img->height);
366 EraseRect (&r);
367 SetGWorld (old_port, old_gdh);
370 if (mask)
372 CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
373 GetGWorldPixMap (mask), &result);
374 if (mask != img->mask)
375 XFreePixmap (FRAME_X_DISPLAY (f), mask);
377 UNBLOCK_INPUT;
379 return result;
380 #endif
382 #endif /* USE_CG_DRAWING */
383 #endif /* MAC_OS */
385 #ifdef HAVE_NS
386 XImagePtr
387 XGetImage (Display *display, Pixmap pixmap, int x, int y,
388 unsigned int width, unsigned int height,
389 unsigned long plane_mask, int format)
391 /* TODO: not sure what this function is supposed to do.. */
392 ns_retain_object(pixmap);
393 return pixmap;
396 /* use with imgs created by ns_image_for_XPM */
397 unsigned long
398 XGetPixel (XImagePtr ximage, int x, int y)
400 return ns_get_pixel(ximage, x, y);
403 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
404 pixel is assumed to be in form RGB */
405 void
406 XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
408 ns_put_pixel(ximage, x, y, pixel);
410 #endif /* HAVE_NS */
413 /* Functions to access the contents of a bitmap, given an id. */
416 x_bitmap_height (f, id)
417 FRAME_PTR f;
418 int id;
420 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
424 x_bitmap_width (f, id)
425 FRAME_PTR f;
426 int id;
428 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
431 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
433 x_bitmap_pixmap (f, id)
434 FRAME_PTR f;
435 int id;
437 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
439 #endif
441 #ifdef HAVE_X_WINDOWS
443 x_bitmap_mask (f, id)
444 FRAME_PTR f;
445 int id;
447 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
449 #endif
451 /* Allocate a new bitmap record. Returns index of new record. */
453 static int
454 x_allocate_bitmap_record (f)
455 FRAME_PTR f;
457 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
458 int i;
460 if (dpyinfo->bitmaps == NULL)
462 dpyinfo->bitmaps_size = 10;
463 dpyinfo->bitmaps
464 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
465 dpyinfo->bitmaps_last = 1;
466 return 1;
469 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
470 return ++dpyinfo->bitmaps_last;
472 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
473 if (dpyinfo->bitmaps[i].refcount == 0)
474 return i + 1;
476 dpyinfo->bitmaps_size *= 2;
477 dpyinfo->bitmaps
478 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
479 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
480 return ++dpyinfo->bitmaps_last;
483 /* Add one reference to the reference count of the bitmap with id ID. */
485 void
486 x_reference_bitmap (f, id)
487 FRAME_PTR f;
488 int id;
490 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
493 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
496 x_create_bitmap_from_data (f, bits, width, height)
497 struct frame *f;
498 char *bits;
499 unsigned int width, height;
501 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
502 int id;
504 #ifdef HAVE_X_WINDOWS
505 Pixmap bitmap;
506 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
507 bits, width, height);
508 if (! bitmap)
509 return -1;
510 #endif /* HAVE_X_WINDOWS */
512 #ifdef HAVE_NTGUI
513 Pixmap bitmap;
514 bitmap = CreateBitmap (width, height,
515 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
516 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
517 bits);
518 if (! bitmap)
519 return -1;
520 #endif /* HAVE_NTGUI */
522 #ifdef HAVE_NS
523 void *bitmap = ns_image_from_XBM(bits, width, height);
524 if (!bitmap)
525 return -1;
526 #endif
528 id = x_allocate_bitmap_record (f);
530 #ifdef HAVE_NS
531 dpyinfo->bitmaps[id - 1].img = bitmap;
532 dpyinfo->bitmaps[id - 1].depth = 1;
533 #endif
535 dpyinfo->bitmaps[id - 1].file = NULL;
536 dpyinfo->bitmaps[id - 1].height = height;
537 dpyinfo->bitmaps[id - 1].width = width;
538 dpyinfo->bitmaps[id - 1].refcount = 1;
540 #ifdef HAVE_X_WINDOWS
541 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
542 dpyinfo->bitmaps[id - 1].have_mask = 0;
543 dpyinfo->bitmaps[id - 1].depth = 1;
544 #endif /* HAVE_X_WINDOWS */
546 #ifdef HAVE_NTGUI
547 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
548 dpyinfo->bitmaps[id - 1].hinst = NULL;
549 dpyinfo->bitmaps[id - 1].depth = 1;
550 #endif /* HAVE_NTGUI */
552 return id;
555 /* Create bitmap from file FILE for frame F. */
558 x_create_bitmap_from_file (f, file)
559 struct frame *f;
560 Lisp_Object file;
562 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
564 #ifdef HAVE_NTGUI
565 return -1; /* W32_TODO : bitmap support */
566 #endif /* HAVE_NTGUI */
568 #ifdef HAVE_NS
569 int id;
570 void *bitmap = ns_image_from_file(file);
572 if (!bitmap)
573 return -1;
576 id = x_allocate_bitmap_record (f);
577 dpyinfo->bitmaps[id - 1].img = bitmap;
578 dpyinfo->bitmaps[id - 1].refcount = 1;
579 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
580 dpyinfo->bitmaps[id - 1].depth = 1;
581 dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap);
582 dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap);
583 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
584 return id;
585 #endif
587 #ifdef HAVE_X_WINDOWS
588 unsigned int width, height;
589 Pixmap bitmap;
590 int xhot, yhot, result, id;
591 Lisp_Object found;
592 int fd;
593 char *filename;
595 /* Look for an existing bitmap with the same name. */
596 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
598 if (dpyinfo->bitmaps[id].refcount
599 && dpyinfo->bitmaps[id].file
600 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
602 ++dpyinfo->bitmaps[id].refcount;
603 return id + 1;
607 /* Search bitmap-file-path for the file, if appropriate. */
608 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
609 if (fd < 0)
610 return -1;
611 emacs_close (fd);
613 filename = (char *) SDATA (found);
615 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
616 filename, &width, &height, &bitmap, &xhot, &yhot);
617 if (result != BitmapSuccess)
618 return -1;
620 id = x_allocate_bitmap_record (f);
621 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
622 dpyinfo->bitmaps[id - 1].have_mask = 0;
623 dpyinfo->bitmaps[id - 1].refcount = 1;
624 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
625 dpyinfo->bitmaps[id - 1].depth = 1;
626 dpyinfo->bitmaps[id - 1].height = height;
627 dpyinfo->bitmaps[id - 1].width = width;
628 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
630 return id;
631 #endif /* HAVE_X_WINDOWS */
634 /* Free bitmap B. */
636 static void
637 free_bitmap_record (dpyinfo, bm)
638 Display_Info *dpyinfo;
639 Bitmap_Record *bm;
641 #ifdef HAVE_X_WINDOWS
642 XFreePixmap (dpyinfo->display, bm->pixmap);
643 if (bm->have_mask)
644 XFreePixmap (dpyinfo->display, bm->mask);
645 #endif /* HAVE_X_WINDOWS */
647 #ifdef HAVE_NTGUI
648 DeleteObject (bm->pixmap);
649 #endif /* HAVE_NTGUI */
651 #ifdef HAVE_NS
652 ns_release_object(bm->img);
653 #endif
655 if (bm->file)
657 xfree (bm->file);
658 bm->file = NULL;
662 /* Remove reference to bitmap with id number ID. */
664 void
665 x_destroy_bitmap (f, id)
666 FRAME_PTR f;
667 int id;
669 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
671 if (id > 0)
673 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
675 if (--bm->refcount == 0)
677 BLOCK_INPUT;
678 free_bitmap_record (dpyinfo, bm);
679 UNBLOCK_INPUT;
684 /* Free all the bitmaps for the display specified by DPYINFO. */
686 void
687 x_destroy_all_bitmaps (dpyinfo)
688 Display_Info *dpyinfo;
690 int i;
691 Bitmap_Record *bm = dpyinfo->bitmaps;
693 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
694 if (bm->refcount > 0)
695 free_bitmap_record (dpyinfo, bm);
697 dpyinfo->bitmaps_last = 0;
701 #ifdef HAVE_X_WINDOWS
703 /* Useful functions defined in the section
704 `Image type independent image structures' below. */
706 static unsigned long four_corners_best P_ ((XImagePtr ximg,
707 int *corners,
708 unsigned long width,
709 unsigned long height));
711 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
712 int depth, XImagePtr *ximg,
713 Pixmap *pixmap));
715 static void x_destroy_x_image P_ ((XImagePtr ximg));
718 /* Create a mask of a bitmap. Note is this not a perfect mask.
719 It's nicer with some borders in this context */
722 x_create_bitmap_mask (f, id)
723 struct frame *f;
724 int id;
726 Pixmap pixmap, mask;
727 XImagePtr ximg, mask_img;
728 unsigned long width, height;
729 int result;
730 unsigned long bg;
731 unsigned long x, y, xp, xm, yp, ym;
732 GC gc;
734 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
736 if (!(id > 0))
737 return -1;
739 pixmap = x_bitmap_pixmap (f, id);
740 width = x_bitmap_width (f, id);
741 height = x_bitmap_height (f, id);
743 BLOCK_INPUT;
744 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
745 ~0, ZPixmap);
747 if (!ximg)
749 UNBLOCK_INPUT;
750 return -1;
753 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
755 UNBLOCK_INPUT;
756 if (!result)
758 XDestroyImage (ximg);
759 return -1;
762 bg = four_corners_best (ximg, NULL, width, height);
764 for (y = 0; y < ximg->height; ++y)
766 for (x = 0; x < ximg->width; ++x)
768 xp = x != ximg->width - 1 ? x + 1 : 0;
769 xm = x != 0 ? x - 1 : ximg->width - 1;
770 yp = y != ximg->height - 1 ? y + 1 : 0;
771 ym = y != 0 ? y - 1 : ximg->height - 1;
772 if (XGetPixel (ximg, x, y) == bg
773 && XGetPixel (ximg, x, yp) == bg
774 && XGetPixel (ximg, x, ym) == bg
775 && XGetPixel (ximg, xp, y) == bg
776 && XGetPixel (ximg, xp, yp) == bg
777 && XGetPixel (ximg, xp, ym) == bg
778 && XGetPixel (ximg, xm, y) == bg
779 && XGetPixel (ximg, xm, yp) == bg
780 && XGetPixel (ximg, xm, ym) == bg)
781 XPutPixel (mask_img, x, y, 0);
782 else
783 XPutPixel (mask_img, x, y, 1);
787 xassert (interrupt_input_blocked);
788 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
789 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
790 width, height);
791 XFreeGC (FRAME_X_DISPLAY (f), gc);
793 dpyinfo->bitmaps[id - 1].have_mask = 1;
794 dpyinfo->bitmaps[id - 1].mask = mask;
796 XDestroyImage (ximg);
797 x_destroy_x_image (mask_img);
799 return 0;
802 #endif /* HAVE_X_WINDOWS */
805 /***********************************************************************
806 Image types
807 ***********************************************************************/
809 /* Value is the number of elements of vector VECTOR. */
811 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
813 /* List of supported image types. Use define_image_type to add new
814 types. Use lookup_image_type to find a type for a given symbol. */
816 static struct image_type *image_types;
818 /* A list of symbols, one for each supported image type. */
820 Lisp_Object Vimage_types;
822 /* An alist of image types and libraries that implement the type. */
824 Lisp_Object Vimage_library_alist;
826 /* Cache for delayed-loading image types. */
828 static Lisp_Object Vimage_type_cache;
830 /* The symbol `xbm' which is used as the type symbol for XBM images. */
832 Lisp_Object Qxbm;
834 /* Keywords. */
836 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
837 extern Lisp_Object QCdata, QCtype;
838 extern Lisp_Object Qcenter;
839 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
840 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
841 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
843 /* Other symbols. */
845 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
847 /* Time in seconds after which images should be removed from the cache
848 if not displayed. */
850 Lisp_Object Vimage_cache_eviction_delay;
852 /* Function prototypes. */
854 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
855 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
856 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
857 static void x_laplace P_ ((struct frame *, struct image *));
858 static void x_emboss P_ ((struct frame *, struct image *));
859 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
860 Lisp_Object));
862 #define CACHE_IMAGE_TYPE(type, status) \
863 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
865 #define ADD_IMAGE_TYPE(type) \
866 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
868 /* Define a new image type from TYPE. This adds a copy of TYPE to
869 image_types and caches the loading status of TYPE. */
871 static Lisp_Object
872 define_image_type (type, loaded)
873 struct image_type *type;
874 int loaded;
876 Lisp_Object success;
878 if (!loaded)
879 success = Qnil;
880 else
882 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
883 The initialized data segment is read-only. */
884 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
885 bcopy (type, p, sizeof *p);
886 p->next = image_types;
887 image_types = p;
888 success = Qt;
891 CACHE_IMAGE_TYPE (*type->type, success);
892 return success;
896 /* Look up image type SYMBOL, and return a pointer to its image_type
897 structure. Value is null if SYMBOL is not a known image type. */
899 static INLINE struct image_type *
900 lookup_image_type (symbol)
901 Lisp_Object symbol;
903 struct image_type *type;
905 /* We must initialize the image-type if it hasn't been already. */
906 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
907 return 0; /* unimplemented */
909 for (type = image_types; type; type = type->next)
910 if (EQ (symbol, *type->type))
911 break;
913 return type;
917 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
918 valid image specification is a list whose car is the symbol
919 `image', and whose rest is a property list. The property list must
920 contain a value for key `:type'. That value must be the name of a
921 supported image type. The rest of the property list depends on the
922 image type. */
925 valid_image_p (object)
926 Lisp_Object object;
928 int valid_p = 0;
930 if (IMAGEP (object))
932 Lisp_Object tem;
934 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
935 if (EQ (XCAR (tem), QCtype))
937 tem = XCDR (tem);
938 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
940 struct image_type *type;
941 type = lookup_image_type (XCAR (tem));
942 if (type)
943 valid_p = type->valid_p (object);
946 break;
950 return valid_p;
954 /* Log error message with format string FORMAT and argument ARG.
955 Signaling an error, e.g. when an image cannot be loaded, is not a
956 good idea because this would interrupt redisplay, and the error
957 message display would lead to another redisplay. This function
958 therefore simply displays a message. */
960 static void
961 image_error (format, arg1, arg2)
962 char *format;
963 Lisp_Object arg1, arg2;
965 add_to_log (format, arg1, arg2);
970 /***********************************************************************
971 Image specifications
972 ***********************************************************************/
974 enum image_value_type
976 IMAGE_DONT_CHECK_VALUE_TYPE,
977 IMAGE_STRING_VALUE,
978 IMAGE_STRING_OR_NIL_VALUE,
979 IMAGE_SYMBOL_VALUE,
980 IMAGE_POSITIVE_INTEGER_VALUE,
981 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
982 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
983 IMAGE_ASCENT_VALUE,
984 IMAGE_INTEGER_VALUE,
985 IMAGE_FUNCTION_VALUE,
986 IMAGE_NUMBER_VALUE,
987 IMAGE_BOOL_VALUE
990 /* Structure used when parsing image specifications. */
992 struct image_keyword
994 /* Name of keyword. */
995 char *name;
997 /* The type of value allowed. */
998 enum image_value_type type;
1000 /* Non-zero means key must be present. */
1001 int mandatory_p;
1003 /* Used to recognize duplicate keywords in a property list. */
1004 int count;
1006 /* The value that was found. */
1007 Lisp_Object value;
1011 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
1012 int, Lisp_Object));
1013 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
1016 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
1017 has the format (image KEYWORD VALUE ...). One of the keyword/
1018 value pairs must be `:type TYPE'. KEYWORDS is a vector of
1019 image_keywords structures of size NKEYWORDS describing other
1020 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1022 static int
1023 parse_image_spec (spec, keywords, nkeywords, type)
1024 Lisp_Object spec;
1025 struct image_keyword *keywords;
1026 int nkeywords;
1027 Lisp_Object type;
1029 int i;
1030 Lisp_Object plist;
1032 if (!IMAGEP (spec))
1033 return 0;
1035 plist = XCDR (spec);
1036 while (CONSP (plist))
1038 Lisp_Object key, value;
1040 /* First element of a pair must be a symbol. */
1041 key = XCAR (plist);
1042 plist = XCDR (plist);
1043 if (!SYMBOLP (key))
1044 return 0;
1046 /* There must follow a value. */
1047 if (!CONSP (plist))
1048 return 0;
1049 value = XCAR (plist);
1050 plist = XCDR (plist);
1052 /* Find key in KEYWORDS. Error if not found. */
1053 for (i = 0; i < nkeywords; ++i)
1054 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
1055 break;
1057 if (i == nkeywords)
1058 continue;
1060 /* Record that we recognized the keyword. If a keywords
1061 was found more than once, it's an error. */
1062 keywords[i].value = value;
1063 ++keywords[i].count;
1065 if (keywords[i].count > 1)
1066 return 0;
1068 /* Check type of value against allowed type. */
1069 switch (keywords[i].type)
1071 case IMAGE_STRING_VALUE:
1072 if (!STRINGP (value))
1073 return 0;
1074 break;
1076 case IMAGE_STRING_OR_NIL_VALUE:
1077 if (!STRINGP (value) && !NILP (value))
1078 return 0;
1079 break;
1081 case IMAGE_SYMBOL_VALUE:
1082 if (!SYMBOLP (value))
1083 return 0;
1084 break;
1086 case IMAGE_POSITIVE_INTEGER_VALUE:
1087 if (!INTEGERP (value) || XINT (value) <= 0)
1088 return 0;
1089 break;
1091 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
1092 if (INTEGERP (value) && XINT (value) >= 0)
1093 break;
1094 if (CONSP (value)
1095 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
1096 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
1097 break;
1098 return 0;
1100 case IMAGE_ASCENT_VALUE:
1101 if (SYMBOLP (value) && EQ (value, Qcenter))
1102 break;
1103 else if (INTEGERP (value)
1104 && XINT (value) >= 0
1105 && XINT (value) <= 100)
1106 break;
1107 return 0;
1109 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
1110 if (!INTEGERP (value) || XINT (value) < 0)
1111 return 0;
1112 break;
1114 case IMAGE_DONT_CHECK_VALUE_TYPE:
1115 break;
1117 case IMAGE_FUNCTION_VALUE:
1118 value = indirect_function (value);
1119 if (SUBRP (value)
1120 || COMPILEDP (value)
1121 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
1122 break;
1123 return 0;
1125 case IMAGE_NUMBER_VALUE:
1126 if (!INTEGERP (value) && !FLOATP (value))
1127 return 0;
1128 break;
1130 case IMAGE_INTEGER_VALUE:
1131 if (!INTEGERP (value))
1132 return 0;
1133 break;
1135 case IMAGE_BOOL_VALUE:
1136 if (!NILP (value) && !EQ (value, Qt))
1137 return 0;
1138 break;
1140 default:
1141 abort ();
1142 break;
1145 if (EQ (key, QCtype) && !EQ (type, value))
1146 return 0;
1149 /* Check that all mandatory fields are present. */
1150 for (i = 0; i < nkeywords; ++i)
1151 if (keywords[i].mandatory_p && keywords[i].count == 0)
1152 return 0;
1154 return NILP (plist);
1158 /* Return the value of KEY in image specification SPEC. Value is nil
1159 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1160 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1162 static Lisp_Object
1163 image_spec_value (spec, key, found)
1164 Lisp_Object spec, key;
1165 int *found;
1167 Lisp_Object tail;
1169 xassert (valid_image_p (spec));
1171 for (tail = XCDR (spec);
1172 CONSP (tail) && CONSP (XCDR (tail));
1173 tail = XCDR (XCDR (tail)))
1175 if (EQ (XCAR (tail), key))
1177 if (found)
1178 *found = 1;
1179 return XCAR (XCDR (tail));
1183 if (found)
1184 *found = 0;
1185 return Qnil;
1189 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
1190 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1191 PIXELS non-nil means return the size in pixels, otherwise return the
1192 size in canonical character units.
1193 FRAME is the frame on which the image will be displayed. FRAME nil
1194 or omitted means use the selected frame. */)
1195 (spec, pixels, frame)
1196 Lisp_Object spec, pixels, frame;
1198 Lisp_Object size;
1200 size = Qnil;
1201 if (valid_image_p (spec))
1203 struct frame *f = check_x_frame (frame);
1204 int id = lookup_image (f, spec);
1205 struct image *img = IMAGE_FROM_ID (f, id);
1206 int width = img->width + 2 * img->hmargin;
1207 int height = img->height + 2 * img->vmargin;
1209 if (NILP (pixels))
1210 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
1211 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
1212 else
1213 size = Fcons (make_number (width), make_number (height));
1215 else
1216 error ("Invalid image specification");
1218 return size;
1222 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
1223 doc: /* Return t if image SPEC has a mask bitmap.
1224 FRAME is the frame on which the image will be displayed. FRAME nil
1225 or omitted means use the selected frame. */)
1226 (spec, frame)
1227 Lisp_Object spec, frame;
1229 Lisp_Object mask;
1231 mask = Qnil;
1232 if (valid_image_p (spec))
1234 struct frame *f = check_x_frame (frame);
1235 int id = lookup_image (f, spec);
1236 struct image *img = IMAGE_FROM_ID (f, id);
1237 if (img->mask)
1238 mask = Qt;
1240 else
1241 error ("Invalid image specification");
1243 return mask;
1246 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1247 doc: /* Return extension data for image SPEC.
1248 FRAME is the frame on which the image will be displayed. FRAME nil
1249 or omitted means use the selected frame. */)
1250 (spec, frame)
1251 Lisp_Object spec, frame;
1253 Lisp_Object ext;
1255 ext = Qnil;
1256 if (valid_image_p (spec))
1258 struct frame *f = check_x_frame (frame);
1259 int id = lookup_image (f, spec);
1260 struct image *img = IMAGE_FROM_ID (f, id);
1261 ext = img->data.lisp_val;
1264 return ext;
1268 /***********************************************************************
1269 Image type independent image structures
1270 ***********************************************************************/
1272 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1273 static void free_image P_ ((struct frame *f, struct image *img));
1274 static int check_image_size P_ ((struct frame *f, int width, int height));
1276 #define MAX_IMAGE_SIZE 6.0
1277 Lisp_Object Vmax_image_size;
1279 /* Allocate and return a new image structure for image specification
1280 SPEC. SPEC has a hash value of HASH. */
1282 static struct image *
1283 make_image (spec, hash)
1284 Lisp_Object spec;
1285 unsigned hash;
1287 struct image *img = (struct image *) xmalloc (sizeof *img);
1288 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
1290 xassert (valid_image_p (spec));
1291 bzero (img, sizeof *img);
1292 img->dependencies = NILP (file) ? Qnil : list1 (file);
1293 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1294 xassert (img->type != NULL);
1295 img->spec = spec;
1296 img->data.lisp_val = Qnil;
1297 img->ascent = DEFAULT_IMAGE_ASCENT;
1298 img->hash = hash;
1299 img->corners[BOT_CORNER] = -1; /* Full image */
1300 return img;
1304 /* Free image IMG which was used on frame F, including its resources. */
1306 static void
1307 free_image (f, img)
1308 struct frame *f;
1309 struct image *img;
1311 if (img)
1313 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1315 /* Remove IMG from the hash table of its cache. */
1316 if (img->prev)
1317 img->prev->next = img->next;
1318 else
1319 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1321 if (img->next)
1322 img->next->prev = img->prev;
1324 c->images[img->id] = NULL;
1326 /* Free resources, then free IMG. */
1327 img->type->free (f, img);
1328 xfree (img);
1332 /* Return 1 if the given widths and heights are valid for display;
1333 otherwise, return 0. */
1336 check_image_size (f, width, height)
1337 struct frame *f;
1338 int width;
1339 int height;
1341 int w, h;
1343 if (width <= 0 || height <= 0)
1344 return 0;
1346 if (INTEGERP (Vmax_image_size))
1347 w = h = XINT (Vmax_image_size);
1348 else if (FLOATP (Vmax_image_size))
1350 if (f != NULL)
1352 w = FRAME_PIXEL_WIDTH (f);
1353 h = FRAME_PIXEL_HEIGHT (f);
1355 else
1356 w = h = 1024; /* Arbitrary size for unknown frame. */
1357 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1358 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1360 else
1361 return 1;
1363 return (width <= w && height <= h);
1366 /* Prepare image IMG for display on frame F. Must be called before
1367 drawing an image. */
1369 void
1370 prepare_image_for_display (f, img)
1371 struct frame *f;
1372 struct image *img;
1374 EMACS_TIME t;
1376 /* We're about to display IMG, so set its timestamp to `now'. */
1377 EMACS_GET_TIME (t);
1378 img->timestamp = EMACS_SECS (t);
1380 /* If IMG doesn't have a pixmap yet, load it now, using the image
1381 type dependent loader function. */
1382 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1383 img->load_failed_p = img->type->load (f, img) == 0;
1388 /* Value is the number of pixels for the ascent of image IMG when
1389 drawn in face FACE. */
1392 image_ascent (img, face, slice)
1393 struct image *img;
1394 struct face *face;
1395 struct glyph_slice *slice;
1397 int height;
1398 int ascent;
1400 if (slice->height == img->height)
1401 height = img->height + img->vmargin;
1402 else if (slice->y == 0)
1403 height = slice->height + img->vmargin;
1404 else
1405 height = slice->height;
1407 if (img->ascent == CENTERED_IMAGE_ASCENT)
1409 if (face->font)
1411 #ifdef HAVE_NTGUI
1412 /* W32 specific version. Why?. ++kfs */
1413 ascent = height / 2 - (FONT_DESCENT (face->font)
1414 - FONT_BASE (face->font)) / 2;
1415 #else
1416 /* This expression is arranged so that if the image can't be
1417 exactly centered, it will be moved slightly up. This is
1418 because a typical font is `top-heavy' (due to the presence
1419 uppercase letters), so the image placement should err towards
1420 being top-heavy too. It also just generally looks better. */
1421 ascent = (height + FONT_BASE(face->font)
1422 - FONT_DESCENT(face->font) + 1) / 2;
1423 #endif /* HAVE_NTGUI */
1425 else
1426 ascent = height / 2;
1428 else
1429 ascent = (int) (height * img->ascent / 100.0);
1431 return ascent;
1435 /* Image background colors. */
1437 /* Find the "best" corner color of a bitmap.
1438 On W32, XIMG is assumed to a device context with the bitmap selected. */
1440 static RGB_PIXEL_COLOR
1441 four_corners_best (ximg, corners, width, height)
1442 XImagePtr_or_DC ximg;
1443 int *corners;
1444 unsigned long width, height;
1446 RGB_PIXEL_COLOR corner_pixels[4], best;
1447 int i, best_count;
1449 if (corners && corners[BOT_CORNER] >= 0)
1451 /* Get the colors at the corner_pixels of ximg. */
1452 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1453 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1454 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1455 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1457 else
1459 /* Get the colors at the corner_pixels of ximg. */
1460 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1461 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1462 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1463 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1465 /* Choose the most frequently found color as background. */
1466 for (i = best_count = 0; i < 4; ++i)
1468 int j, n;
1470 for (j = n = 0; j < 4; ++j)
1471 if (corner_pixels[i] == corner_pixels[j])
1472 ++n;
1474 if (n > best_count)
1475 best = corner_pixels[i], best_count = n;
1478 return best;
1481 /* Portability macros */
1483 #ifdef HAVE_NTGUI
1485 #define Destroy_Image(img_dc, prev) \
1486 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1488 #define Free_Pixmap(display, pixmap) \
1489 DeleteObject (pixmap)
1491 #elif defined (HAVE_NS)
1493 #define Destroy_Image(ximg, dummy) \
1494 ns_release_object(ximg)
1496 #define Free_Pixmap(display, pixmap) \
1497 ns_release_object(pixmap)
1499 #else
1501 #define Destroy_Image(ximg, dummy) \
1502 XDestroyImage (ximg)
1504 #define Free_Pixmap(display, pixmap) \
1505 XFreePixmap (display, pixmap)
1507 #endif /* !HAVE_NTGUI && !HAVE_NS */
1510 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1511 it is guessed heuristically. If non-zero, XIMG is an existing
1512 XImage object (or device context with the image selected on W32) to
1513 use for the heuristic. */
1515 RGB_PIXEL_COLOR
1516 image_background (img, f, ximg)
1517 struct image *img;
1518 struct frame *f;
1519 XImagePtr_or_DC ximg;
1521 if (! img->background_valid)
1522 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1524 int free_ximg = !ximg;
1525 #ifdef HAVE_NTGUI
1526 HGDIOBJ prev;
1527 #endif /* HAVE_NTGUI */
1529 if (free_ximg)
1531 #ifndef HAVE_NTGUI
1532 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1533 0, 0, img->width, img->height, ~0, ZPixmap);
1534 #else
1535 HDC frame_dc = get_frame_dc (f);
1536 ximg = CreateCompatibleDC (frame_dc);
1537 release_frame_dc (f, frame_dc);
1538 prev = SelectObject (ximg, img->pixmap);
1539 #endif /* !HAVE_NTGUI */
1542 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1544 if (free_ximg)
1545 Destroy_Image (ximg, prev);
1547 img->background_valid = 1;
1550 return img->background;
1553 /* Return the `background_transparent' field of IMG. If IMG doesn't
1554 have one yet, it is guessed heuristically. If non-zero, MASK is an
1555 existing XImage object to use for the heuristic. */
1558 image_background_transparent (img, f, mask)
1559 struct image *img;
1560 struct frame *f;
1561 XImagePtr_or_DC mask;
1563 if (! img->background_transparent_valid)
1564 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1566 if (img->mask)
1568 int free_mask = !mask;
1569 #ifdef HAVE_NTGUI
1570 HGDIOBJ prev;
1571 #endif /* HAVE_NTGUI */
1573 if (free_mask)
1575 #ifndef HAVE_NTGUI
1576 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1577 0, 0, img->width, img->height, ~0, ZPixmap);
1578 #else
1579 HDC frame_dc = get_frame_dc (f);
1580 mask = CreateCompatibleDC (frame_dc);
1581 release_frame_dc (f, frame_dc);
1582 prev = SelectObject (mask, img->mask);
1583 #endif /* HAVE_NTGUI */
1586 img->background_transparent
1587 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1589 if (free_mask)
1590 Destroy_Image (mask, prev);
1592 else
1593 img->background_transparent = 0;
1595 img->background_transparent_valid = 1;
1598 return img->background_transparent;
1602 /***********************************************************************
1603 Helper functions for X image types
1604 ***********************************************************************/
1606 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1607 int, int));
1608 static void x_clear_image P_ ((struct frame *f, struct image *img));
1609 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1610 struct image *img,
1611 Lisp_Object color_name,
1612 unsigned long dflt));
1615 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1616 free the pixmap if any. MASK_P non-zero means clear the mask
1617 pixmap if any. COLORS_P non-zero means free colors allocated for
1618 the image, if any. */
1620 static void
1621 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1622 struct frame *f;
1623 struct image *img;
1624 int pixmap_p, mask_p, colors_p;
1626 if (pixmap_p && img->pixmap)
1628 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1629 img->pixmap = NO_PIXMAP;
1630 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1631 img->background_valid = 0;
1634 if (mask_p && img->mask)
1636 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1637 img->mask = NO_PIXMAP;
1638 img->background_transparent_valid = 0;
1641 if (colors_p && img->ncolors)
1643 /* W32_TODO: color table support. */
1644 #ifdef HAVE_X_WINDOWS
1645 x_free_colors (f, img->colors, img->ncolors);
1646 #endif /* HAVE_X_WINDOWS */
1647 xfree (img->colors);
1648 img->colors = NULL;
1649 img->ncolors = 0;
1654 /* Free X resources of image IMG which is used on frame F. */
1656 static void
1657 x_clear_image (f, img)
1658 struct frame *f;
1659 struct image *img;
1661 BLOCK_INPUT;
1662 x_clear_image_1 (f, img, 1, 1, 1);
1663 UNBLOCK_INPUT;
1667 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1668 cannot be allocated, use DFLT. Add a newly allocated color to
1669 IMG->colors, so that it can be freed again. Value is the pixel
1670 color. */
1672 static unsigned long
1673 x_alloc_image_color (f, img, color_name, dflt)
1674 struct frame *f;
1675 struct image *img;
1676 Lisp_Object color_name;
1677 unsigned long dflt;
1679 XColor color;
1680 unsigned long result;
1682 xassert (STRINGP (color_name));
1684 if (x_defined_color (f, SDATA (color_name), &color, 1))
1686 /* This isn't called frequently so we get away with simply
1687 reallocating the color vector to the needed size, here. */
1688 ++img->ncolors;
1689 img->colors =
1690 (unsigned long *) xrealloc (img->colors,
1691 img->ncolors * sizeof *img->colors);
1692 img->colors[img->ncolors - 1] = color.pixel;
1693 result = color.pixel;
1695 else
1696 result = dflt;
1698 return result;
1703 /***********************************************************************
1704 Image Cache
1705 ***********************************************************************/
1707 static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
1708 static void cache_image P_ ((struct frame *f, struct image *img));
1709 static void postprocess_image P_ ((struct frame *, struct image *));
1711 /* Return a new, initialized image cache that is allocated from the
1712 heap. Call free_image_cache to free an image cache. */
1714 struct image_cache *
1715 make_image_cache ()
1717 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1718 int size;
1720 bzero (c, sizeof *c);
1721 c->size = 50;
1722 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1723 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1724 c->buckets = (struct image **) xmalloc (size);
1725 bzero (c->buckets, size);
1726 return c;
1730 /* Find an image matching SPEC in the cache, and return it. If no
1731 image is found, return NULL. */
1732 static struct image *
1733 search_image_cache (f, spec, hash)
1734 struct frame *f;
1735 Lisp_Object spec;
1736 unsigned hash;
1738 struct image *img;
1739 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1740 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1742 if (!c) return NULL;
1744 /* If the image spec does not specify a background color, the cached
1745 image must have the same background color as the current frame.
1746 The foreground color must also match, for the sake of monochrome
1747 images.
1749 In fact, we could ignore the foreground color matching condition
1750 for color images, or if the image spec specifies :foreground;
1751 similarly we could ignore the background color matching condition
1752 for formats that don't use transparency (such as jpeg), or if the
1753 image spec specifies :background. However, the extra memory
1754 usage is probably negligible in practice, so we don't bother. */
1756 for (img = c->buckets[i]; img; img = img->next)
1757 if (img->hash == hash
1758 && !NILP (Fequal (img->spec, spec))
1759 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1760 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1761 break;
1762 return img;
1766 /* Search frame F for an image with spec SPEC, and free it. */
1768 static void
1769 uncache_image (f, spec)
1770 struct frame *f;
1771 Lisp_Object spec;
1773 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1774 if (img)
1775 free_image (f, img);
1779 /* Free image cache of frame F. Be aware that X frames share images
1780 caches. */
1782 void
1783 free_image_cache (f)
1784 struct frame *f;
1786 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1787 if (c)
1789 int i;
1791 /* Cache should not be referenced by any frame when freed. */
1792 xassert (c->refcount == 0);
1794 for (i = 0; i < c->used; ++i)
1795 free_image (f, c->images[i]);
1796 xfree (c->images);
1797 xfree (c->buckets);
1798 xfree (c);
1799 FRAME_IMAGE_CACHE (f) = NULL;
1804 /* Clear image cache of frame F. FILTER=t means free all images.
1805 FILTER=nil means clear only images that haven't been
1806 displayed for some time.
1807 Else, only free the images which have FILTER in their `dependencies'.
1808 Should be called from time to time to reduce the number of loaded images.
1809 If image-cache-eviction-delay is non-nil, this frees images in the cache
1810 which weren't displayed for at least that many seconds. */
1812 void
1813 clear_image_cache (struct frame *f, Lisp_Object filter)
1815 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1817 if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
1819 EMACS_TIME t;
1820 unsigned long old;
1821 int i, nfreed;
1823 EMACS_GET_TIME (t);
1824 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1826 /* Block input so that we won't be interrupted by a SIGIO
1827 while being in an inconsistent state. */
1828 BLOCK_INPUT;
1830 for (i = nfreed = 0; i < c->used; ++i)
1832 struct image *img = c->images[i];
1833 if (img != NULL
1834 && (NILP (filter) ? img->timestamp < old
1835 : (EQ (Qt, filter)
1836 || !NILP (Fmember (filter, img->dependencies)))))
1838 free_image (f, img);
1839 ++nfreed;
1843 /* We may be clearing the image cache because, for example,
1844 Emacs was iconified for a longer period of time. In that
1845 case, current matrices may still contain references to
1846 images freed above. So, clear these matrices. */
1847 if (nfreed)
1849 Lisp_Object tail, frame;
1851 FOR_EACH_FRAME (tail, frame)
1853 struct frame *f = XFRAME (frame);
1854 if (FRAME_IMAGE_CACHE (f) == c)
1855 clear_current_matrices (f);
1858 ++windows_or_buffers_changed;
1861 UNBLOCK_INPUT;
1865 void
1866 clear_image_caches (Lisp_Object filter)
1868 /* FIXME: We want to do
1869 * struct terminal *t;
1870 * for (t = terminal_list; t; t = t->next_terminal)
1871 * clear_image_cache (t, filter); */
1872 Lisp_Object tail, frame;
1873 FOR_EACH_FRAME (tail, frame)
1874 if (FRAME_WINDOW_P (XFRAME (frame)))
1875 clear_image_cache (XFRAME (frame), filter);
1878 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1879 0, 1, 0,
1880 doc: /* Clear the image cache.
1881 FILTER nil or a frame means clear all images in the selected frame.
1882 FILTER t means clear the image caches of all frames.
1883 Anything else, means only clear those images which refer to FILTER,
1884 which is then usually a filename. */)
1885 (filter)
1886 Lisp_Object filter;
1888 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1889 clear_image_caches (filter);
1890 else
1891 clear_image_cache (check_x_frame (filter), Qt);
1893 return Qnil;
1897 DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
1898 1, 2, 0,
1899 doc: /* Refresh the image with specification SPEC on frame FRAME.
1900 If SPEC specifies an image file, the displayed image is updated with
1901 the current contents of that file.
1902 FRAME nil or omitted means use the selected frame.
1903 FRAME t means refresh the image on all frames. */)
1904 (spec, frame)
1905 Lisp_Object spec, frame;
1907 if (!valid_image_p (spec))
1908 error ("Invalid image specification");
1910 if (EQ (frame, Qt))
1912 Lisp_Object tail;
1913 FOR_EACH_FRAME (tail, frame)
1915 struct frame *f = XFRAME (frame);
1916 if (FRAME_WINDOW_P (f))
1917 uncache_image (f, spec);
1920 else
1921 uncache_image (check_x_frame (frame), spec);
1923 return Qnil;
1927 /* Compute masks and transform image IMG on frame F, as specified
1928 by the image's specification, */
1930 static void
1931 postprocess_image (f, img)
1932 struct frame *f;
1933 struct image *img;
1935 /* Manipulation of the image's mask. */
1936 if (img->pixmap)
1938 Lisp_Object conversion, spec;
1939 Lisp_Object mask;
1941 spec = img->spec;
1943 /* `:heuristic-mask t'
1944 `:mask heuristic'
1945 means build a mask heuristically.
1946 `:heuristic-mask (R G B)'
1947 `:mask (heuristic (R G B))'
1948 means build a mask from color (R G B) in the
1949 image.
1950 `:mask nil'
1951 means remove a mask, if any. */
1953 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1954 if (!NILP (mask))
1955 x_build_heuristic_mask (f, img, mask);
1956 else
1958 int found_p;
1960 mask = image_spec_value (spec, QCmask, &found_p);
1962 if (EQ (mask, Qheuristic))
1963 x_build_heuristic_mask (f, img, Qt);
1964 else if (CONSP (mask)
1965 && EQ (XCAR (mask), Qheuristic))
1967 if (CONSP (XCDR (mask)))
1968 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1969 else
1970 x_build_heuristic_mask (f, img, XCDR (mask));
1972 else if (NILP (mask) && found_p && img->mask)
1974 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1975 img->mask = NO_PIXMAP;
1980 /* Should we apply an image transformation algorithm? */
1981 conversion = image_spec_value (spec, QCconversion, NULL);
1982 if (EQ (conversion, Qdisabled))
1983 x_disable_image (f, img);
1984 else if (EQ (conversion, Qlaplace))
1985 x_laplace (f, img);
1986 else if (EQ (conversion, Qemboss))
1987 x_emboss (f, img);
1988 else if (CONSP (conversion)
1989 && EQ (XCAR (conversion), Qedge_detection))
1991 Lisp_Object tem;
1992 tem = XCDR (conversion);
1993 if (CONSP (tem))
1994 x_edge_detection (f, img,
1995 Fplist_get (tem, QCmatrix),
1996 Fplist_get (tem, QCcolor_adjustment));
2002 /* Return the id of image with Lisp specification SPEC on frame F.
2003 SPEC must be a valid Lisp image specification (see valid_image_p). */
2006 lookup_image (f, spec)
2007 struct frame *f;
2008 Lisp_Object spec;
2010 struct image_cache *c;
2011 struct image *img;
2012 unsigned hash;
2013 struct gcpro gcpro1;
2014 EMACS_TIME now;
2016 /* F must be a window-system frame, and SPEC must be a valid image
2017 specification. */
2018 xassert (FRAME_WINDOW_P (f));
2019 xassert (valid_image_p (spec));
2021 c = FRAME_IMAGE_CACHE (f);
2023 GCPRO1 (spec);
2025 /* Look up SPEC in the hash table of the image cache. */
2026 hash = sxhash (spec, 0);
2027 img = search_image_cache (f, spec, hash);
2028 if (img && img->load_failed_p)
2030 free_image (f, img);
2031 img = NULL;
2034 /* If not found, create a new image and cache it. */
2035 if (img == NULL)
2037 extern Lisp_Object Qpostscript;
2039 BLOCK_INPUT;
2040 img = make_image (spec, hash);
2041 cache_image (f, img);
2042 img->load_failed_p = img->type->load (f, img) == 0;
2043 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
2044 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
2046 /* If we can't load the image, and we don't have a width and
2047 height, use some arbitrary width and height so that we can
2048 draw a rectangle for it. */
2049 if (img->load_failed_p)
2051 Lisp_Object value;
2053 value = image_spec_value (spec, QCwidth, NULL);
2054 img->width = (INTEGERP (value)
2055 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
2056 value = image_spec_value (spec, QCheight, NULL);
2057 img->height = (INTEGERP (value)
2058 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
2060 else
2062 /* Handle image type independent image attributes
2063 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2064 `:background COLOR'. */
2065 Lisp_Object ascent, margin, relief, bg;
2067 ascent = image_spec_value (spec, QCascent, NULL);
2068 if (INTEGERP (ascent))
2069 img->ascent = XFASTINT (ascent);
2070 else if (EQ (ascent, Qcenter))
2071 img->ascent = CENTERED_IMAGE_ASCENT;
2073 margin = image_spec_value (spec, QCmargin, NULL);
2074 if (INTEGERP (margin) && XINT (margin) >= 0)
2075 img->vmargin = img->hmargin = XFASTINT (margin);
2076 else if (CONSP (margin) && INTEGERP (XCAR (margin))
2077 && INTEGERP (XCDR (margin)))
2079 if (XINT (XCAR (margin)) > 0)
2080 img->hmargin = XFASTINT (XCAR (margin));
2081 if (XINT (XCDR (margin)) > 0)
2082 img->vmargin = XFASTINT (XCDR (margin));
2085 relief = image_spec_value (spec, QCrelief, NULL);
2086 if (INTEGERP (relief))
2088 img->relief = XINT (relief);
2089 img->hmargin += eabs (img->relief);
2090 img->vmargin += eabs (img->relief);
2093 if (! img->background_valid)
2095 bg = image_spec_value (img->spec, QCbackground, NULL);
2096 if (!NILP (bg))
2098 img->background
2099 = x_alloc_image_color (f, img, bg,
2100 FRAME_BACKGROUND_PIXEL (f));
2101 img->background_valid = 1;
2105 /* Do image transformations and compute masks, unless we
2106 don't have the image yet. */
2107 if (!EQ (*img->type->type, Qpostscript))
2108 postprocess_image (f, img);
2111 UNBLOCK_INPUT;
2114 /* We're using IMG, so set its timestamp to `now'. */
2115 EMACS_GET_TIME (now);
2116 img->timestamp = EMACS_SECS (now);
2118 UNGCPRO;
2120 /* Value is the image id. */
2121 return img->id;
2125 /* Cache image IMG in the image cache of frame F. */
2127 static void
2128 cache_image (f, img)
2129 struct frame *f;
2130 struct image *img;
2132 struct image_cache *c = FRAME_IMAGE_CACHE (f);
2133 int i;
2135 /* Find a free slot in c->images. */
2136 for (i = 0; i < c->used; ++i)
2137 if (c->images[i] == NULL)
2138 break;
2140 /* If no free slot found, maybe enlarge c->images. */
2141 if (i == c->used && c->used == c->size)
2143 c->size *= 2;
2144 c->images = (struct image **) xrealloc (c->images,
2145 c->size * sizeof *c->images);
2148 /* Add IMG to c->images, and assign IMG an id. */
2149 c->images[i] = img;
2150 img->id = i;
2151 if (i == c->used)
2152 ++c->used;
2154 /* Add IMG to the cache's hash table. */
2155 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
2156 img->next = c->buckets[i];
2157 if (img->next)
2158 img->next->prev = img;
2159 img->prev = NULL;
2160 c->buckets[i] = img;
2164 /* Call FN on every image in the image cache of frame F. Used to mark
2165 Lisp Objects in the image cache. */
2167 /* Mark Lisp objects in image IMG. */
2169 static void
2170 mark_image (img)
2171 struct image *img;
2173 mark_object (img->spec);
2174 mark_object (img->dependencies);
2176 if (!NILP (img->data.lisp_val))
2177 mark_object (img->data.lisp_val);
2181 void
2182 mark_image_cache (struct image_cache *c)
2184 if (c)
2186 int i;
2187 for (i = 0; i < c->used; ++i)
2188 if (c->images[i])
2189 mark_image (c->images[i]);
2195 /***********************************************************************
2196 X / NS / W32 support code
2197 ***********************************************************************/
2199 #ifdef HAVE_NTGUI
2201 /* Macro for defining functions that will be loaded from image DLLs. */
2202 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2204 /* Macro for loading those image functions from the library. */
2205 #define LOAD_IMGLIB_FN(lib,func) { \
2206 fn_##func = (void *) GetProcAddress (lib, #func); \
2207 if (!fn_##func) return 0; \
2210 /* Load a DLL implementing an image type.
2211 The `image-library-alist' variable associates a symbol,
2212 identifying an image type, to a list of possible filenames.
2213 The function returns NULL if no library could be loaded for
2214 the given image type, or if the library was previously loaded;
2215 else the handle of the DLL. */
2216 static HMODULE
2217 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
2219 HMODULE library = NULL;
2221 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2223 Lisp_Object dlls = Fassq (type, libraries);
2225 if (CONSP (dlls))
2226 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2228 CHECK_STRING_CAR (dlls);
2229 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2230 break;
2234 return library;
2237 #endif /* HAVE_NTGUI */
2239 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2240 XImagePtr *, Pixmap *));
2241 static void x_destroy_x_image P_ ((XImagePtr));
2242 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2245 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2246 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2247 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2248 via xmalloc. Print error messages via image_error if an error
2249 occurs. Value is non-zero if successful.
2251 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2252 should indicate the bit depth of the image. */
2254 static int
2255 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2256 struct frame *f;
2257 int width, height, depth;
2258 XImagePtr *ximg;
2259 Pixmap *pixmap;
2261 #ifdef HAVE_X_WINDOWS
2262 Display *display = FRAME_X_DISPLAY (f);
2263 Window window = FRAME_X_WINDOW (f);
2264 Screen *screen = FRAME_X_SCREEN (f);
2266 xassert (interrupt_input_blocked);
2268 if (depth <= 0)
2269 depth = DefaultDepthOfScreen (screen);
2270 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2271 depth, ZPixmap, 0, NULL, width, height,
2272 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2273 if (*ximg == NULL)
2275 image_error ("Unable to allocate X image", Qnil, Qnil);
2276 return 0;
2279 /* Allocate image raster. */
2280 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2282 /* Allocate a pixmap of the same size. */
2283 *pixmap = XCreatePixmap (display, window, width, height, depth);
2284 if (*pixmap == NO_PIXMAP)
2286 x_destroy_x_image (*ximg);
2287 *ximg = NULL;
2288 image_error ("Unable to create X pixmap", Qnil, Qnil);
2289 return 0;
2292 return 1;
2293 #endif /* HAVE_X_WINDOWS */
2295 #ifdef HAVE_NTGUI
2297 BITMAPINFOHEADER *header;
2298 HDC hdc;
2299 int scanline_width_bits;
2300 int remainder;
2301 int palette_colors = 0;
2303 if (depth == 0)
2304 depth = 24;
2306 if (depth != 1 && depth != 4 && depth != 8
2307 && depth != 16 && depth != 24 && depth != 32)
2309 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2310 return 0;
2313 scanline_width_bits = width * depth;
2314 remainder = scanline_width_bits % 32;
2316 if (remainder)
2317 scanline_width_bits += 32 - remainder;
2319 /* Bitmaps with a depth less than 16 need a palette. */
2320 /* BITMAPINFO structure already contains the first RGBQUAD. */
2321 if (depth < 16)
2322 palette_colors = 1 << depth - 1;
2324 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2325 if (*ximg == NULL)
2327 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2328 return 0;
2331 header = &((*ximg)->info.bmiHeader);
2332 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2333 header->biSize = sizeof (*header);
2334 header->biWidth = width;
2335 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2336 header->biPlanes = 1;
2337 header->biBitCount = depth;
2338 header->biCompression = BI_RGB;
2339 header->biClrUsed = palette_colors;
2341 /* TODO: fill in palette. */
2342 if (depth == 1)
2344 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2345 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2346 (*ximg)->info.bmiColors[0].rgbRed = 0;
2347 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2348 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2349 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2350 (*ximg)->info.bmiColors[1].rgbRed = 255;
2351 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2354 hdc = get_frame_dc (f);
2356 /* Create a DIBSection and raster array for the bitmap,
2357 and store its handle in *pixmap. */
2358 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2359 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2360 /* casting avoids a GCC warning */
2361 (void **)&((*ximg)->data), NULL, 0);
2363 /* Realize display palette and garbage all frames. */
2364 release_frame_dc (f, hdc);
2366 if (*pixmap == NULL)
2368 DWORD err = GetLastError ();
2369 Lisp_Object errcode;
2370 /* All system errors are < 10000, so the following is safe. */
2371 XSETINT (errcode, (int) err);
2372 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2373 x_destroy_x_image (*ximg);
2374 return 0;
2377 return 1;
2379 #endif /* HAVE_NTGUI */
2381 #ifdef HAVE_NS
2382 *pixmap = ns_image_for_XPM(width, height, depth);
2383 if (*pixmap == 0)
2385 *ximg = NULL;
2386 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
2387 return 0;
2389 *ximg = *pixmap;
2390 return 1;
2391 #endif
2395 /* Destroy XImage XIMG. Free XIMG->data. */
2397 static void
2398 x_destroy_x_image (ximg)
2399 XImagePtr ximg;
2401 xassert (interrupt_input_blocked);
2402 if (ximg)
2404 #ifdef HAVE_X_WINDOWS
2405 xfree (ximg->data);
2406 ximg->data = NULL;
2407 XDestroyImage (ximg);
2408 #endif /* HAVE_X_WINDOWS */
2409 #ifdef HAVE_NTGUI
2410 /* Data will be freed by DestroyObject. */
2411 ximg->data = NULL;
2412 xfree (ximg);
2413 #endif /* HAVE_NTGUI */
2414 #ifdef HAVE_NS
2415 ns_release_object(ximg);
2416 #endif /* HAVE_NS */
2421 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2422 are width and height of both the image and pixmap. */
2424 static void
2425 x_put_x_image (f, ximg, pixmap, width, height)
2426 struct frame *f;
2427 XImagePtr ximg;
2428 Pixmap pixmap;
2429 int width, height;
2431 #ifdef HAVE_X_WINDOWS
2432 GC gc;
2434 xassert (interrupt_input_blocked);
2435 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2436 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2437 XFreeGC (FRAME_X_DISPLAY (f), gc);
2438 #endif /* HAVE_X_WINDOWS */
2440 #ifdef HAVE_NTGUI
2441 #if 0 /* I don't think this is necessary looking at where it is used. */
2442 HDC hdc = get_frame_dc (f);
2443 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2444 release_frame_dc (f, hdc);
2445 #endif
2446 #endif /* HAVE_NTGUI */
2448 #ifdef HAVE_NS
2449 xassert (ximg == pixmap);
2450 ns_retain_object(ximg);
2451 #endif
2455 /***********************************************************************
2456 File Handling
2457 ***********************************************************************/
2459 static unsigned char *slurp_file P_ ((char *, int *));
2462 /* Find image file FILE. Look in data-directory/images, then
2463 x-bitmap-file-path. Value is the encoded full name of the file
2464 found, or nil if not found. */
2466 Lisp_Object
2467 x_find_image_file (file)
2468 Lisp_Object file;
2470 Lisp_Object file_found, search_path;
2471 struct gcpro gcpro1, gcpro2;
2472 int fd;
2474 file_found = Qnil;
2475 /* TODO I think this should use something like image-load-path
2476 instead. Unfortunately, that can contain non-string elements. */
2477 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2478 Vdata_directory),
2479 Vx_bitmap_file_path);
2480 GCPRO2 (file_found, search_path);
2482 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2483 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2485 if (fd == -1)
2486 file_found = Qnil;
2487 else
2489 file_found = ENCODE_FILE (file_found);
2490 close (fd);
2493 UNGCPRO;
2494 return file_found;
2498 /* Read FILE into memory. Value is a pointer to a buffer allocated
2499 with xmalloc holding FILE's contents. Value is null if an error
2500 occurred. *SIZE is set to the size of the file. */
2502 static unsigned char *
2503 slurp_file (file, size)
2504 char *file;
2505 int *size;
2507 FILE *fp = NULL;
2508 unsigned char *buf = NULL;
2509 struct stat st;
2511 if (stat (file, &st) == 0
2512 && (fp = fopen (file, "rb")) != NULL
2513 && (buf = (unsigned char *) xmalloc (st.st_size),
2514 fread (buf, 1, st.st_size, fp) == st.st_size))
2516 *size = st.st_size;
2517 fclose (fp);
2519 else
2521 if (fp)
2522 fclose (fp);
2523 if (buf)
2525 xfree (buf);
2526 buf = NULL;
2530 return buf;
2535 /***********************************************************************
2536 XBM images
2537 ***********************************************************************/
2539 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
2540 static int xbm_load P_ ((struct frame *f, struct image *img));
2541 static int xbm_load_image P_ ((struct frame *f, struct image *img,
2542 unsigned char *, unsigned char *));
2543 static int xbm_image_p P_ ((Lisp_Object object));
2544 static int xbm_read_bitmap_data P_ ((struct frame *f,
2545 unsigned char *, unsigned char *,
2546 int *, int *, unsigned char **));
2547 static int xbm_file_p P_ ((Lisp_Object));
2550 /* Indices of image specification fields in xbm_format, below. */
2552 enum xbm_keyword_index
2554 XBM_TYPE,
2555 XBM_FILE,
2556 XBM_WIDTH,
2557 XBM_HEIGHT,
2558 XBM_DATA,
2559 XBM_FOREGROUND,
2560 XBM_BACKGROUND,
2561 XBM_ASCENT,
2562 XBM_MARGIN,
2563 XBM_RELIEF,
2564 XBM_ALGORITHM,
2565 XBM_HEURISTIC_MASK,
2566 XBM_MASK,
2567 XBM_LAST
2570 /* Vector of image_keyword structures describing the format
2571 of valid XBM image specifications. */
2573 static struct image_keyword xbm_format[XBM_LAST] =
2575 {":type", IMAGE_SYMBOL_VALUE, 1},
2576 {":file", IMAGE_STRING_VALUE, 0},
2577 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2578 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2579 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2580 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2581 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2582 {":ascent", IMAGE_ASCENT_VALUE, 0},
2583 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2584 {":relief", IMAGE_INTEGER_VALUE, 0},
2585 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2586 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2587 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2590 /* Structure describing the image type XBM. */
2592 static struct image_type xbm_type =
2594 &Qxbm,
2595 xbm_image_p,
2596 xbm_load,
2597 x_clear_image,
2598 NULL
2601 /* Tokens returned from xbm_scan. */
2603 enum xbm_token
2605 XBM_TK_IDENT = 256,
2606 XBM_TK_NUMBER
2610 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2611 A valid specification is a list starting with the symbol `image'
2612 The rest of the list is a property list which must contain an
2613 entry `:type xbm..
2615 If the specification specifies a file to load, it must contain
2616 an entry `:file FILENAME' where FILENAME is a string.
2618 If the specification is for a bitmap loaded from memory it must
2619 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2620 WIDTH and HEIGHT are integers > 0. DATA may be:
2622 1. a string large enough to hold the bitmap data, i.e. it must
2623 have a size >= (WIDTH + 7) / 8 * HEIGHT
2625 2. a bool-vector of size >= WIDTH * HEIGHT
2627 3. a vector of strings or bool-vectors, one for each line of the
2628 bitmap.
2630 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2631 may not be specified in this case because they are defined in the
2632 XBM file.
2634 Both the file and data forms may contain the additional entries
2635 `:background COLOR' and `:foreground COLOR'. If not present,
2636 foreground and background of the frame on which the image is
2637 displayed is used. */
2639 static int
2640 xbm_image_p (object)
2641 Lisp_Object object;
2643 struct image_keyword kw[XBM_LAST];
2645 bcopy (xbm_format, kw, sizeof kw);
2646 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2647 return 0;
2649 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2651 if (kw[XBM_FILE].count)
2653 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2654 return 0;
2656 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2658 /* In-memory XBM file. */
2659 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2660 return 0;
2662 else
2664 Lisp_Object data;
2665 int width, height;
2667 /* Entries for `:width', `:height' and `:data' must be present. */
2668 if (!kw[XBM_WIDTH].count
2669 || !kw[XBM_HEIGHT].count
2670 || !kw[XBM_DATA].count)
2671 return 0;
2673 data = kw[XBM_DATA].value;
2674 width = XFASTINT (kw[XBM_WIDTH].value);
2675 height = XFASTINT (kw[XBM_HEIGHT].value);
2677 /* Check type of data, and width and height against contents of
2678 data. */
2679 if (VECTORP (data))
2681 int i;
2683 /* Number of elements of the vector must be >= height. */
2684 if (XVECTOR (data)->size < height)
2685 return 0;
2687 /* Each string or bool-vector in data must be large enough
2688 for one line of the image. */
2689 for (i = 0; i < height; ++i)
2691 Lisp_Object elt = XVECTOR (data)->contents[i];
2693 if (STRINGP (elt))
2695 if (SCHARS (elt)
2696 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2697 return 0;
2699 else if (BOOL_VECTOR_P (elt))
2701 if (XBOOL_VECTOR (elt)->size < width)
2702 return 0;
2704 else
2705 return 0;
2708 else if (STRINGP (data))
2710 if (SCHARS (data)
2711 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2712 return 0;
2714 else if (BOOL_VECTOR_P (data))
2716 if (XBOOL_VECTOR (data)->size < width * height)
2717 return 0;
2719 else
2720 return 0;
2723 return 1;
2727 /* Scan a bitmap file. FP is the stream to read from. Value is
2728 either an enumerator from enum xbm_token, or a character for a
2729 single-character token, or 0 at end of file. If scanning an
2730 identifier, store the lexeme of the identifier in SVAL. If
2731 scanning a number, store its value in *IVAL. */
2733 static int
2734 xbm_scan (s, end, sval, ival)
2735 unsigned char **s, *end;
2736 char *sval;
2737 int *ival;
2739 unsigned int c;
2741 loop:
2743 /* Skip white space. */
2744 while (*s < end && (c = *(*s)++, isspace (c)))
2747 if (*s >= end)
2748 c = 0;
2749 else if (isdigit (c))
2751 int value = 0, digit;
2753 if (c == '0' && *s < end)
2755 c = *(*s)++;
2756 if (c == 'x' || c == 'X')
2758 while (*s < end)
2760 c = *(*s)++;
2761 if (isdigit (c))
2762 digit = c - '0';
2763 else if (c >= 'a' && c <= 'f')
2764 digit = c - 'a' + 10;
2765 else if (c >= 'A' && c <= 'F')
2766 digit = c - 'A' + 10;
2767 else
2768 break;
2769 value = 16 * value + digit;
2772 else if (isdigit (c))
2774 value = c - '0';
2775 while (*s < end
2776 && (c = *(*s)++, isdigit (c)))
2777 value = 8 * value + c - '0';
2780 else
2782 value = c - '0';
2783 while (*s < end
2784 && (c = *(*s)++, isdigit (c)))
2785 value = 10 * value + c - '0';
2788 if (*s < end)
2789 *s = *s - 1;
2790 *ival = value;
2791 c = XBM_TK_NUMBER;
2793 else if (isalpha (c) || c == '_')
2795 *sval++ = c;
2796 while (*s < end
2797 && (c = *(*s)++, (isalnum (c) || c == '_')))
2798 *sval++ = c;
2799 *sval = 0;
2800 if (*s < end)
2801 *s = *s - 1;
2802 c = XBM_TK_IDENT;
2804 else if (c == '/' && **s == '*')
2806 /* C-style comment. */
2807 ++*s;
2808 while (**s && (**s != '*' || *(*s + 1) != '/'))
2809 ++*s;
2810 if (**s)
2812 *s += 2;
2813 goto loop;
2817 return c;
2820 #ifdef HAVE_NTGUI
2822 /* Create a Windows bitmap from X bitmap data. */
2823 static HBITMAP
2824 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2826 static unsigned char swap_nibble[16]
2827 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2828 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2829 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2830 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2831 int i, j, w1, w2;
2832 unsigned char *bits, *p;
2833 HBITMAP bmp;
2835 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2836 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2837 bits = (unsigned char *) alloca (height * w2);
2838 bzero (bits, height * w2);
2839 for (i = 0; i < height; i++)
2841 p = bits + i*w2;
2842 for (j = 0; j < w1; j++)
2844 /* Bitswap XBM bytes to match how Windows does things. */
2845 unsigned char c = *data++;
2846 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2847 | (swap_nibble[(c>>4) & 0xf]));
2850 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2852 return bmp;
2855 static void
2856 convert_mono_to_color_image (f, img, foreground, background)
2857 struct frame *f;
2858 struct image *img;
2859 COLORREF foreground, background;
2861 HDC hdc, old_img_dc, new_img_dc;
2862 HGDIOBJ old_prev, new_prev;
2863 HBITMAP new_pixmap;
2865 hdc = get_frame_dc (f);
2866 old_img_dc = CreateCompatibleDC (hdc);
2867 new_img_dc = CreateCompatibleDC (hdc);
2868 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
2869 release_frame_dc (f, hdc);
2870 old_prev = SelectObject (old_img_dc, img->pixmap);
2871 new_prev = SelectObject (new_img_dc, new_pixmap);
2872 /* Windows convention for mono bitmaps is black = background,
2873 white = foreground. */
2874 SetTextColor (new_img_dc, background);
2875 SetBkColor (new_img_dc, foreground);
2877 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
2878 0, 0, SRCCOPY);
2880 SelectObject (old_img_dc, old_prev);
2881 SelectObject (new_img_dc, new_prev);
2882 DeleteDC (old_img_dc);
2883 DeleteDC (new_img_dc);
2884 DeleteObject (img->pixmap);
2885 if (new_pixmap == 0)
2886 fprintf (stderr, "Failed to convert image to color.\n");
2887 else
2888 img->pixmap = new_pixmap;
2891 #define XBM_BIT_SHUFFLE(b) (~(b))
2893 #else
2895 #define XBM_BIT_SHUFFLE(b) (b)
2897 #endif /* HAVE_NTGUI */
2900 static void
2901 Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
2902 struct frame *f;
2903 struct image *img;
2904 char *data;
2905 RGB_PIXEL_COLOR fg, bg;
2906 int non_default_colors;
2908 #ifdef HAVE_NTGUI
2909 img->pixmap
2910 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
2912 /* If colors were specified, transfer the bitmap to a color one. */
2913 if (non_default_colors)
2914 convert_mono_to_color_image (f, img, fg, bg);
2916 #elif defined (HAVE_NS)
2917 img->pixmap = ns_image_from_XBM(data, img->width, img->height);
2919 #else
2920 img->pixmap
2921 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
2922 FRAME_X_WINDOW (f),
2923 data,
2924 img->width, img->height,
2925 fg, bg,
2926 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
2927 #endif /* !HAVE_NTGUI && !HAVE_NS */
2932 /* Replacement for XReadBitmapFileData which isn't available under old
2933 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2934 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2935 the image. Return in *DATA the bitmap data allocated with xmalloc.
2936 Value is non-zero if successful. DATA null means just test if
2937 CONTENTS looks like an in-memory XBM file. */
2939 static int
2940 xbm_read_bitmap_data (f, contents, end, width, height, data)
2941 struct frame *f;
2942 unsigned char *contents, *end;
2943 int *width, *height;
2944 unsigned char **data;
2946 unsigned char *s = contents;
2947 char buffer[BUFSIZ];
2948 int padding_p = 0;
2949 int v10 = 0;
2950 int bytes_per_line, i, nbytes;
2951 unsigned char *p;
2952 int value;
2953 int LA1;
2955 #define match() \
2956 LA1 = xbm_scan (&s, end, buffer, &value)
2958 #define expect(TOKEN) \
2959 if (LA1 != (TOKEN)) \
2960 goto failure; \
2961 else \
2962 match ()
2964 #define expect_ident(IDENT) \
2965 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2966 match (); \
2967 else \
2968 goto failure
2970 *width = *height = -1;
2971 if (data)
2972 *data = NULL;
2973 LA1 = xbm_scan (&s, end, buffer, &value);
2975 /* Parse defines for width, height and hot-spots. */
2976 while (LA1 == '#')
2978 match ();
2979 expect_ident ("define");
2980 expect (XBM_TK_IDENT);
2982 if (LA1 == XBM_TK_NUMBER)
2984 char *p = strrchr (buffer, '_');
2985 p = p ? p + 1 : buffer;
2986 if (strcmp (p, "width") == 0)
2987 *width = value;
2988 else if (strcmp (p, "height") == 0)
2989 *height = value;
2991 expect (XBM_TK_NUMBER);
2994 if (!check_image_size (f, *width, *height))
2995 goto failure;
2996 else if (data == NULL)
2997 goto success;
2999 /* Parse bits. Must start with `static'. */
3000 expect_ident ("static");
3001 if (LA1 == XBM_TK_IDENT)
3003 if (strcmp (buffer, "unsigned") == 0)
3005 match ();
3006 expect_ident ("char");
3008 else if (strcmp (buffer, "short") == 0)
3010 match ();
3011 v10 = 1;
3012 if (*width % 16 && *width % 16 < 9)
3013 padding_p = 1;
3015 else if (strcmp (buffer, "char") == 0)
3016 match ();
3017 else
3018 goto failure;
3020 else
3021 goto failure;
3023 expect (XBM_TK_IDENT);
3024 expect ('[');
3025 expect (']');
3026 expect ('=');
3027 expect ('{');
3029 bytes_per_line = (*width + 7) / 8 + padding_p;
3030 nbytes = bytes_per_line * *height;
3031 p = *data = (unsigned char *) xmalloc (nbytes);
3033 if (v10)
3035 for (i = 0; i < nbytes; i += 2)
3037 int val = value;
3038 expect (XBM_TK_NUMBER);
3040 *p++ = XBM_BIT_SHUFFLE (val);
3041 if (!padding_p || ((i + 2) % bytes_per_line))
3042 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3044 if (LA1 == ',' || LA1 == '}')
3045 match ();
3046 else
3047 goto failure;
3050 else
3052 for (i = 0; i < nbytes; ++i)
3054 int val = value;
3055 expect (XBM_TK_NUMBER);
3057 *p++ = XBM_BIT_SHUFFLE (val);
3059 if (LA1 == ',' || LA1 == '}')
3060 match ();
3061 else
3062 goto failure;
3066 success:
3067 return 1;
3069 failure:
3071 if (data && *data)
3073 xfree (*data);
3074 *data = NULL;
3076 return 0;
3078 #undef match
3079 #undef expect
3080 #undef expect_ident
3084 /* Load XBM image IMG which will be displayed on frame F from buffer
3085 CONTENTS. END is the end of the buffer. Value is non-zero if
3086 successful. */
3088 static int
3089 xbm_load_image (f, img, contents, end)
3090 struct frame *f;
3091 struct image *img;
3092 unsigned char *contents, *end;
3094 int rc;
3095 unsigned char *data;
3096 int success_p = 0;
3098 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3099 if (rc)
3101 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3102 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3103 int non_default_colors = 0;
3104 Lisp_Object value;
3106 xassert (img->width > 0 && img->height > 0);
3108 /* Get foreground and background colors, maybe allocate colors. */
3109 value = image_spec_value (img->spec, QCforeground, NULL);
3110 if (!NILP (value))
3112 foreground = x_alloc_image_color (f, img, value, foreground);
3113 non_default_colors = 1;
3115 value = image_spec_value (img->spec, QCbackground, NULL);
3116 if (!NILP (value))
3118 background = x_alloc_image_color (f, img, value, background);
3119 img->background = background;
3120 img->background_valid = 1;
3121 non_default_colors = 1;
3124 Create_Pixmap_From_Bitmap_Data (f, img, data,
3125 foreground, background,
3126 non_default_colors);
3127 xfree (data);
3129 if (img->pixmap == NO_PIXMAP)
3131 x_clear_image (f, img);
3132 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3134 else
3135 success_p = 1;
3137 else
3138 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3140 return success_p;
3144 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3146 static int
3147 xbm_file_p (data)
3148 Lisp_Object data;
3150 int w, h;
3151 return (STRINGP (data)
3152 && xbm_read_bitmap_data (NULL, SDATA (data),
3153 (SDATA (data)
3154 + SBYTES (data)),
3155 &w, &h, NULL));
3159 /* Fill image IMG which is used on frame F with pixmap data. Value is
3160 non-zero if successful. */
3162 static int
3163 xbm_load (f, img)
3164 struct frame *f;
3165 struct image *img;
3167 int success_p = 0;
3168 Lisp_Object file_name;
3170 xassert (xbm_image_p (img->spec));
3172 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3173 file_name = image_spec_value (img->spec, QCfile, NULL);
3174 if (STRINGP (file_name))
3176 Lisp_Object file;
3177 unsigned char *contents;
3178 int size;
3179 struct gcpro gcpro1;
3181 file = x_find_image_file (file_name);
3182 GCPRO1 (file);
3183 if (!STRINGP (file))
3185 image_error ("Cannot find image file `%s'", file_name, Qnil);
3186 UNGCPRO;
3187 return 0;
3190 contents = slurp_file (SDATA (file), &size);
3191 if (contents == NULL)
3193 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3194 UNGCPRO;
3195 return 0;
3198 success_p = xbm_load_image (f, img, contents, contents + size);
3199 UNGCPRO;
3201 else
3203 struct image_keyword fmt[XBM_LAST];
3204 Lisp_Object data;
3205 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3206 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3207 int non_default_colors = 0;
3208 char *bits;
3209 int parsed_p;
3210 int in_memory_file_p = 0;
3212 /* See if data looks like an in-memory XBM file. */
3213 data = image_spec_value (img->spec, QCdata, NULL);
3214 in_memory_file_p = xbm_file_p (data);
3216 /* Parse the image specification. */
3217 bcopy (xbm_format, fmt, sizeof fmt);
3218 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3219 xassert (parsed_p);
3221 /* Get specified width, and height. */
3222 if (!in_memory_file_p)
3224 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3225 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3226 xassert (img->width > 0 && img->height > 0);
3229 /* Get foreground and background colors, maybe allocate colors. */
3230 if (fmt[XBM_FOREGROUND].count
3231 && STRINGP (fmt[XBM_FOREGROUND].value))
3233 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3234 foreground);
3235 non_default_colors = 1;
3238 if (fmt[XBM_BACKGROUND].count
3239 && STRINGP (fmt[XBM_BACKGROUND].value))
3241 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3242 background);
3243 non_default_colors = 1;
3246 if (in_memory_file_p)
3247 success_p = xbm_load_image (f, img, SDATA (data),
3248 (SDATA (data)
3249 + SBYTES (data)));
3250 else
3252 if (VECTORP (data))
3254 int i;
3255 char *p;
3256 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3258 p = bits = (char *) alloca (nbytes * img->height);
3259 for (i = 0; i < img->height; ++i, p += nbytes)
3261 Lisp_Object line = XVECTOR (data)->contents[i];
3262 if (STRINGP (line))
3263 bcopy (SDATA (line), p, nbytes);
3264 else
3265 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3268 else if (STRINGP (data))
3269 bits = SDATA (data);
3270 else
3271 bits = XBOOL_VECTOR (data)->data;
3273 #ifdef WINDOWSNT
3275 char *invertedBits;
3276 int nbytes, i;
3277 /* Windows mono bitmaps are reversed compared with X. */
3278 invertedBits = bits;
3279 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
3280 * img->height;
3281 bits = (char *) alloca(nbytes);
3282 for (i = 0; i < nbytes; i++)
3283 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3285 #endif
3286 /* Create the pixmap. */
3288 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3289 foreground, background,
3290 non_default_colors);
3291 if (img->pixmap)
3292 success_p = 1;
3293 else
3295 image_error ("Unable to create pixmap for XBM image `%s'",
3296 img->spec, Qnil);
3297 x_clear_image (f, img);
3302 return success_p;
3307 /***********************************************************************
3308 XPM images
3309 ***********************************************************************/
3311 #if defined (HAVE_XPM) || defined (HAVE_NS)
3313 static int xpm_image_p P_ ((Lisp_Object object));
3314 static int xpm_load P_ ((struct frame *f, struct image *img));
3315 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3317 #endif /* HAVE_XPM || HAVE_NS */
3319 #ifdef HAVE_XPM
3320 #ifdef HAVE_NTGUI
3321 /* Indicate to xpm.h that we don't have Xlib. */
3322 #define FOR_MSW
3323 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3324 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3325 #define XColor xpm_XColor
3326 #define XImage xpm_XImage
3327 #define Display xpm_Display
3328 #define PIXEL_ALREADY_TYPEDEFED
3329 #include "X11/xpm.h"
3330 #undef FOR_MSW
3331 #undef XColor
3332 #undef XImage
3333 #undef Display
3334 #undef PIXEL_ALREADY_TYPEDEFED
3335 #else
3336 #include "X11/xpm.h"
3337 #endif /* HAVE_NTGUI */
3338 #endif /* HAVE_XPM */
3340 #if defined (HAVE_XPM) || defined (HAVE_NS)
3341 /* The symbol `xpm' identifying XPM-format images. */
3343 Lisp_Object Qxpm;
3345 /* Indices of image specification fields in xpm_format, below. */
3347 enum xpm_keyword_index
3349 XPM_TYPE,
3350 XPM_FILE,
3351 XPM_DATA,
3352 XPM_ASCENT,
3353 XPM_MARGIN,
3354 XPM_RELIEF,
3355 XPM_ALGORITHM,
3356 XPM_HEURISTIC_MASK,
3357 XPM_MASK,
3358 XPM_COLOR_SYMBOLS,
3359 XPM_BACKGROUND,
3360 XPM_LAST
3363 /* Vector of image_keyword structures describing the format
3364 of valid XPM image specifications. */
3366 static struct image_keyword xpm_format[XPM_LAST] =
3368 {":type", IMAGE_SYMBOL_VALUE, 1},
3369 {":file", IMAGE_STRING_VALUE, 0},
3370 {":data", IMAGE_STRING_VALUE, 0},
3371 {":ascent", IMAGE_ASCENT_VALUE, 0},
3372 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3373 {":relief", IMAGE_INTEGER_VALUE, 0},
3374 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3375 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3376 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3377 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3378 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3381 /* Structure describing the image type XPM. */
3383 static struct image_type xpm_type =
3385 &Qxpm,
3386 xpm_image_p,
3387 xpm_load,
3388 x_clear_image,
3389 NULL
3392 #ifdef HAVE_X_WINDOWS
3394 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3395 functions for allocating image colors. Our own functions handle
3396 color allocation failures more gracefully than the ones on the XPM
3397 lib. */
3399 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3400 #define ALLOC_XPM_COLORS
3401 #endif
3402 #endif /* HAVE_X_WINDOWS */
3404 #ifdef ALLOC_XPM_COLORS
3406 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3407 static void xpm_free_color_cache P_ ((void));
3408 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3409 static int xpm_color_bucket P_ ((char *));
3410 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3411 XColor *, int));
3413 /* An entry in a hash table used to cache color definitions of named
3414 colors. This cache is necessary to speed up XPM image loading in
3415 case we do color allocations ourselves. Without it, we would need
3416 a call to XParseColor per pixel in the image. */
3418 struct xpm_cached_color
3420 /* Next in collision chain. */
3421 struct xpm_cached_color *next;
3423 /* Color definition (RGB and pixel color). */
3424 XColor color;
3426 /* Color name. */
3427 char name[1];
3430 /* The hash table used for the color cache, and its bucket vector
3431 size. */
3433 #define XPM_COLOR_CACHE_BUCKETS 1001
3434 struct xpm_cached_color **xpm_color_cache;
3436 /* Initialize the color cache. */
3438 static void
3439 xpm_init_color_cache (f, attrs)
3440 struct frame *f;
3441 XpmAttributes *attrs;
3443 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3444 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3445 memset (xpm_color_cache, 0, nbytes);
3446 init_color_table ();
3448 if (attrs->valuemask & XpmColorSymbols)
3450 int i;
3451 XColor color;
3453 for (i = 0; i < attrs->numsymbols; ++i)
3454 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3455 attrs->colorsymbols[i].value, &color))
3457 color.pixel = lookup_rgb_color (f, color.red, color.green,
3458 color.blue);
3459 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3464 /* Free the color cache. */
3466 static void
3467 xpm_free_color_cache ()
3469 struct xpm_cached_color *p, *next;
3470 int i;
3472 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3473 for (p = xpm_color_cache[i]; p; p = next)
3475 next = p->next;
3476 xfree (p);
3479 xfree (xpm_color_cache);
3480 xpm_color_cache = NULL;
3481 free_color_table ();
3484 /* Return the bucket index for color named COLOR_NAME in the color
3485 cache. */
3487 static int
3488 xpm_color_bucket (color_name)
3489 char *color_name;
3491 unsigned h = 0;
3492 char *s;
3494 for (s = color_name; *s; ++s)
3495 h = (h << 2) ^ *s;
3496 return h %= XPM_COLOR_CACHE_BUCKETS;
3500 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3501 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3502 entry added. */
3504 static struct xpm_cached_color *
3505 xpm_cache_color (f, color_name, color, bucket)
3506 struct frame *f;
3507 char *color_name;
3508 XColor *color;
3509 int bucket;
3511 size_t nbytes;
3512 struct xpm_cached_color *p;
3514 if (bucket < 0)
3515 bucket = xpm_color_bucket (color_name);
3517 nbytes = sizeof *p + strlen (color_name);
3518 p = (struct xpm_cached_color *) xmalloc (nbytes);
3519 strcpy (p->name, color_name);
3520 p->color = *color;
3521 p->next = xpm_color_cache[bucket];
3522 xpm_color_cache[bucket] = p;
3523 return p;
3526 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3527 return the cached definition in *COLOR. Otherwise, make a new
3528 entry in the cache and allocate the color. Value is zero if color
3529 allocation failed. */
3531 static int
3532 xpm_lookup_color (f, color_name, color)
3533 struct frame *f;
3534 char *color_name;
3535 XColor *color;
3537 struct xpm_cached_color *p;
3538 int h = xpm_color_bucket (color_name);
3540 for (p = xpm_color_cache[h]; p; p = p->next)
3541 if (strcmp (p->name, color_name) == 0)
3542 break;
3544 if (p != NULL)
3545 *color = p->color;
3546 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3547 color_name, color))
3549 color->pixel = lookup_rgb_color (f, color->red, color->green,
3550 color->blue);
3551 p = xpm_cache_color (f, color_name, color, h);
3553 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3554 with transparency, and it's useful. */
3555 else if (strcmp ("opaque", color_name) == 0)
3557 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
3558 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3559 p = xpm_cache_color (f, color_name, color, h);
3562 return p != NULL;
3566 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3567 CLOSURE is a pointer to the frame on which we allocate the
3568 color. Return in *COLOR the allocated color. Value is non-zero
3569 if successful. */
3571 static int
3572 xpm_alloc_color (dpy, cmap, color_name, color, closure)
3573 Display *dpy;
3574 Colormap cmap;
3575 char *color_name;
3576 XColor *color;
3577 void *closure;
3579 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3583 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3584 is a pointer to the frame on which we allocate the color. Value is
3585 non-zero if successful. */
3587 static int
3588 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
3589 Display *dpy;
3590 Colormap cmap;
3591 Pixel *pixels;
3592 int npixels;
3593 void *closure;
3595 return 1;
3598 #endif /* ALLOC_XPM_COLORS */
3601 #ifdef HAVE_NTGUI
3603 /* XPM library details. */
3605 DEF_IMGLIB_FN (XpmFreeAttributes);
3606 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
3607 DEF_IMGLIB_FN (XpmReadFileToImage);
3608 DEF_IMGLIB_FN (XImageFree);
3610 static int
3611 init_xpm_functions (Lisp_Object libraries)
3613 HMODULE library;
3615 if (!(library = w32_delayed_load (libraries, Qxpm)))
3616 return 0;
3618 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3619 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3620 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3621 LOAD_IMGLIB_FN (library, XImageFree);
3622 return 1;
3625 #endif /* HAVE_NTGUI */
3628 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3629 for XPM images. Such a list must consist of conses whose car and
3630 cdr are strings. */
3632 static int
3633 xpm_valid_color_symbols_p (color_symbols)
3634 Lisp_Object color_symbols;
3636 while (CONSP (color_symbols))
3638 Lisp_Object sym = XCAR (color_symbols);
3639 if (!CONSP (sym)
3640 || !STRINGP (XCAR (sym))
3641 || !STRINGP (XCDR (sym)))
3642 break;
3643 color_symbols = XCDR (color_symbols);
3646 return NILP (color_symbols);
3650 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3652 static int
3653 xpm_image_p (object)
3654 Lisp_Object object;
3656 struct image_keyword fmt[XPM_LAST];
3657 bcopy (xpm_format, fmt, sizeof fmt);
3658 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3659 /* Either `:file' or `:data' must be present. */
3660 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3661 /* Either no `:color-symbols' or it's a list of conses
3662 whose car and cdr are strings. */
3663 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3664 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3667 #endif /* HAVE_XPM || HAVE_NS */
3669 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3671 x_create_bitmap_from_xpm_data (f, bits)
3672 struct frame *f;
3673 char **bits;
3675 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3676 int id, rc;
3677 XpmAttributes attrs;
3678 Pixmap bitmap, mask;
3680 bzero (&attrs, sizeof attrs);
3682 attrs.visual = FRAME_X_VISUAL (f);
3683 attrs.colormap = FRAME_X_COLORMAP (f);
3684 attrs.valuemask |= XpmVisual;
3685 attrs.valuemask |= XpmColormap;
3687 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3688 bits, &bitmap, &mask, &attrs);
3689 if (rc != XpmSuccess)
3691 XpmFreeAttributes (&attrs);
3692 return -1;
3695 id = x_allocate_bitmap_record (f);
3696 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3697 dpyinfo->bitmaps[id - 1].have_mask = 1;
3698 dpyinfo->bitmaps[id - 1].mask = mask;
3699 dpyinfo->bitmaps[id - 1].file = NULL;
3700 dpyinfo->bitmaps[id - 1].height = attrs.height;
3701 dpyinfo->bitmaps[id - 1].width = attrs.width;
3702 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3703 dpyinfo->bitmaps[id - 1].refcount = 1;
3705 XpmFreeAttributes (&attrs);
3706 return id;
3708 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3710 /* Load image IMG which will be displayed on frame F. Value is
3711 non-zero if successful. */
3713 #ifdef HAVE_XPM
3715 static int
3716 xpm_load (f, img)
3717 struct frame *f;
3718 struct image *img;
3720 int rc;
3721 XpmAttributes attrs;
3722 Lisp_Object specified_file, color_symbols;
3723 #ifdef HAVE_NTGUI
3724 HDC hdc;
3725 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3726 #endif /* HAVE_NTGUI */
3728 /* Configure the XPM lib. Use the visual of frame F. Allocate
3729 close colors. Return colors allocated. */
3730 bzero (&attrs, sizeof attrs);
3732 #ifndef HAVE_NTGUI
3733 attrs.visual = FRAME_X_VISUAL (f);
3734 attrs.colormap = FRAME_X_COLORMAP (f);
3735 attrs.valuemask |= XpmVisual;
3736 attrs.valuemask |= XpmColormap;
3737 #endif /* HAVE_NTGUI */
3739 #ifdef ALLOC_XPM_COLORS
3740 /* Allocate colors with our own functions which handle
3741 failing color allocation more gracefully. */
3742 attrs.color_closure = f;
3743 attrs.alloc_color = xpm_alloc_color;
3744 attrs.free_colors = xpm_free_colors;
3745 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3746 #else /* not ALLOC_XPM_COLORS */
3747 /* Let the XPM lib allocate colors. */
3748 attrs.valuemask |= XpmReturnAllocPixels;
3749 #ifdef XpmAllocCloseColors
3750 attrs.alloc_close_colors = 1;
3751 attrs.valuemask |= XpmAllocCloseColors;
3752 #else /* not XpmAllocCloseColors */
3753 attrs.closeness = 600;
3754 attrs.valuemask |= XpmCloseness;
3755 #endif /* not XpmAllocCloseColors */
3756 #endif /* ALLOC_XPM_COLORS */
3758 /* If image specification contains symbolic color definitions, add
3759 these to `attrs'. */
3760 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3761 if (CONSP (color_symbols))
3763 Lisp_Object tail;
3764 XpmColorSymbol *xpm_syms;
3765 int i, size;
3767 attrs.valuemask |= XpmColorSymbols;
3769 /* Count number of symbols. */
3770 attrs.numsymbols = 0;
3771 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3772 ++attrs.numsymbols;
3774 /* Allocate an XpmColorSymbol array. */
3775 size = attrs.numsymbols * sizeof *xpm_syms;
3776 xpm_syms = (XpmColorSymbol *) alloca (size);
3777 bzero (xpm_syms, size);
3778 attrs.colorsymbols = xpm_syms;
3780 /* Fill the color symbol array. */
3781 for (tail = color_symbols, i = 0;
3782 CONSP (tail);
3783 ++i, tail = XCDR (tail))
3785 Lisp_Object name = XCAR (XCAR (tail));
3786 Lisp_Object color = XCDR (XCAR (tail));
3787 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
3788 strcpy (xpm_syms[i].name, SDATA (name));
3789 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
3790 strcpy (xpm_syms[i].value, SDATA (color));
3794 /* Create a pixmap for the image, either from a file, or from a
3795 string buffer containing data in the same format as an XPM file. */
3796 #ifdef ALLOC_XPM_COLORS
3797 xpm_init_color_cache (f, &attrs);
3798 #endif
3800 specified_file = image_spec_value (img->spec, QCfile, NULL);
3802 #ifdef HAVE_NTGUI
3804 HDC frame_dc = get_frame_dc (f);
3805 hdc = CreateCompatibleDC (frame_dc);
3806 release_frame_dc (f, frame_dc);
3808 #endif /* HAVE_NTGUI */
3810 if (STRINGP (specified_file))
3812 Lisp_Object file = x_find_image_file (specified_file);
3813 if (!STRINGP (file))
3815 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3816 return 0;
3819 #ifdef HAVE_NTGUI
3820 /* XpmReadFileToPixmap is not available in the Windows port of
3821 libxpm. But XpmReadFileToImage almost does what we want. */
3822 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3823 &xpm_image, &xpm_mask,
3824 &attrs);
3825 #else
3826 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3827 SDATA (file), &img->pixmap, &img->mask,
3828 &attrs);
3829 #endif /* HAVE_NTGUI */
3831 else
3833 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
3834 #ifdef HAVE_NTGUI
3835 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3836 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3837 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3838 &xpm_image, &xpm_mask,
3839 &attrs);
3840 #else
3841 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3842 SDATA (buffer),
3843 &img->pixmap, &img->mask,
3844 &attrs);
3845 #endif /* HAVE_NTGUI */
3848 if (rc == XpmSuccess)
3850 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3851 img->colors = colors_in_color_table (&img->ncolors);
3852 #else /* not ALLOC_XPM_COLORS */
3853 int i;
3855 #ifdef HAVE_NTGUI
3856 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3857 plus some duplicate attributes. */
3858 if (xpm_image && xpm_image->bitmap)
3860 img->pixmap = xpm_image->bitmap;
3861 /* XImageFree in libXpm frees XImage struct without destroying
3862 the bitmap, which is what we want. */
3863 fn_XImageFree (xpm_image);
3865 if (xpm_mask && xpm_mask->bitmap)
3867 /* The mask appears to be inverted compared with what we expect.
3868 TODO: invert our expectations. See other places where we
3869 have to invert bits because our idea of masks is backwards. */
3870 HGDIOBJ old_obj;
3871 old_obj = SelectObject (hdc, xpm_mask->bitmap);
3873 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
3874 SelectObject (hdc, old_obj);
3876 img->mask = xpm_mask->bitmap;
3877 fn_XImageFree (xpm_mask);
3878 DeleteDC (hdc);
3881 DeleteDC (hdc);
3882 #endif /* HAVE_NTGUI */
3884 /* Remember allocated colors. */
3885 img->ncolors = attrs.nalloc_pixels;
3886 img->colors = (unsigned long *) xmalloc (img->ncolors
3887 * sizeof *img->colors);
3888 for (i = 0; i < attrs.nalloc_pixels; ++i)
3890 img->colors[i] = attrs.alloc_pixels[i];
3891 #ifdef DEBUG_X_COLORS
3892 register_color (img->colors[i]);
3893 #endif
3895 #endif /* not ALLOC_XPM_COLORS */
3897 img->width = attrs.width;
3898 img->height = attrs.height;
3899 xassert (img->width > 0 && img->height > 0);
3901 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3902 #ifdef HAVE_NTGUI
3903 fn_XpmFreeAttributes (&attrs);
3904 #else
3905 XpmFreeAttributes (&attrs);
3906 #endif /* HAVE_NTGUI */
3908 else
3910 #ifdef HAVE_NTGUI
3911 DeleteDC (hdc);
3912 #endif /* HAVE_NTGUI */
3914 switch (rc)
3916 case XpmOpenFailed:
3917 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
3918 break;
3920 case XpmFileInvalid:
3921 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
3922 break;
3924 case XpmNoMemory:
3925 image_error ("Out of memory (%s)", img->spec, Qnil);
3926 break;
3928 case XpmColorFailed:
3929 image_error ("Color allocation error (%s)", img->spec, Qnil);
3930 break;
3932 default:
3933 image_error ("Unknown error (%s)", img->spec, Qnil);
3934 break;
3938 #ifdef ALLOC_XPM_COLORS
3939 xpm_free_color_cache ();
3940 #endif
3941 return rc == XpmSuccess;
3944 #endif /* HAVE_XPM */
3946 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3948 /* XPM support functions for NS where libxpm is not available.
3949 Only XPM version 3 (without any extensions) is supported. */
3951 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
3952 const unsigned char **, int *));
3953 static Lisp_Object xpm_make_color_table_v
3954 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
3955 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
3956 static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
3957 int, Lisp_Object));
3958 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
3959 const unsigned char *, int));
3960 static Lisp_Object xpm_make_color_table_h
3961 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
3962 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
3963 static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
3964 int, Lisp_Object));
3965 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
3966 const unsigned char *, int));
3967 static int xpm_str_to_color_key P_ ((const char *));
3968 static int xpm_load_image P_ ((struct frame *, struct image *,
3969 const unsigned char *, const unsigned char *));
3971 /* Tokens returned from xpm_scan. */
3973 enum xpm_token
3975 XPM_TK_IDENT = 256,
3976 XPM_TK_STRING,
3977 XPM_TK_EOF
3980 /* Scan an XPM data and return a character (< 256) or a token defined
3981 by enum xpm_token above. *S and END are the start (inclusive) and
3982 the end (exclusive) addresses of the data, respectively. Advance
3983 *S while scanning. If token is either XPM_TK_IDENT or
3984 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3985 length of the corresponding token, respectively. */
3987 static int
3988 xpm_scan (s, end, beg, len)
3989 const unsigned char **s, *end, **beg;
3990 int *len;
3992 int c;
3994 while (*s < end)
3996 /* Skip white-space. */
3997 while (*s < end && (c = *(*s)++, isspace (c)))
4000 /* gnus-pointer.xpm uses '-' in its identifier.
4001 sb-dir-plus.xpm uses '+' in its identifier. */
4002 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4004 *beg = *s - 1;
4005 while (*s < end
4006 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4007 ++*s;
4008 *len = *s - *beg;
4009 return XPM_TK_IDENT;
4011 else if (c == '"')
4013 *beg = *s;
4014 while (*s < end && **s != '"')
4015 ++*s;
4016 *len = *s - *beg;
4017 if (*s < end)
4018 ++*s;
4019 return XPM_TK_STRING;
4021 else if (c == '/')
4023 if (*s < end && **s == '*')
4025 /* C-style comment. */
4026 ++*s;
4029 while (*s < end && *(*s)++ != '*')
4032 while (*s < end && **s != '/');
4033 if (*s < end)
4034 ++*s;
4036 else
4037 return c;
4039 else
4040 return c;
4043 return XPM_TK_EOF;
4046 /* Functions for color table lookup in XPM data. A key is a string
4047 specifying the color of each pixel in XPM data. A value is either
4048 an integer that specifies a pixel color, Qt that specifies
4049 transparency, or Qnil for the unspecified color. If the length of
4050 the key string is one, a vector is used as a table. Otherwise, a
4051 hash table is used. */
4053 static Lisp_Object
4054 xpm_make_color_table_v (put_func, get_func)
4055 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4056 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4058 *put_func = xpm_put_color_table_v;
4059 *get_func = xpm_get_color_table_v;
4060 return Fmake_vector (make_number (256), Qnil);
4063 static void
4064 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4065 Lisp_Object color_table;
4066 const unsigned char *chars_start;
4067 int chars_len;
4068 Lisp_Object color;
4070 XVECTOR (color_table)->contents[*chars_start] = color;
4073 static Lisp_Object
4074 xpm_get_color_table_v (color_table, chars_start, chars_len)
4075 Lisp_Object color_table;
4076 const unsigned char *chars_start;
4077 int chars_len;
4079 return XVECTOR (color_table)->contents[*chars_start];
4082 static Lisp_Object
4083 xpm_make_color_table_h (put_func, get_func)
4084 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4085 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4087 *put_func = xpm_put_color_table_h;
4088 *get_func = xpm_get_color_table_h;
4089 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4090 make_float (DEFAULT_REHASH_SIZE),
4091 make_float (DEFAULT_REHASH_THRESHOLD),
4092 Qnil, Qnil, Qnil);
4095 static void
4096 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4097 Lisp_Object color_table;
4098 const unsigned char *chars_start;
4099 int chars_len;
4100 Lisp_Object color;
4102 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4103 unsigned hash_code;
4104 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4106 hash_lookup (table, chars, &hash_code);
4107 hash_put (table, chars, color, hash_code);
4110 static Lisp_Object
4111 xpm_get_color_table_h (color_table, chars_start, chars_len)
4112 Lisp_Object color_table;
4113 const unsigned char *chars_start;
4114 int chars_len;
4116 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4117 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4118 NULL);
4120 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4123 enum xpm_color_key {
4124 XPM_COLOR_KEY_S,
4125 XPM_COLOR_KEY_M,
4126 XPM_COLOR_KEY_G4,
4127 XPM_COLOR_KEY_G,
4128 XPM_COLOR_KEY_C
4131 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4133 static int
4134 xpm_str_to_color_key (s)
4135 const char *s;
4137 int i;
4139 for (i = 0;
4140 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4141 i++)
4142 if (strcmp (xpm_color_key_strings[i], s) == 0)
4143 return i;
4144 return -1;
4147 static int
4148 xpm_load_image (f, img, contents, end)
4149 struct frame *f;
4150 struct image *img;
4151 const unsigned char *contents, *end;
4153 const unsigned char *s = contents, *beg, *str;
4154 unsigned char buffer[BUFSIZ];
4155 int width, height, x, y;
4156 int num_colors, chars_per_pixel;
4157 int len, LA1;
4158 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4159 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
4160 Lisp_Object frame, color_symbols, color_table;
4161 int best_key, have_mask = 0;
4162 XImagePtr ximg = NULL, mask_img = NULL;
4164 #define match() \
4165 LA1 = xpm_scan (&s, end, &beg, &len)
4167 #define expect(TOKEN) \
4168 if (LA1 != (TOKEN)) \
4169 goto failure; \
4170 else \
4171 match ()
4173 #define expect_ident(IDENT) \
4174 if (LA1 == XPM_TK_IDENT \
4175 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4176 match (); \
4177 else \
4178 goto failure
4180 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4181 goto failure;
4182 s += 9;
4183 match();
4184 expect_ident ("static");
4185 expect_ident ("char");
4186 expect ('*');
4187 expect (XPM_TK_IDENT);
4188 expect ('[');
4189 expect (']');
4190 expect ('=');
4191 expect ('{');
4192 expect (XPM_TK_STRING);
4193 if (len >= BUFSIZ)
4194 goto failure;
4195 memcpy (buffer, beg, len);
4196 buffer[len] = '\0';
4197 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4198 &num_colors, &chars_per_pixel) != 4
4199 || width <= 0 || height <= 0
4200 || num_colors <= 0 || chars_per_pixel <= 0)
4201 goto failure;
4203 if (!check_image_size (f, width, height))
4205 image_error ("Invalid image size", Qnil, Qnil);
4206 goto failure;
4209 expect (',');
4211 XSETFRAME (frame, f);
4212 if (!NILP (Fxw_display_color_p (frame)))
4213 best_key = XPM_COLOR_KEY_C;
4214 else if (!NILP (Fx_display_grayscale_p (frame)))
4215 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4216 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4217 else
4218 best_key = XPM_COLOR_KEY_M;
4220 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4221 if (chars_per_pixel == 1)
4222 color_table = xpm_make_color_table_v (&put_color_table,
4223 &get_color_table);
4224 else
4225 color_table = xpm_make_color_table_h (&put_color_table,
4226 &get_color_table);
4228 while (num_colors-- > 0)
4230 unsigned char *color, *max_color;
4231 int key, next_key, max_key = 0;
4232 Lisp_Object symbol_color = Qnil, color_val;
4233 XColor cdef;
4235 expect (XPM_TK_STRING);
4236 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4237 goto failure;
4238 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4239 buffer[len - chars_per_pixel] = '\0';
4241 str = strtok (buffer, " \t");
4242 if (str == NULL)
4243 goto failure;
4244 key = xpm_str_to_color_key (str);
4245 if (key < 0)
4246 goto failure;
4249 color = strtok (NULL, " \t");
4250 if (color == NULL)
4251 goto failure;
4253 while ((str = strtok (NULL, " \t")) != NULL)
4255 next_key = xpm_str_to_color_key (str);
4256 if (next_key >= 0)
4257 break;
4258 color[strlen (color)] = ' ';
4261 if (key == XPM_COLOR_KEY_S)
4263 if (NILP (symbol_color))
4264 symbol_color = build_string (color);
4266 else if (max_key < key && key <= best_key)
4268 max_key = key;
4269 max_color = color;
4271 key = next_key;
4273 while (str);
4275 color_val = Qnil;
4276 if (!NILP (color_symbols) && !NILP (symbol_color))
4278 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4280 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4282 if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0)
4283 color_val = Qt;
4284 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4285 &cdef, 0))
4286 color_val = make_number (cdef.pixel);
4289 if (NILP (color_val) && max_key > 0)
4291 if (xstrcasecmp (max_color, "None") == 0)
4292 color_val = Qt;
4293 else if (x_defined_color (f, max_color, &cdef, 0))
4294 color_val = make_number (cdef.pixel);
4296 if (!NILP (color_val))
4297 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4299 expect (',');
4302 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4303 &ximg, &img->pixmap)
4304 #ifndef HAVE_NS
4305 || !x_create_x_image_and_pixmap (f, width, height, 1,
4306 &mask_img, &img->mask)
4307 #endif
4310 image_error ("Out of memory (%s)", img->spec, Qnil);
4311 goto error;
4314 for (y = 0; y < height; y++)
4316 expect (XPM_TK_STRING);
4317 str = beg;
4318 if (len < width * chars_per_pixel)
4319 goto failure;
4320 for (x = 0; x < width; x++, str += chars_per_pixel)
4322 Lisp_Object color_val =
4323 (*get_color_table) (color_table, str, chars_per_pixel);
4325 XPutPixel (ximg, x, y,
4326 (INTEGERP (color_val) ? XINT (color_val)
4327 : FRAME_FOREGROUND_PIXEL (f)));
4328 #ifndef HAVE_NS
4329 XPutPixel (mask_img, x, y,
4330 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4331 : (have_mask = 1, PIX_MASK_RETAIN)));
4332 #else
4333 if (EQ(color_val, Qt))
4334 ns_set_alpha(ximg, x, y, 0);
4335 #endif
4337 if (y + 1 < height)
4338 expect (',');
4341 img->width = width;
4342 img->height = height;
4344 /* Maybe fill in the background field while we have ximg handy. */
4345 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4346 IMAGE_BACKGROUND (img, f, ximg);
4348 x_put_x_image (f, ximg, img->pixmap, width, height);
4349 x_destroy_x_image (ximg);
4350 #ifndef HAVE_NS
4351 if (have_mask)
4353 /* Fill in the background_transparent field while we have the
4354 mask handy. */
4355 image_background_transparent (img, f, mask_img);
4357 x_put_x_image (f, mask_img, img->mask, width, height);
4358 x_destroy_x_image (mask_img);
4360 else
4362 x_destroy_x_image (mask_img);
4363 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4364 img->mask = NO_PIXMAP;
4366 #endif
4367 return 1;
4369 failure:
4370 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4371 error:
4372 x_destroy_x_image (ximg);
4373 x_destroy_x_image (mask_img);
4374 x_clear_image (f, img);
4375 return 0;
4377 #undef match
4378 #undef expect
4379 #undef expect_ident
4382 static int
4383 xpm_load (f, img)
4384 struct frame *f;
4385 struct image *img;
4387 int success_p = 0;
4388 Lisp_Object file_name;
4390 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4391 file_name = image_spec_value (img->spec, QCfile, NULL);
4392 if (STRINGP (file_name))
4394 Lisp_Object file;
4395 unsigned char *contents;
4396 int size;
4397 struct gcpro gcpro1;
4399 file = x_find_image_file (file_name);
4400 GCPRO1 (file);
4401 if (!STRINGP (file))
4403 image_error ("Cannot find image file `%s'", file_name, Qnil);
4404 UNGCPRO;
4405 return 0;
4408 contents = slurp_file (SDATA (file), &size);
4409 if (contents == NULL)
4411 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4412 UNGCPRO;
4413 return 0;
4416 success_p = xpm_load_image (f, img, contents, contents + size);
4417 xfree (contents);
4418 UNGCPRO;
4420 else
4422 Lisp_Object data;
4424 data = image_spec_value (img->spec, QCdata, NULL);
4425 success_p = xpm_load_image (f, img, SDATA (data),
4426 SDATA (data) + SBYTES (data));
4429 return success_p;
4432 #endif /* HAVE_NS && !HAVE_XPM */
4436 /***********************************************************************
4437 Color table
4438 ***********************************************************************/
4440 #ifdef COLOR_TABLE_SUPPORT
4442 /* An entry in the color table mapping an RGB color to a pixel color. */
4444 struct ct_color
4446 int r, g, b;
4447 unsigned long pixel;
4449 /* Next in color table collision list. */
4450 struct ct_color *next;
4453 /* The bucket vector size to use. Must be prime. */
4455 #define CT_SIZE 101
4457 /* Value is a hash of the RGB color given by R, G, and B. */
4459 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4461 /* The color hash table. */
4463 struct ct_color **ct_table;
4465 /* Number of entries in the color table. */
4467 int ct_colors_allocated;
4469 /* Initialize the color table. */
4471 static void
4472 init_color_table ()
4474 int size = CT_SIZE * sizeof (*ct_table);
4475 ct_table = (struct ct_color **) xmalloc (size);
4476 bzero (ct_table, size);
4477 ct_colors_allocated = 0;
4481 /* Free memory associated with the color table. */
4483 static void
4484 free_color_table ()
4486 int i;
4487 struct ct_color *p, *next;
4489 for (i = 0; i < CT_SIZE; ++i)
4490 for (p = ct_table[i]; p; p = next)
4492 next = p->next;
4493 xfree (p);
4496 xfree (ct_table);
4497 ct_table = NULL;
4501 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4502 entry for that color already is in the color table, return the
4503 pixel color of that entry. Otherwise, allocate a new color for R,
4504 G, B, and make an entry in the color table. */
4506 static unsigned long
4507 lookup_rgb_color (f, r, g, b)
4508 struct frame *f;
4509 int r, g, b;
4511 unsigned hash = CT_HASH_RGB (r, g, b);
4512 int i = hash % CT_SIZE;
4513 struct ct_color *p;
4514 Display_Info *dpyinfo;
4516 /* Handle TrueColor visuals specially, which improves performance by
4517 two orders of magnitude. Freeing colors on TrueColor visuals is
4518 a nop, and pixel colors specify RGB values directly. See also
4519 the Xlib spec, chapter 3.1. */
4520 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4521 if (dpyinfo->red_bits > 0)
4523 unsigned long pr, pg, pb;
4525 /* Apply gamma-correction like normal color allocation does. */
4526 if (f->gamma)
4528 XColor color;
4529 color.red = r, color.green = g, color.blue = b;
4530 gamma_correct (f, &color);
4531 r = color.red, g = color.green, b = color.blue;
4534 /* Scale down RGB values to the visual's bits per RGB, and shift
4535 them to the right position in the pixel color. Note that the
4536 original RGB values are 16-bit values, as usual in X. */
4537 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4538 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4539 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4541 /* Assemble the pixel color. */
4542 return pr | pg | pb;
4545 for (p = ct_table[i]; p; p = p->next)
4546 if (p->r == r && p->g == g && p->b == b)
4547 break;
4549 if (p == NULL)
4552 #ifdef HAVE_X_WINDOWS
4553 XColor color;
4554 Colormap cmap;
4555 int rc;
4557 color.red = r;
4558 color.green = g;
4559 color.blue = b;
4561 cmap = FRAME_X_COLORMAP (f);
4562 rc = x_alloc_nearest_color (f, cmap, &color);
4563 if (rc)
4565 ++ct_colors_allocated;
4566 p = (struct ct_color *) xmalloc (sizeof *p);
4567 p->r = r;
4568 p->g = g;
4569 p->b = b;
4570 p->pixel = color.pixel;
4571 p->next = ct_table[i];
4572 ct_table[i] = p;
4574 else
4575 return FRAME_FOREGROUND_PIXEL (f);
4577 #else
4578 COLORREF color;
4579 #ifdef HAVE_NTGUI
4580 color = PALETTERGB (r, g, b);
4581 #else
4582 color = RGB_TO_ULONG (r, g, b);
4583 #endif /* HAVE_NTGUI */
4584 ++ct_colors_allocated;
4585 p = (struct ct_color *) xmalloc (sizeof *p);
4586 p->r = r;
4587 p->g = g;
4588 p->b = b;
4589 p->pixel = color;
4590 p->next = ct_table[i];
4591 ct_table[i] = p;
4592 #endif /* HAVE_X_WINDOWS */
4596 return p->pixel;
4600 /* Look up pixel color PIXEL which is used on frame F in the color
4601 table. If not already present, allocate it. Value is PIXEL. */
4603 static unsigned long
4604 lookup_pixel_color (f, pixel)
4605 struct frame *f;
4606 unsigned long pixel;
4608 int i = pixel % CT_SIZE;
4609 struct ct_color *p;
4611 for (p = ct_table[i]; p; p = p->next)
4612 if (p->pixel == pixel)
4613 break;
4615 if (p == NULL)
4617 XColor color;
4618 Colormap cmap;
4619 int rc;
4621 #ifdef HAVE_X_WINDOWS
4622 cmap = FRAME_X_COLORMAP (f);
4623 color.pixel = pixel;
4624 x_query_color (f, &color);
4625 rc = x_alloc_nearest_color (f, cmap, &color);
4626 #else
4627 BLOCK_INPUT;
4628 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4629 color.pixel = pixel;
4630 XQueryColor (NULL, cmap, &color);
4631 rc = x_alloc_nearest_color (f, cmap, &color);
4632 UNBLOCK_INPUT;
4633 #endif /* HAVE_X_WINDOWS */
4635 if (rc)
4637 ++ct_colors_allocated;
4639 p = (struct ct_color *) xmalloc (sizeof *p);
4640 p->r = color.red;
4641 p->g = color.green;
4642 p->b = color.blue;
4643 p->pixel = pixel;
4644 p->next = ct_table[i];
4645 ct_table[i] = p;
4647 else
4648 return FRAME_FOREGROUND_PIXEL (f);
4650 return p->pixel;
4654 /* Value is a vector of all pixel colors contained in the color table,
4655 allocated via xmalloc. Set *N to the number of colors. */
4657 static unsigned long *
4658 colors_in_color_table (n)
4659 int *n;
4661 int i, j;
4662 struct ct_color *p;
4663 unsigned long *colors;
4665 if (ct_colors_allocated == 0)
4667 *n = 0;
4668 colors = NULL;
4670 else
4672 colors = (unsigned long *) xmalloc (ct_colors_allocated
4673 * sizeof *colors);
4674 *n = ct_colors_allocated;
4676 for (i = j = 0; i < CT_SIZE; ++i)
4677 for (p = ct_table[i]; p; p = p->next)
4678 colors[j++] = p->pixel;
4681 return colors;
4684 #else /* COLOR_TABLE_SUPPORT */
4686 static unsigned long
4687 lookup_rgb_color (f, r, g, b)
4688 struct frame *f;
4689 int r, g, b;
4691 unsigned long pixel;
4693 #ifdef HAVE_NTGUI
4694 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4695 #endif /* HAVE_NTGUI */
4697 #ifdef HAVE_NS
4698 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4699 #endif /* HAVE_NS */
4700 return pixel;
4703 static void
4704 init_color_table ()
4707 #endif /* COLOR_TABLE_SUPPORT */
4710 /***********************************************************************
4711 Algorithms
4712 ***********************************************************************/
4714 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
4715 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
4716 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
4718 #ifdef HAVE_NTGUI
4719 static void XPutPixel (XImagePtr , int, int, COLORREF);
4720 #endif /* HAVE_NTGUI */
4722 /* Non-zero means draw a cross on images having `:conversion
4723 disabled'. */
4725 int cross_disabled_images;
4727 /* Edge detection matrices for different edge-detection
4728 strategies. */
4730 static int emboss_matrix[9] = {
4731 /* x - 1 x x + 1 */
4732 2, -1, 0, /* y - 1 */
4733 -1, 0, 1, /* y */
4734 0, 1, -2 /* y + 1 */
4737 static int laplace_matrix[9] = {
4738 /* x - 1 x x + 1 */
4739 1, 0, 0, /* y - 1 */
4740 0, 0, 0, /* y */
4741 0, 0, -1 /* y + 1 */
4744 /* Value is the intensity of the color whose red/green/blue values
4745 are R, G, and B. */
4747 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4750 /* On frame F, return an array of XColor structures describing image
4751 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4752 non-zero means also fill the red/green/blue members of the XColor
4753 structures. Value is a pointer to the array of XColors structures,
4754 allocated with xmalloc; it must be freed by the caller. */
4756 static XColor *
4757 x_to_xcolors (f, img, rgb_p)
4758 struct frame *f;
4759 struct image *img;
4760 int rgb_p;
4762 int x, y;
4763 XColor *colors, *p;
4764 XImagePtr_or_DC ximg;
4765 #ifdef HAVE_NTGUI
4766 HDC hdc;
4767 HGDIOBJ prev;
4768 #endif /* HAVE_NTGUI */
4770 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
4772 #ifndef HAVE_NTGUI
4773 /* Get the X image IMG->pixmap. */
4774 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4775 0, 0, img->width, img->height, ~0, ZPixmap);
4776 #else
4777 /* Load the image into a memory device context. */
4778 hdc = get_frame_dc (f);
4779 ximg = CreateCompatibleDC (hdc);
4780 release_frame_dc (f, hdc);
4781 prev = SelectObject (ximg, img->pixmap);
4782 #endif /* HAVE_NTGUI */
4784 /* Fill the `pixel' members of the XColor array. I wished there
4785 were an easy and portable way to circumvent XGetPixel. */
4786 p = colors;
4787 for (y = 0; y < img->height; ++y)
4789 XColor *row = p;
4791 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4792 for (x = 0; x < img->width; ++x, ++p)
4793 p->pixel = GET_PIXEL (ximg, x, y);
4794 if (rgb_p)
4795 x_query_colors (f, row, img->width);
4797 #else
4799 for (x = 0; x < img->width; ++x, ++p)
4801 /* W32_TODO: palette support needed here? */
4802 p->pixel = GET_PIXEL (ximg, x, y);
4803 if (rgb_p)
4805 p->red = RED16_FROM_ULONG (p->pixel);
4806 p->green = GREEN16_FROM_ULONG (p->pixel);
4807 p->blue = BLUE16_FROM_ULONG (p->pixel);
4810 #endif /* HAVE_X_WINDOWS */
4813 Destroy_Image (ximg, prev);
4815 return colors;
4818 #ifdef HAVE_NTGUI
4820 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4821 created with CreateDIBSection, with the pointer to the bit values
4822 stored in ximg->data. */
4824 static void
4825 XPutPixel (ximg, x, y, color)
4826 XImagePtr ximg;
4827 int x, y;
4828 COLORREF color;
4830 int width = ximg->info.bmiHeader.biWidth;
4831 int height = ximg->info.bmiHeader.biHeight;
4832 unsigned char * pixel;
4834 /* True color images. */
4835 if (ximg->info.bmiHeader.biBitCount == 24)
4837 int rowbytes = width * 3;
4838 /* Ensure scanlines are aligned on 4 byte boundaries. */
4839 if (rowbytes % 4)
4840 rowbytes += 4 - (rowbytes % 4);
4842 pixel = ximg->data + y * rowbytes + x * 3;
4843 /* Windows bitmaps are in BGR order. */
4844 *pixel = GetBValue (color);
4845 *(pixel + 1) = GetGValue (color);
4846 *(pixel + 2) = GetRValue (color);
4848 /* Monochrome images. */
4849 else if (ximg->info.bmiHeader.biBitCount == 1)
4851 int rowbytes = width / 8;
4852 /* Ensure scanlines are aligned on 4 byte boundaries. */
4853 if (rowbytes % 4)
4854 rowbytes += 4 - (rowbytes % 4);
4855 pixel = ximg->data + y * rowbytes + x / 8;
4856 /* Filter out palette info. */
4857 if (color & 0x00ffffff)
4858 *pixel = *pixel | (1 << x % 8);
4859 else
4860 *pixel = *pixel & ~(1 << x % 8);
4862 else
4863 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4866 #endif /* HAVE_NTGUI */
4868 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4869 RGB members are set. F is the frame on which this all happens.
4870 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4872 static void
4873 x_from_xcolors (f, img, colors)
4874 struct frame *f;
4875 struct image *img;
4876 XColor *colors;
4878 int x, y;
4879 XImagePtr oimg = NULL;
4880 Pixmap pixmap;
4881 XColor *p;
4883 init_color_table ();
4885 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
4886 &oimg, &pixmap);
4887 p = colors;
4888 for (y = 0; y < img->height; ++y)
4889 for (x = 0; x < img->width; ++x, ++p)
4891 unsigned long pixel;
4892 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
4893 XPutPixel (oimg, x, y, pixel);
4896 xfree (colors);
4897 x_clear_image_1 (f, img, 1, 0, 1);
4899 x_put_x_image (f, oimg, pixmap, img->width, img->height);
4900 x_destroy_x_image (oimg);
4901 img->pixmap = pixmap;
4902 #ifdef COLOR_TABLE_SUPPORT
4903 img->colors = colors_in_color_table (&img->ncolors);
4904 free_color_table ();
4905 #endif /* COLOR_TABLE_SUPPORT */
4909 /* On frame F, perform edge-detection on image IMG.
4911 MATRIX is a nine-element array specifying the transformation
4912 matrix. See emboss_matrix for an example.
4914 COLOR_ADJUST is a color adjustment added to each pixel of the
4915 outgoing image. */
4917 static void
4918 x_detect_edges (f, img, matrix, color_adjust)
4919 struct frame *f;
4920 struct image *img;
4921 int matrix[9], color_adjust;
4923 XColor *colors = x_to_xcolors (f, img, 1);
4924 XColor *new, *p;
4925 int x, y, i, sum;
4927 for (i = sum = 0; i < 9; ++i)
4928 sum += eabs (matrix[i]);
4930 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4932 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
4934 for (y = 0; y < img->height; ++y)
4936 p = COLOR (new, 0, y);
4937 p->red = p->green = p->blue = 0xffff/2;
4938 p = COLOR (new, img->width - 1, y);
4939 p->red = p->green = p->blue = 0xffff/2;
4942 for (x = 1; x < img->width - 1; ++x)
4944 p = COLOR (new, x, 0);
4945 p->red = p->green = p->blue = 0xffff/2;
4946 p = COLOR (new, x, img->height - 1);
4947 p->red = p->green = p->blue = 0xffff/2;
4950 for (y = 1; y < img->height - 1; ++y)
4952 p = COLOR (new, 1, y);
4954 for (x = 1; x < img->width - 1; ++x, ++p)
4956 int r, g, b, y1, x1;
4958 r = g = b = i = 0;
4959 for (y1 = y - 1; y1 < y + 2; ++y1)
4960 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
4961 if (matrix[i])
4963 XColor *t = COLOR (colors, x1, y1);
4964 r += matrix[i] * t->red;
4965 g += matrix[i] * t->green;
4966 b += matrix[i] * t->blue;
4969 r = (r / sum + color_adjust) & 0xffff;
4970 g = (g / sum + color_adjust) & 0xffff;
4971 b = (b / sum + color_adjust) & 0xffff;
4972 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
4976 xfree (colors);
4977 x_from_xcolors (f, img, new);
4979 #undef COLOR
4983 /* Perform the pre-defined `emboss' edge-detection on image IMG
4984 on frame F. */
4986 static void
4987 x_emboss (f, img)
4988 struct frame *f;
4989 struct image *img;
4991 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
4995 /* Transform image IMG which is used on frame F with a Laplace
4996 edge-detection algorithm. The result is an image that can be used
4997 to draw disabled buttons, for example. */
4999 static void
5000 x_laplace (f, img)
5001 struct frame *f;
5002 struct image *img;
5004 x_detect_edges (f, img, laplace_matrix, 45000);
5008 /* Perform edge-detection on image IMG on frame F, with specified
5009 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5011 MATRIX must be either
5013 - a list of at least 9 numbers in row-major form
5014 - a vector of at least 9 numbers
5016 COLOR_ADJUST nil means use a default; otherwise it must be a
5017 number. */
5019 static void
5020 x_edge_detection (f, img, matrix, color_adjust)
5021 struct frame *f;
5022 struct image *img;
5023 Lisp_Object matrix, color_adjust;
5025 int i = 0;
5026 int trans[9];
5028 if (CONSP (matrix))
5030 for (i = 0;
5031 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5032 ++i, matrix = XCDR (matrix))
5033 trans[i] = XFLOATINT (XCAR (matrix));
5035 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5037 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5038 trans[i] = XFLOATINT (AREF (matrix, i));
5041 if (NILP (color_adjust))
5042 color_adjust = make_number (0xffff / 2);
5044 if (i == 9 && NUMBERP (color_adjust))
5045 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5049 /* Transform image IMG on frame F so that it looks disabled. */
5051 static void
5052 x_disable_image (f, img)
5053 struct frame *f;
5054 struct image *img;
5056 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5057 #ifdef HAVE_NTGUI
5058 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5059 #else
5060 int n_planes = dpyinfo->n_planes;
5061 #endif /* HAVE_NTGUI */
5063 if (n_planes >= 2)
5065 /* Color (or grayscale). Convert to gray, and equalize. Just
5066 drawing such images with a stipple can look very odd, so
5067 we're using this method instead. */
5068 XColor *colors = x_to_xcolors (f, img, 1);
5069 XColor *p, *end;
5070 const int h = 15000;
5071 const int l = 30000;
5073 for (p = colors, end = colors + img->width * img->height;
5074 p < end;
5075 ++p)
5077 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5078 int i2 = (0xffff - h - l) * i / 0xffff + l;
5079 p->red = p->green = p->blue = i2;
5082 x_from_xcolors (f, img, colors);
5085 /* Draw a cross over the disabled image, if we must or if we
5086 should. */
5087 if (n_planes < 2 || cross_disabled_images)
5089 #ifndef HAVE_NTGUI
5090 Display *dpy = FRAME_X_DISPLAY (f);
5091 GC gc;
5093 #ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5095 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5097 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
5098 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5099 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5100 img->width - 1, img->height - 1);
5101 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5102 img->width - 1, 0);
5103 XFreeGC (dpy, gc);
5105 if (img->mask)
5107 gc = XCreateGC (dpy, img->mask, 0, NULL);
5108 XSetForeground (dpy, gc, MaskForeground (f));
5109 XDrawLine (dpy, img->mask, gc, 0, 0,
5110 img->width - 1, img->height - 1);
5111 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5112 img->width - 1, 0);
5113 XFreeGC (dpy, gc);
5115 #endif /* !HAVE_NS */
5116 #else
5117 HDC hdc, bmpdc;
5118 HGDIOBJ prev;
5120 hdc = get_frame_dc (f);
5121 bmpdc = CreateCompatibleDC (hdc);
5122 release_frame_dc (f, hdc);
5124 prev = SelectObject (bmpdc, img->pixmap);
5126 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5127 MoveToEx (bmpdc, 0, 0, NULL);
5128 LineTo (bmpdc, img->width - 1, img->height - 1);
5129 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5130 LineTo (bmpdc, img->width - 1, 0);
5132 if (img->mask)
5134 SelectObject (bmpdc, img->mask);
5135 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5136 MoveToEx (bmpdc, 0, 0, NULL);
5137 LineTo (bmpdc, img->width - 1, img->height - 1);
5138 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5139 LineTo (bmpdc, img->width - 1, 0);
5141 SelectObject (bmpdc, prev);
5142 DeleteDC (bmpdc);
5143 #endif /* HAVE_NTGUI */
5148 /* Build a mask for image IMG which is used on frame F. FILE is the
5149 name of an image file, for error messages. HOW determines how to
5150 determine the background color of IMG. If it is a list '(R G B)',
5151 with R, G, and B being integers >= 0, take that as the color of the
5152 background. Otherwise, determine the background color of IMG
5153 heuristically. Value is non-zero if successful. */
5155 static int
5156 x_build_heuristic_mask (f, img, how)
5157 struct frame *f;
5158 struct image *img;
5159 Lisp_Object how;
5161 XImagePtr_or_DC ximg;
5162 #ifndef HAVE_NTGUI
5163 XImagePtr mask_img;
5164 #else
5165 HDC frame_dc;
5166 HGDIOBJ prev;
5167 char *mask_img;
5168 int row_width;
5169 #endif /* HAVE_NTGUI */
5170 int x, y, rc, use_img_background;
5171 unsigned long bg = 0;
5173 if (img->mask)
5175 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5176 img->mask = NO_PIXMAP;
5177 img->background_transparent_valid = 0;
5180 #ifndef HAVE_NTGUI
5181 #ifndef HAVE_NS
5182 /* Create an image and pixmap serving as mask. */
5183 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5184 &mask_img, &img->mask);
5185 if (!rc)
5186 return 0;
5187 #endif /* !HAVE_NS */
5189 /* Get the X image of IMG->pixmap. */
5190 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5191 img->width, img->height,
5192 ~0, ZPixmap);
5193 #else
5194 /* Create the bit array serving as mask. */
5195 row_width = (img->width + 7) / 8;
5196 mask_img = xmalloc (row_width * img->height);
5197 bzero (mask_img, row_width * img->height);
5199 /* Create a memory device context for IMG->pixmap. */
5200 frame_dc = get_frame_dc (f);
5201 ximg = CreateCompatibleDC (frame_dc);
5202 release_frame_dc (f, frame_dc);
5203 prev = SelectObject (ximg, img->pixmap);
5204 #endif /* HAVE_NTGUI */
5206 /* Determine the background color of ximg. If HOW is `(R G B)'
5207 take that as color. Otherwise, use the image's background color. */
5208 use_img_background = 1;
5210 if (CONSP (how))
5212 int rgb[3], i;
5214 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5216 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5217 how = XCDR (how);
5220 if (i == 3 && NILP (how))
5222 char color_name[30];
5223 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5224 bg = (
5225 #ifdef HAVE_NTGUI
5226 0x00ffffff & /* Filter out palette info. */
5227 #endif /* HAVE_NTGUI */
5228 x_alloc_image_color (f, img, build_string (color_name), 0));
5229 use_img_background = 0;
5233 if (use_img_background)
5234 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5236 /* Set all bits in mask_img to 1 whose color in ximg is different
5237 from the background color bg. */
5238 #ifndef HAVE_NTGUI
5239 for (y = 0; y < img->height; ++y)
5240 for (x = 0; x < img->width; ++x)
5241 #ifndef HAVE_NS
5242 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5243 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5244 #else
5245 if (XGetPixel (ximg, x, y) == bg)
5246 ns_set_alpha(ximg, x, y, 0);
5247 #endif /* HAVE_NS */
5248 #ifndef HAVE_NS
5249 /* Fill in the background_transparent field while we have the mask handy. */
5250 image_background_transparent (img, f, mask_img);
5252 /* Put mask_img into img->mask. */
5253 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5254 x_destroy_x_image (mask_img);
5255 #endif /* !HAVE_NS */
5256 #else
5257 for (y = 0; y < img->height; ++y)
5258 for (x = 0; x < img->width; ++x)
5260 COLORREF p = GetPixel (ximg, x, y);
5261 if (p != bg)
5262 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5265 /* Create the mask image. */
5266 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5267 mask_img);
5268 /* Fill in the background_transparent field while we have the mask handy. */
5269 SelectObject (ximg, img->mask);
5270 image_background_transparent (img, f, ximg);
5272 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5273 xfree (mask_img);
5274 #endif /* HAVE_NTGUI */
5276 Destroy_Image (ximg, prev);
5278 return 1;
5282 /***********************************************************************
5283 PBM (mono, gray, color)
5284 ***********************************************************************/
5286 static int pbm_image_p P_ ((Lisp_Object object));
5287 static int pbm_load P_ ((struct frame *f, struct image *img));
5288 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5290 /* The symbol `pbm' identifying images of this type. */
5292 Lisp_Object Qpbm;
5294 /* Indices of image specification fields in gs_format, below. */
5296 enum pbm_keyword_index
5298 PBM_TYPE,
5299 PBM_FILE,
5300 PBM_DATA,
5301 PBM_ASCENT,
5302 PBM_MARGIN,
5303 PBM_RELIEF,
5304 PBM_ALGORITHM,
5305 PBM_HEURISTIC_MASK,
5306 PBM_MASK,
5307 PBM_FOREGROUND,
5308 PBM_BACKGROUND,
5309 PBM_LAST
5312 /* Vector of image_keyword structures describing the format
5313 of valid user-defined image specifications. */
5315 static struct image_keyword pbm_format[PBM_LAST] =
5317 {":type", IMAGE_SYMBOL_VALUE, 1},
5318 {":file", IMAGE_STRING_VALUE, 0},
5319 {":data", IMAGE_STRING_VALUE, 0},
5320 {":ascent", IMAGE_ASCENT_VALUE, 0},
5321 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5322 {":relief", IMAGE_INTEGER_VALUE, 0},
5323 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5324 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5325 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5326 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5327 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5330 /* Structure describing the image type `pbm'. */
5332 static struct image_type pbm_type =
5334 &Qpbm,
5335 pbm_image_p,
5336 pbm_load,
5337 x_clear_image,
5338 NULL
5342 /* Return non-zero if OBJECT is a valid PBM image specification. */
5344 static int
5345 pbm_image_p (object)
5346 Lisp_Object object;
5348 struct image_keyword fmt[PBM_LAST];
5350 bcopy (pbm_format, fmt, sizeof fmt);
5352 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5353 return 0;
5355 /* Must specify either :data or :file. */
5356 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5360 /* Scan a decimal number from *S and return it. Advance *S while
5361 reading the number. END is the end of the string. Value is -1 at
5362 end of input. */
5364 static int
5365 pbm_scan_number (s, end)
5366 unsigned char **s, *end;
5368 int c = 0, val = -1;
5370 while (*s < end)
5372 /* Skip white-space. */
5373 while (*s < end && (c = *(*s)++, isspace (c)))
5376 if (c == '#')
5378 /* Skip comment to end of line. */
5379 while (*s < end && (c = *(*s)++, c != '\n'))
5382 else if (isdigit (c))
5384 /* Read decimal number. */
5385 val = c - '0';
5386 while (*s < end && (c = *(*s)++, isdigit (c)))
5387 val = 10 * val + c - '0';
5388 break;
5390 else
5391 break;
5394 return val;
5398 #ifdef HAVE_NTGUI
5399 #if 0 /* Unused. ++kfs */
5401 /* Read FILE into memory. Value is a pointer to a buffer allocated
5402 with xmalloc holding FILE's contents. Value is null if an error
5403 occurred. *SIZE is set to the size of the file. */
5405 static char *
5406 pbm_read_file (file, size)
5407 Lisp_Object file;
5408 int *size;
5410 FILE *fp = NULL;
5411 char *buf = NULL;
5412 struct stat st;
5414 if (stat (SDATA (file), &st) == 0
5415 && (fp = fopen (SDATA (file), "rb")) != NULL
5416 && (buf = (char *) xmalloc (st.st_size),
5417 fread (buf, 1, st.st_size, fp) == st.st_size))
5419 *size = st.st_size;
5420 fclose (fp);
5422 else
5424 if (fp)
5425 fclose (fp);
5426 if (buf)
5428 xfree (buf);
5429 buf = NULL;
5433 return buf;
5435 #endif
5436 #endif /* HAVE_NTGUI */
5438 /* Load PBM image IMG for use on frame F. */
5440 static int
5441 pbm_load (f, img)
5442 struct frame *f;
5443 struct image *img;
5445 int raw_p, x, y;
5446 int width, height, max_color_idx = 0;
5447 XImagePtr ximg;
5448 Lisp_Object file, specified_file;
5449 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5450 struct gcpro gcpro1;
5451 unsigned char *contents = NULL;
5452 unsigned char *end, *p;
5453 int size;
5455 specified_file = image_spec_value (img->spec, QCfile, NULL);
5456 file = Qnil;
5457 GCPRO1 (file);
5459 if (STRINGP (specified_file))
5461 file = x_find_image_file (specified_file);
5462 if (!STRINGP (file))
5464 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5465 UNGCPRO;
5466 return 0;
5469 contents = slurp_file (SDATA (file), &size);
5470 if (contents == NULL)
5472 image_error ("Error reading `%s'", file, Qnil);
5473 UNGCPRO;
5474 return 0;
5477 p = contents;
5478 end = contents + size;
5480 else
5482 Lisp_Object data;
5483 data = image_spec_value (img->spec, QCdata, NULL);
5484 p = SDATA (data);
5485 end = p + SBYTES (data);
5488 /* Check magic number. */
5489 if (end - p < 2 || *p++ != 'P')
5491 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5492 error:
5493 xfree (contents);
5494 UNGCPRO;
5495 return 0;
5498 switch (*p++)
5500 case '1':
5501 raw_p = 0, type = PBM_MONO;
5502 break;
5504 case '2':
5505 raw_p = 0, type = PBM_GRAY;
5506 break;
5508 case '3':
5509 raw_p = 0, type = PBM_COLOR;
5510 break;
5512 case '4':
5513 raw_p = 1, type = PBM_MONO;
5514 break;
5516 case '5':
5517 raw_p = 1, type = PBM_GRAY;
5518 break;
5520 case '6':
5521 raw_p = 1, type = PBM_COLOR;
5522 break;
5524 default:
5525 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5526 goto error;
5529 /* Read width, height, maximum color-component. Characters
5530 starting with `#' up to the end of a line are ignored. */
5531 width = pbm_scan_number (&p, end);
5532 height = pbm_scan_number (&p, end);
5534 if (type != PBM_MONO)
5536 max_color_idx = pbm_scan_number (&p, end);
5537 if (max_color_idx > 65535 || max_color_idx < 0)
5539 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
5540 goto error;
5544 if (!check_image_size (f, width, height))
5546 image_error ("Invalid image size", Qnil, Qnil);
5547 goto error;
5550 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5551 &ximg, &img->pixmap))
5552 goto error;
5554 /* Initialize the color hash table. */
5555 init_color_table ();
5557 if (type == PBM_MONO)
5559 int c = 0, g;
5560 struct image_keyword fmt[PBM_LAST];
5561 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5562 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5564 /* Parse the image specification. */
5565 bcopy (pbm_format, fmt, sizeof fmt);
5566 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5568 /* Get foreground and background colors, maybe allocate colors. */
5569 if (fmt[PBM_FOREGROUND].count
5570 && STRINGP (fmt[PBM_FOREGROUND].value))
5571 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5572 if (fmt[PBM_BACKGROUND].count
5573 && STRINGP (fmt[PBM_BACKGROUND].value))
5575 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5576 img->background = bg;
5577 img->background_valid = 1;
5580 for (y = 0; y < height; ++y)
5581 for (x = 0; x < width; ++x)
5583 if (raw_p)
5585 if ((x & 7) == 0)
5587 if (p >= end)
5589 x_destroy_x_image (ximg);
5590 x_clear_image (f, img);
5591 image_error ("Invalid image size in image `%s'",
5592 img->spec, Qnil);
5593 goto error;
5595 c = *p++;
5597 g = c & 0x80;
5598 c <<= 1;
5600 else
5601 g = pbm_scan_number (&p, end);
5603 XPutPixel (ximg, x, y, g ? fg : bg);
5606 else
5608 int expected_size = height * width;
5609 if (max_color_idx > 255)
5610 expected_size *= 2;
5611 if (type == PBM_COLOR)
5612 expected_size *= 3;
5614 if (raw_p && p + expected_size > end)
5616 x_destroy_x_image (ximg);
5617 x_clear_image (f, img);
5618 image_error ("Invalid image size in image `%s'",
5619 img->spec, Qnil);
5620 goto error;
5623 for (y = 0; y < height; ++y)
5624 for (x = 0; x < width; ++x)
5626 int r, g, b;
5628 if (type == PBM_GRAY && raw_p)
5630 r = g = b = *p++;
5631 if (max_color_idx > 255)
5632 r = g = b = r * 256 + *p++;
5634 else if (type == PBM_GRAY)
5635 r = g = b = pbm_scan_number (&p, end);
5636 else if (raw_p)
5638 r = *p++;
5639 if (max_color_idx > 255)
5640 r = r * 256 + *p++;
5641 g = *p++;
5642 if (max_color_idx > 255)
5643 g = g * 256 + *p++;
5644 b = *p++;
5645 if (max_color_idx > 255)
5646 b = b * 256 + *p++;
5648 else
5650 r = pbm_scan_number (&p, end);
5651 g = pbm_scan_number (&p, end);
5652 b = pbm_scan_number (&p, end);
5655 if (r < 0 || g < 0 || b < 0)
5657 x_destroy_x_image (ximg);
5658 image_error ("Invalid pixel value in image `%s'",
5659 img->spec, Qnil);
5660 goto error;
5663 /* RGB values are now in the range 0..max_color_idx.
5664 Scale this to the range 0..0xffff supported by X. */
5665 r = (double) r * 65535 / max_color_idx;
5666 g = (double) g * 65535 / max_color_idx;
5667 b = (double) b * 65535 / max_color_idx;
5668 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5672 #ifdef COLOR_TABLE_SUPPORT
5673 /* Store in IMG->colors the colors allocated for the image, and
5674 free the color table. */
5675 img->colors = colors_in_color_table (&img->ncolors);
5676 free_color_table ();
5677 #endif /* COLOR_TABLE_SUPPORT */
5679 img->width = width;
5680 img->height = height;
5682 /* Maybe fill in the background field while we have ximg handy. */
5684 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5685 /* Casting avoids a GCC warning. */
5686 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5688 /* Put the image into a pixmap. */
5689 x_put_x_image (f, ximg, img->pixmap, width, height);
5690 x_destroy_x_image (ximg);
5692 /* X and W32 versions did it here, MAC version above. ++kfs
5693 img->width = width;
5694 img->height = height; */
5696 UNGCPRO;
5697 xfree (contents);
5698 return 1;
5702 /***********************************************************************
5704 ***********************************************************************/
5706 #if defined (HAVE_PNG) || defined (HAVE_NS)
5708 /* Function prototypes. */
5710 static int png_image_p P_ ((Lisp_Object object));
5711 static int png_load P_ ((struct frame *f, struct image *img));
5713 /* The symbol `png' identifying images of this type. */
5715 Lisp_Object Qpng;
5717 /* Indices of image specification fields in png_format, below. */
5719 enum png_keyword_index
5721 PNG_TYPE,
5722 PNG_DATA,
5723 PNG_FILE,
5724 PNG_ASCENT,
5725 PNG_MARGIN,
5726 PNG_RELIEF,
5727 PNG_ALGORITHM,
5728 PNG_HEURISTIC_MASK,
5729 PNG_MASK,
5730 PNG_BACKGROUND,
5731 PNG_LAST
5734 /* Vector of image_keyword structures describing the format
5735 of valid user-defined image specifications. */
5737 static struct image_keyword png_format[PNG_LAST] =
5739 {":type", IMAGE_SYMBOL_VALUE, 1},
5740 {":data", IMAGE_STRING_VALUE, 0},
5741 {":file", IMAGE_STRING_VALUE, 0},
5742 {":ascent", IMAGE_ASCENT_VALUE, 0},
5743 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5744 {":relief", IMAGE_INTEGER_VALUE, 0},
5745 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5746 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5747 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5748 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5751 /* Structure describing the image type `png'. */
5753 static struct image_type png_type =
5755 &Qpng,
5756 png_image_p,
5757 png_load,
5758 x_clear_image,
5759 NULL
5762 /* Return non-zero if OBJECT is a valid PNG image specification. */
5764 static int
5765 png_image_p (object)
5766 Lisp_Object object;
5768 struct image_keyword fmt[PNG_LAST];
5769 bcopy (png_format, fmt, sizeof fmt);
5771 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5772 return 0;
5774 /* Must specify either the :data or :file keyword. */
5775 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5778 #endif /* HAVE_PNG || HAVE_NS */
5781 #ifdef HAVE_PNG
5783 #if defined HAVE_LIBPNG_PNG_H
5784 # include <libpng/png.h>
5785 #else
5786 # include <png.h>
5787 #endif
5789 #ifdef HAVE_NTGUI
5790 /* PNG library details. */
5792 DEF_IMGLIB_FN (png_get_io_ptr);
5793 DEF_IMGLIB_FN (png_check_sig);
5794 DEF_IMGLIB_FN (png_create_read_struct);
5795 DEF_IMGLIB_FN (png_create_info_struct);
5796 DEF_IMGLIB_FN (png_destroy_read_struct);
5797 DEF_IMGLIB_FN (png_set_read_fn);
5798 DEF_IMGLIB_FN (png_set_sig_bytes);
5799 DEF_IMGLIB_FN (png_read_info);
5800 DEF_IMGLIB_FN (png_get_IHDR);
5801 DEF_IMGLIB_FN (png_get_valid);
5802 DEF_IMGLIB_FN (png_set_strip_16);
5803 DEF_IMGLIB_FN (png_set_expand);
5804 DEF_IMGLIB_FN (png_set_gray_to_rgb);
5805 DEF_IMGLIB_FN (png_set_background);
5806 DEF_IMGLIB_FN (png_get_bKGD);
5807 DEF_IMGLIB_FN (png_read_update_info);
5808 DEF_IMGLIB_FN (png_get_channels);
5809 DEF_IMGLIB_FN (png_get_rowbytes);
5810 DEF_IMGLIB_FN (png_read_image);
5811 DEF_IMGLIB_FN (png_read_end);
5812 DEF_IMGLIB_FN (png_error);
5814 static int
5815 init_png_functions (Lisp_Object libraries)
5817 HMODULE library;
5819 /* Try loading libpng under probable names. */
5820 if (!(library = w32_delayed_load (libraries, Qpng)))
5821 return 0;
5823 LOAD_IMGLIB_FN (library, png_get_io_ptr);
5824 LOAD_IMGLIB_FN (library, png_check_sig);
5825 LOAD_IMGLIB_FN (library, png_create_read_struct);
5826 LOAD_IMGLIB_FN (library, png_create_info_struct);
5827 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5828 LOAD_IMGLIB_FN (library, png_set_read_fn);
5829 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5830 LOAD_IMGLIB_FN (library, png_read_info);
5831 LOAD_IMGLIB_FN (library, png_get_IHDR);
5832 LOAD_IMGLIB_FN (library, png_get_valid);
5833 LOAD_IMGLIB_FN (library, png_set_strip_16);
5834 LOAD_IMGLIB_FN (library, png_set_expand);
5835 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5836 LOAD_IMGLIB_FN (library, png_set_background);
5837 LOAD_IMGLIB_FN (library, png_get_bKGD);
5838 LOAD_IMGLIB_FN (library, png_read_update_info);
5839 LOAD_IMGLIB_FN (library, png_get_channels);
5840 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5841 LOAD_IMGLIB_FN (library, png_read_image);
5842 LOAD_IMGLIB_FN (library, png_read_end);
5843 LOAD_IMGLIB_FN (library, png_error);
5844 return 1;
5846 #else
5848 #define fn_png_get_io_ptr png_get_io_ptr
5849 #define fn_png_check_sig png_check_sig
5850 #define fn_png_create_read_struct png_create_read_struct
5851 #define fn_png_create_info_struct png_create_info_struct
5852 #define fn_png_destroy_read_struct png_destroy_read_struct
5853 #define fn_png_set_read_fn png_set_read_fn
5854 #define fn_png_set_sig_bytes png_set_sig_bytes
5855 #define fn_png_read_info png_read_info
5856 #define fn_png_get_IHDR png_get_IHDR
5857 #define fn_png_get_valid png_get_valid
5858 #define fn_png_set_strip_16 png_set_strip_16
5859 #define fn_png_set_expand png_set_expand
5860 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5861 #define fn_png_set_background png_set_background
5862 #define fn_png_get_bKGD png_get_bKGD
5863 #define fn_png_read_update_info png_read_update_info
5864 #define fn_png_get_channels png_get_channels
5865 #define fn_png_get_rowbytes png_get_rowbytes
5866 #define fn_png_read_image png_read_image
5867 #define fn_png_read_end png_read_end
5868 #define fn_png_error png_error
5870 #endif /* HAVE_NTGUI */
5872 /* Error and warning handlers installed when the PNG library
5873 is initialized. */
5875 static void
5876 my_png_error (png_ptr, msg)
5877 png_struct *png_ptr;
5878 char *msg;
5880 xassert (png_ptr != NULL);
5881 image_error ("PNG error: %s", build_string (msg), Qnil);
5882 longjmp (png_ptr->jmpbuf, 1);
5886 static void
5887 my_png_warning (png_ptr, msg)
5888 png_struct *png_ptr;
5889 char *msg;
5891 xassert (png_ptr != NULL);
5892 image_error ("PNG warning: %s", build_string (msg), Qnil);
5895 /* Memory source for PNG decoding. */
5897 struct png_memory_storage
5899 unsigned char *bytes; /* The data */
5900 size_t len; /* How big is it? */
5901 int index; /* Where are we? */
5905 /* Function set as reader function when reading PNG image from memory.
5906 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5907 bytes from the input to DATA. */
5909 static void
5910 png_read_from_memory (png_ptr, data, length)
5911 png_structp png_ptr;
5912 png_bytep data;
5913 png_size_t length;
5915 struct png_memory_storage *tbr
5916 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5918 if (length > tbr->len - tbr->index)
5919 fn_png_error (png_ptr, "Read error");
5921 bcopy (tbr->bytes + tbr->index, data, length);
5922 tbr->index = tbr->index + length;
5926 /* Function set as reader function when reading PNG image from a file.
5927 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5928 bytes from the input to DATA. */
5930 static void
5931 png_read_from_file (png_ptr, data, length)
5932 png_structp png_ptr;
5933 png_bytep data;
5934 png_size_t length;
5936 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
5938 if (fread (data, 1, length, fp) < length)
5939 fn_png_error (png_ptr, "Read error");
5943 /* Load PNG image IMG for use on frame F. Value is non-zero if
5944 successful. */
5946 static int
5947 png_load (f, img)
5948 struct frame *f;
5949 struct image *img;
5951 Lisp_Object file, specified_file;
5952 Lisp_Object specified_data;
5953 int x, y, i;
5954 XImagePtr ximg, mask_img = NULL;
5955 struct gcpro gcpro1;
5956 png_struct *png_ptr = NULL;
5957 png_info *info_ptr = NULL, *end_info = NULL;
5958 FILE *volatile fp = NULL;
5959 png_byte sig[8];
5960 png_byte * volatile pixels = NULL;
5961 png_byte ** volatile rows = NULL;
5962 png_uint_32 width, height;
5963 int bit_depth, color_type, interlace_type;
5964 png_byte channels;
5965 png_uint_32 row_bytes;
5966 int transparent_p;
5967 struct png_memory_storage tbr; /* Data to be read */
5969 /* Find out what file to load. */
5970 specified_file = image_spec_value (img->spec, QCfile, NULL);
5971 specified_data = image_spec_value (img->spec, QCdata, NULL);
5972 file = Qnil;
5973 GCPRO1 (file);
5975 if (NILP (specified_data))
5977 file = x_find_image_file (specified_file);
5978 if (!STRINGP (file))
5980 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5981 UNGCPRO;
5982 return 0;
5985 /* Open the image file. */
5986 fp = fopen (SDATA (file), "rb");
5987 if (!fp)
5989 image_error ("Cannot open image file `%s'", file, Qnil);
5990 UNGCPRO;
5991 return 0;
5994 /* Check PNG signature. */
5995 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
5996 || !fn_png_check_sig (sig, sizeof sig))
5998 image_error ("Not a PNG file: `%s'", file, Qnil);
5999 UNGCPRO;
6000 fclose (fp);
6001 return 0;
6004 else
6006 /* Read from memory. */
6007 tbr.bytes = SDATA (specified_data);
6008 tbr.len = SBYTES (specified_data);
6009 tbr.index = 0;
6011 /* Check PNG signature. */
6012 if (tbr.len < sizeof sig
6013 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6015 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6016 UNGCPRO;
6017 return 0;
6020 /* Need to skip past the signature. */
6021 tbr.bytes += sizeof (sig);
6024 /* Initialize read and info structs for PNG lib. Casting return
6025 value avoids a GCC warning on W32. */
6026 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6027 NULL, my_png_error,
6028 my_png_warning);
6029 if (!png_ptr)
6031 if (fp) fclose (fp);
6032 UNGCPRO;
6033 return 0;
6036 /* Casting return value avoids a GCC warning on W32. */
6037 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6038 if (!info_ptr)
6040 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6041 if (fp) fclose (fp);
6042 UNGCPRO;
6043 return 0;
6046 /* Casting return value avoids a GCC warning on W32. */
6047 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6048 if (!end_info)
6050 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6051 if (fp) fclose (fp);
6052 UNGCPRO;
6053 return 0;
6056 /* Set error jump-back. We come back here when the PNG library
6057 detects an error. */
6058 if (setjmp (png_ptr->jmpbuf))
6060 error:
6061 if (png_ptr)
6062 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6063 xfree (pixels);
6064 xfree (rows);
6065 if (fp) fclose (fp);
6066 UNGCPRO;
6067 return 0;
6070 /* Read image info. */
6071 if (!NILP (specified_data))
6072 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6073 else
6074 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6076 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6077 fn_png_read_info (png_ptr, info_ptr);
6078 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6079 &interlace_type, NULL, NULL);
6081 if (!check_image_size (f, width, height))
6082 goto error;
6084 /* If image contains simply transparency data, we prefer to
6085 construct a clipping mask. */
6086 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6087 transparent_p = 1;
6088 else
6089 transparent_p = 0;
6091 /* This function is easier to write if we only have to handle
6092 one data format: RGB or RGBA with 8 bits per channel. Let's
6093 transform other formats into that format. */
6095 /* Strip more than 8 bits per channel. */
6096 if (bit_depth == 16)
6097 fn_png_set_strip_16 (png_ptr);
6099 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6100 if available. */
6101 fn_png_set_expand (png_ptr);
6103 /* Convert grayscale images to RGB. */
6104 if (color_type == PNG_COLOR_TYPE_GRAY
6105 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6106 fn_png_set_gray_to_rgb (png_ptr);
6108 /* Handle alpha channel by combining the image with a background
6109 color. Do this only if a real alpha channel is supplied. For
6110 simple transparency, we prefer a clipping mask. */
6111 if (!transparent_p)
6113 /* png_color_16 *image_bg; */
6114 Lisp_Object specified_bg
6115 = image_spec_value (img->spec, QCbackground, NULL);
6116 int shift = (bit_depth == 16) ? 0 : 8;
6118 if (STRINGP (specified_bg))
6119 /* The user specified `:background', use that. */
6121 XColor color;
6122 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6124 png_color_16 user_bg;
6126 bzero (&user_bg, sizeof user_bg);
6127 user_bg.red = color.red >> shift;
6128 user_bg.green = color.green >> shift;
6129 user_bg.blue = color.blue >> shift;
6131 fn_png_set_background (png_ptr, &user_bg,
6132 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6135 else
6137 /* We use the current frame background, ignoring any default
6138 background color set by the image. */
6139 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
6140 XColor color;
6141 png_color_16 frame_background;
6143 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6144 x_query_color (f, &color);
6146 bzero (&frame_background, sizeof frame_background);
6147 frame_background.red = color.red >> shift;
6148 frame_background.green = color.green >> shift;
6149 frame_background.blue = color.blue >> shift;
6150 #endif /* HAVE_X_WINDOWS */
6152 fn_png_set_background (png_ptr, &frame_background,
6153 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6157 /* Update info structure. */
6158 fn_png_read_update_info (png_ptr, info_ptr);
6160 /* Get number of channels. Valid values are 1 for grayscale images
6161 and images with a palette, 2 for grayscale images with transparency
6162 information (alpha channel), 3 for RGB images, and 4 for RGB
6163 images with alpha channel, i.e. RGBA. If conversions above were
6164 sufficient we should only have 3 or 4 channels here. */
6165 channels = fn_png_get_channels (png_ptr, info_ptr);
6166 xassert (channels == 3 || channels == 4);
6168 /* Number of bytes needed for one row of the image. */
6169 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6171 /* Allocate memory for the image. */
6172 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6173 rows = (png_byte **) xmalloc (height * sizeof *rows);
6174 for (i = 0; i < height; ++i)
6175 rows[i] = pixels + i * row_bytes;
6177 /* Read the entire image. */
6178 fn_png_read_image (png_ptr, rows);
6179 fn_png_read_end (png_ptr, info_ptr);
6180 if (fp)
6182 fclose (fp);
6183 fp = NULL;
6186 /* Create the X image and pixmap. */
6187 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6188 &img->pixmap))
6189 goto error;
6191 /* Create an image and pixmap serving as mask if the PNG image
6192 contains an alpha channel. */
6193 if (channels == 4
6194 && !transparent_p
6195 && !x_create_x_image_and_pixmap (f, width, height, 1,
6196 &mask_img, &img->mask))
6198 x_destroy_x_image (ximg);
6199 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6200 img->pixmap = NO_PIXMAP;
6201 goto error;
6204 /* Fill the X image and mask from PNG data. */
6205 init_color_table ();
6207 for (y = 0; y < height; ++y)
6209 png_byte *p = rows[y];
6211 for (x = 0; x < width; ++x)
6213 unsigned r, g, b;
6215 r = *p++ << 8;
6216 g = *p++ << 8;
6217 b = *p++ << 8;
6218 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6219 /* An alpha channel, aka mask channel, associates variable
6220 transparency with an image. Where other image formats
6221 support binary transparency---fully transparent or fully
6222 opaque---PNG allows up to 254 levels of partial transparency.
6223 The PNG library implements partial transparency by combining
6224 the image with a specified background color.
6226 I'm not sure how to handle this here nicely: because the
6227 background on which the image is displayed may change, for
6228 real alpha channel support, it would be necessary to create
6229 a new image for each possible background.
6231 What I'm doing now is that a mask is created if we have
6232 boolean transparency information. Otherwise I'm using
6233 the frame's background color to combine the image with. */
6235 if (channels == 4)
6237 if (mask_img)
6238 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6239 ++p;
6244 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6245 /* Set IMG's background color from the PNG image, unless the user
6246 overrode it. */
6248 png_color_16 *bg;
6249 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6251 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6252 img->background_valid = 1;
6256 #ifdef COLOR_TABLE_SUPPORT
6257 /* Remember colors allocated for this image. */
6258 img->colors = colors_in_color_table (&img->ncolors);
6259 free_color_table ();
6260 #endif /* COLOR_TABLE_SUPPORT */
6262 /* Clean up. */
6263 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6264 xfree (rows);
6265 xfree (pixels);
6267 img->width = width;
6268 img->height = height;
6270 /* Maybe fill in the background field while we have ximg handy.
6271 Casting avoids a GCC warning. */
6272 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6274 /* Put the image into the pixmap, then free the X image and its buffer. */
6275 x_put_x_image (f, ximg, img->pixmap, width, height);
6276 x_destroy_x_image (ximg);
6278 /* Same for the mask. */
6279 if (mask_img)
6281 /* Fill in the background_transparent field while we have the
6282 mask handy. Casting avoids a GCC warning. */
6283 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6285 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6286 x_destroy_x_image (mask_img);
6289 UNGCPRO;
6290 return 1;
6293 #else /* HAVE_PNG */
6295 #ifdef HAVE_NS
6296 static int
6297 png_load (struct frame *f, struct image *img)
6299 return ns_load_image(f, img,
6300 image_spec_value (img->spec, QCfile, NULL),
6301 image_spec_value (img->spec, QCdata, NULL));
6303 #endif /* HAVE_NS */
6306 #endif /* !HAVE_PNG */
6310 /***********************************************************************
6311 JPEG
6312 ***********************************************************************/
6314 #if defined (HAVE_JPEG) || defined (HAVE_NS)
6316 static int jpeg_image_p P_ ((Lisp_Object object));
6317 static int jpeg_load P_ ((struct frame *f, struct image *img));
6319 /* The symbol `jpeg' identifying images of this type. */
6321 Lisp_Object Qjpeg;
6323 /* Indices of image specification fields in gs_format, below. */
6325 enum jpeg_keyword_index
6327 JPEG_TYPE,
6328 JPEG_DATA,
6329 JPEG_FILE,
6330 JPEG_ASCENT,
6331 JPEG_MARGIN,
6332 JPEG_RELIEF,
6333 JPEG_ALGORITHM,
6334 JPEG_HEURISTIC_MASK,
6335 JPEG_MASK,
6336 JPEG_BACKGROUND,
6337 JPEG_LAST
6340 /* Vector of image_keyword structures describing the format
6341 of valid user-defined image specifications. */
6343 static struct image_keyword jpeg_format[JPEG_LAST] =
6345 {":type", IMAGE_SYMBOL_VALUE, 1},
6346 {":data", IMAGE_STRING_VALUE, 0},
6347 {":file", IMAGE_STRING_VALUE, 0},
6348 {":ascent", IMAGE_ASCENT_VALUE, 0},
6349 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6350 {":relief", IMAGE_INTEGER_VALUE, 0},
6351 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6352 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6353 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6354 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6357 /* Structure describing the image type `jpeg'. */
6359 static struct image_type jpeg_type =
6361 &Qjpeg,
6362 jpeg_image_p,
6363 jpeg_load,
6364 x_clear_image,
6365 NULL
6368 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6370 static int
6371 jpeg_image_p (object)
6372 Lisp_Object object;
6374 struct image_keyword fmt[JPEG_LAST];
6376 bcopy (jpeg_format, fmt, sizeof fmt);
6378 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6379 return 0;
6381 /* Must specify either the :data or :file keyword. */
6382 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6385 #endif /* HAVE_JPEG || HAVE_NS */
6387 #ifdef HAVE_JPEG
6389 /* Work around a warning about HAVE_STDLIB_H being redefined in
6390 jconfig.h. */
6391 #ifdef HAVE_STDLIB_H
6392 #define HAVE_STDLIB_H_1
6393 #undef HAVE_STDLIB_H
6394 #endif /* HAVE_STLIB_H */
6396 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6397 /* In older releases of the jpeg library, jpeglib.h will define boolean
6398 differently depending on __WIN32__, so make sure it is defined. */
6399 #define __WIN32__ 1
6400 #endif
6402 #include <jpeglib.h>
6403 #include <jerror.h>
6404 #include <setjmp.h>
6406 #ifdef HAVE_STLIB_H_1
6407 #define HAVE_STDLIB_H 1
6408 #endif
6410 #ifdef HAVE_NTGUI
6412 /* JPEG library details. */
6413 DEF_IMGLIB_FN (jpeg_CreateDecompress);
6414 DEF_IMGLIB_FN (jpeg_start_decompress);
6415 DEF_IMGLIB_FN (jpeg_finish_decompress);
6416 DEF_IMGLIB_FN (jpeg_destroy_decompress);
6417 DEF_IMGLIB_FN (jpeg_read_header);
6418 DEF_IMGLIB_FN (jpeg_read_scanlines);
6419 DEF_IMGLIB_FN (jpeg_std_error);
6420 DEF_IMGLIB_FN (jpeg_resync_to_restart);
6422 static int
6423 init_jpeg_functions (Lisp_Object libraries)
6425 HMODULE library;
6427 if (!(library = w32_delayed_load (libraries, Qjpeg)))
6428 return 0;
6430 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6431 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6432 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6433 LOAD_IMGLIB_FN (library, jpeg_read_header);
6434 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6435 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6436 LOAD_IMGLIB_FN (library, jpeg_std_error);
6437 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6438 return 1;
6441 /* Wrapper since we can't directly assign the function pointer
6442 to another function pointer that was declared more completely easily. */
6443 static boolean
6444 jpeg_resync_to_restart_wrapper (cinfo, desired)
6445 j_decompress_ptr cinfo;
6446 int desired;
6448 return fn_jpeg_resync_to_restart (cinfo, desired);
6451 #else
6453 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6454 #define fn_jpeg_start_decompress jpeg_start_decompress
6455 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6456 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6457 #define fn_jpeg_read_header jpeg_read_header
6458 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6459 #define fn_jpeg_std_error jpeg_std_error
6460 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6462 #endif /* HAVE_NTGUI */
6464 struct my_jpeg_error_mgr
6466 struct jpeg_error_mgr pub;
6467 jmp_buf setjmp_buffer;
6471 static void
6472 my_error_exit (cinfo)
6473 j_common_ptr cinfo;
6475 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6476 longjmp (mgr->setjmp_buffer, 1);
6480 /* Init source method for JPEG data source manager. Called by
6481 jpeg_read_header() before any data is actually read. See
6482 libjpeg.doc from the JPEG lib distribution. */
6484 static void
6485 our_common_init_source (cinfo)
6486 j_decompress_ptr cinfo;
6491 /* Method to terminate data source. Called by
6492 jpeg_finish_decompress() after all data has been processed. */
6494 static void
6495 our_common_term_source (cinfo)
6496 j_decompress_ptr cinfo;
6501 /* Fill input buffer method for JPEG data source manager. Called
6502 whenever more data is needed. We read the whole image in one step,
6503 so this only adds a fake end of input marker at the end. */
6505 static JOCTET our_memory_buffer[2];
6507 static boolean
6508 our_memory_fill_input_buffer (cinfo)
6509 j_decompress_ptr cinfo;
6511 /* Insert a fake EOI marker. */
6512 struct jpeg_source_mgr *src = cinfo->src;
6514 our_memory_buffer[0] = (JOCTET) 0xFF;
6515 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
6517 src->next_input_byte = our_memory_buffer;
6518 src->bytes_in_buffer = 2;
6519 return 1;
6523 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6524 is the JPEG data source manager. */
6526 static void
6527 our_memory_skip_input_data (cinfo, num_bytes)
6528 j_decompress_ptr cinfo;
6529 long num_bytes;
6531 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6533 if (src)
6535 if (num_bytes > src->bytes_in_buffer)
6536 ERREXIT (cinfo, JERR_INPUT_EOF);
6538 src->bytes_in_buffer -= num_bytes;
6539 src->next_input_byte += num_bytes;
6544 /* Set up the JPEG lib for reading an image from DATA which contains
6545 LEN bytes. CINFO is the decompression info structure created for
6546 reading the image. */
6548 static void
6549 jpeg_memory_src (cinfo, data, len)
6550 j_decompress_ptr cinfo;
6551 JOCTET *data;
6552 unsigned int len;
6554 struct jpeg_source_mgr *src;
6556 if (cinfo->src == NULL)
6558 /* First time for this JPEG object? */
6559 cinfo->src = (struct jpeg_source_mgr *)
6560 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6561 sizeof (struct jpeg_source_mgr));
6562 src = (struct jpeg_source_mgr *) cinfo->src;
6563 src->next_input_byte = data;
6566 src = (struct jpeg_source_mgr *) cinfo->src;
6567 src->init_source = our_common_init_source;
6568 src->fill_input_buffer = our_memory_fill_input_buffer;
6569 src->skip_input_data = our_memory_skip_input_data;
6570 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6571 src->term_source = our_common_term_source;
6572 src->bytes_in_buffer = len;
6573 src->next_input_byte = data;
6577 struct jpeg_stdio_mgr
6579 struct jpeg_source_mgr mgr;
6580 boolean finished;
6581 FILE *file;
6582 JOCTET *buffer;
6586 /* Size of buffer to read JPEG from file.
6587 Not too big, as we want to use alloc_small. */
6588 #define JPEG_STDIO_BUFFER_SIZE 8192
6591 /* Fill input buffer method for JPEG data source manager. Called
6592 whenever more data is needed. The data is read from a FILE *. */
6594 static boolean
6595 our_stdio_fill_input_buffer (cinfo)
6596 j_decompress_ptr cinfo;
6598 struct jpeg_stdio_mgr *src;
6600 src = (struct jpeg_stdio_mgr *) cinfo->src;
6601 if (!src->finished)
6603 size_t bytes;
6605 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6606 if (bytes > 0)
6607 src->mgr.bytes_in_buffer = bytes;
6608 else
6610 WARNMS (cinfo, JWRN_JPEG_EOF);
6611 src->finished = 1;
6612 src->buffer[0] = (JOCTET) 0xFF;
6613 src->buffer[1] = (JOCTET) JPEG_EOI;
6614 src->mgr.bytes_in_buffer = 2;
6616 src->mgr.next_input_byte = src->buffer;
6619 return 1;
6623 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6624 is the JPEG data source manager. */
6626 static void
6627 our_stdio_skip_input_data (cinfo, num_bytes)
6628 j_decompress_ptr cinfo;
6629 long num_bytes;
6631 struct jpeg_stdio_mgr *src;
6632 src = (struct jpeg_stdio_mgr *) cinfo->src;
6634 while (num_bytes > 0 && !src->finished)
6636 if (num_bytes <= src->mgr.bytes_in_buffer)
6638 src->mgr.bytes_in_buffer -= num_bytes;
6639 src->mgr.next_input_byte += num_bytes;
6640 break;
6642 else
6644 num_bytes -= src->mgr.bytes_in_buffer;
6645 src->mgr.bytes_in_buffer = 0;
6646 src->mgr.next_input_byte = NULL;
6648 our_stdio_fill_input_buffer (cinfo);
6654 /* Set up the JPEG lib for reading an image from a FILE *.
6655 CINFO is the decompression info structure created for
6656 reading the image. */
6658 static void
6659 jpeg_file_src (cinfo, fp)
6660 j_decompress_ptr cinfo;
6661 FILE *fp;
6663 struct jpeg_stdio_mgr *src;
6665 if (cinfo->src != NULL)
6666 src = (struct jpeg_stdio_mgr *) cinfo->src;
6667 else
6669 /* First time for this JPEG object? */
6670 cinfo->src = (struct jpeg_source_mgr *)
6671 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6672 sizeof (struct jpeg_stdio_mgr));
6673 src = (struct jpeg_stdio_mgr *) cinfo->src;
6674 src->buffer = (JOCTET *)
6675 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6676 JPEG_STDIO_BUFFER_SIZE);
6679 src->file = fp;
6680 src->finished = 0;
6681 src->mgr.init_source = our_common_init_source;
6682 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6683 src->mgr.skip_input_data = our_stdio_skip_input_data;
6684 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6685 src->mgr.term_source = our_common_term_source;
6686 src->mgr.bytes_in_buffer = 0;
6687 src->mgr.next_input_byte = NULL;
6691 /* Load image IMG for use on frame F. Patterned after example.c
6692 from the JPEG lib. */
6694 static int
6695 jpeg_load (f, img)
6696 struct frame *f;
6697 struct image *img;
6699 struct jpeg_decompress_struct cinfo;
6700 struct my_jpeg_error_mgr mgr;
6701 Lisp_Object file, specified_file;
6702 Lisp_Object specified_data;
6703 FILE * volatile fp = NULL;
6704 JSAMPARRAY buffer;
6705 int row_stride, x, y;
6706 XImagePtr ximg = NULL;
6707 int rc;
6708 unsigned long *colors;
6709 int width, height;
6710 struct gcpro gcpro1;
6712 /* Open the JPEG file. */
6713 specified_file = image_spec_value (img->spec, QCfile, NULL);
6714 specified_data = image_spec_value (img->spec, QCdata, NULL);
6715 file = Qnil;
6716 GCPRO1 (file);
6718 if (NILP (specified_data))
6720 file = x_find_image_file (specified_file);
6721 if (!STRINGP (file))
6723 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6724 UNGCPRO;
6725 return 0;
6728 fp = fopen (SDATA (file), "rb");
6729 if (fp == NULL)
6731 image_error ("Cannot open `%s'", file, Qnil);
6732 UNGCPRO;
6733 return 0;
6737 /* Customize libjpeg's error handling to call my_error_exit when an
6738 error is detected. This function will perform a longjmp.
6739 Casting return value avoids a GCC warning on W32. */
6740 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
6741 mgr.pub.error_exit = my_error_exit;
6743 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6745 if (rc == 1)
6747 /* Called from my_error_exit. Display a JPEG error. */
6748 char buffer[JMSG_LENGTH_MAX];
6749 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
6750 image_error ("Error reading JPEG image `%s': %s", img->spec,
6751 build_string (buffer));
6754 /* Close the input file and destroy the JPEG object. */
6755 if (fp)
6756 fclose ((FILE *) fp);
6757 fn_jpeg_destroy_decompress (&cinfo);
6759 /* If we already have an XImage, free that. */
6760 x_destroy_x_image (ximg);
6762 /* Free pixmap and colors. */
6763 x_clear_image (f, img);
6765 UNGCPRO;
6766 return 0;
6769 /* Create the JPEG decompression object. Let it read from fp.
6770 Read the JPEG image header. */
6771 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
6773 if (NILP (specified_data))
6774 jpeg_file_src (&cinfo, (FILE *) fp);
6775 else
6776 jpeg_memory_src (&cinfo, SDATA (specified_data),
6777 SBYTES (specified_data));
6779 fn_jpeg_read_header (&cinfo, 1);
6781 /* Customize decompression so that color quantization will be used.
6782 Start decompression. */
6783 cinfo.quantize_colors = 1;
6784 fn_jpeg_start_decompress (&cinfo);
6785 width = img->width = cinfo.output_width;
6786 height = img->height = cinfo.output_height;
6788 if (!check_image_size (f, width, height))
6790 image_error ("Invalid image size", Qnil, Qnil);
6791 longjmp (mgr.setjmp_buffer, 2);
6794 /* Create X image and pixmap. */
6795 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6796 longjmp (mgr.setjmp_buffer, 2);
6798 /* Allocate colors. When color quantization is used,
6799 cinfo.actual_number_of_colors has been set with the number of
6800 colors generated, and cinfo.colormap is a two-dimensional array
6801 of color indices in the range 0..cinfo.actual_number_of_colors.
6802 No more than 255 colors will be generated. */
6804 int i, ir, ig, ib;
6806 if (cinfo.out_color_components > 2)
6807 ir = 0, ig = 1, ib = 2;
6808 else if (cinfo.out_color_components > 1)
6809 ir = 0, ig = 1, ib = 0;
6810 else
6811 ir = 0, ig = 0, ib = 0;
6813 /* Use the color table mechanism because it handles colors that
6814 cannot be allocated nicely. Such colors will be replaced with
6815 a default color, and we don't have to care about which colors
6816 can be freed safely, and which can't. */
6817 init_color_table ();
6818 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6819 * sizeof *colors);
6821 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6823 /* Multiply RGB values with 255 because X expects RGB values
6824 in the range 0..0xffff. */
6825 int r = cinfo.colormap[ir][i] << 8;
6826 int g = cinfo.colormap[ig][i] << 8;
6827 int b = cinfo.colormap[ib][i] << 8;
6828 colors[i] = lookup_rgb_color (f, r, g, b);
6831 #ifdef COLOR_TABLE_SUPPORT
6832 /* Remember those colors actually allocated. */
6833 img->colors = colors_in_color_table (&img->ncolors);
6834 free_color_table ();
6835 #endif /* COLOR_TABLE_SUPPORT */
6838 /* Read pixels. */
6839 row_stride = width * cinfo.output_components;
6840 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6841 row_stride, 1);
6842 for (y = 0; y < height; ++y)
6844 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
6845 for (x = 0; x < cinfo.output_width; ++x)
6846 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6849 /* Clean up. */
6850 fn_jpeg_finish_decompress (&cinfo);
6851 fn_jpeg_destroy_decompress (&cinfo);
6852 if (fp)
6853 fclose ((FILE *) fp);
6855 /* Maybe fill in the background field while we have ximg handy. */
6856 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6857 /* Casting avoids a GCC warning. */
6858 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6860 /* Put the image into the pixmap. */
6861 x_put_x_image (f, ximg, img->pixmap, width, height);
6862 x_destroy_x_image (ximg);
6863 UNGCPRO;
6864 return 1;
6867 #else /* HAVE_JPEG */
6869 #ifdef HAVE_NS
6870 static int
6871 jpeg_load (struct frame *f, struct image *img)
6873 return ns_load_image(f, img,
6874 image_spec_value (img->spec, QCfile, NULL),
6875 image_spec_value (img->spec, QCdata, NULL));
6877 #endif /* HAVE_NS */
6879 #endif /* !HAVE_JPEG */
6883 /***********************************************************************
6884 TIFF
6885 ***********************************************************************/
6887 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6889 static int tiff_image_p P_ ((Lisp_Object object));
6890 static int tiff_load P_ ((struct frame *f, struct image *img));
6892 /* The symbol `tiff' identifying images of this type. */
6894 Lisp_Object Qtiff;
6896 /* Indices of image specification fields in tiff_format, below. */
6898 enum tiff_keyword_index
6900 TIFF_TYPE,
6901 TIFF_DATA,
6902 TIFF_FILE,
6903 TIFF_ASCENT,
6904 TIFF_MARGIN,
6905 TIFF_RELIEF,
6906 TIFF_ALGORITHM,
6907 TIFF_HEURISTIC_MASK,
6908 TIFF_MASK,
6909 TIFF_BACKGROUND,
6910 TIFF_INDEX,
6911 TIFF_LAST
6914 /* Vector of image_keyword structures describing the format
6915 of valid user-defined image specifications. */
6917 static struct image_keyword tiff_format[TIFF_LAST] =
6919 {":type", IMAGE_SYMBOL_VALUE, 1},
6920 {":data", IMAGE_STRING_VALUE, 0},
6921 {":file", IMAGE_STRING_VALUE, 0},
6922 {":ascent", IMAGE_ASCENT_VALUE, 0},
6923 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6924 {":relief", IMAGE_INTEGER_VALUE, 0},
6925 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6926 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6927 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6928 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6929 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
6932 /* Structure describing the image type `tiff'. */
6934 static struct image_type tiff_type =
6936 &Qtiff,
6937 tiff_image_p,
6938 tiff_load,
6939 x_clear_image,
6940 NULL
6943 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6945 static int
6946 tiff_image_p (object)
6947 Lisp_Object object;
6949 struct image_keyword fmt[TIFF_LAST];
6950 bcopy (tiff_format, fmt, sizeof fmt);
6952 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6953 return 0;
6955 /* Must specify either the :data or :file keyword. */
6956 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6959 #endif /* HAVE_TIFF || HAVE_NS */
6961 #ifdef HAVE_TIFF
6963 #include <tiffio.h>
6965 #ifdef HAVE_NTGUI
6967 /* TIFF library details. */
6968 DEF_IMGLIB_FN (TIFFSetErrorHandler);
6969 DEF_IMGLIB_FN (TIFFSetWarningHandler);
6970 DEF_IMGLIB_FN (TIFFOpen);
6971 DEF_IMGLIB_FN (TIFFClientOpen);
6972 DEF_IMGLIB_FN (TIFFGetField);
6973 DEF_IMGLIB_FN (TIFFReadRGBAImage);
6974 DEF_IMGLIB_FN (TIFFClose);
6975 DEF_IMGLIB_FN (TIFFSetDirectory);
6977 static int
6978 init_tiff_functions (Lisp_Object libraries)
6980 HMODULE library;
6982 if (!(library = w32_delayed_load (libraries, Qtiff)))
6983 return 0;
6985 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
6986 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
6987 LOAD_IMGLIB_FN (library, TIFFOpen);
6988 LOAD_IMGLIB_FN (library, TIFFClientOpen);
6989 LOAD_IMGLIB_FN (library, TIFFGetField);
6990 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
6991 LOAD_IMGLIB_FN (library, TIFFClose);
6992 LOAD_IMGLIB_FN (library, TIFFSetDirectory);
6993 return 1;
6996 #else
6998 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6999 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7000 #define fn_TIFFOpen TIFFOpen
7001 #define fn_TIFFClientOpen TIFFClientOpen
7002 #define fn_TIFFGetField TIFFGetField
7003 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7004 #define fn_TIFFClose TIFFClose
7005 #define fn_TIFFSetDirectory TIFFSetDirectory
7006 #endif /* HAVE_NTGUI */
7009 /* Reading from a memory buffer for TIFF images Based on the PNG
7010 memory source, but we have to provide a lot of extra functions.
7011 Blah.
7013 We really only need to implement read and seek, but I am not
7014 convinced that the TIFF library is smart enough not to destroy
7015 itself if we only hand it the function pointers we need to
7016 override. */
7018 typedef struct
7020 unsigned char *bytes;
7021 size_t len;
7022 int index;
7024 tiff_memory_source;
7026 static size_t
7027 tiff_read_from_memory (data, buf, size)
7028 thandle_t data;
7029 tdata_t buf;
7030 tsize_t size;
7032 tiff_memory_source *src = (tiff_memory_source *) data;
7034 if (size > src->len - src->index)
7035 return (size_t) -1;
7036 bcopy (src->bytes + src->index, buf, size);
7037 src->index += size;
7038 return size;
7041 static size_t
7042 tiff_write_from_memory (data, buf, size)
7043 thandle_t data;
7044 tdata_t buf;
7045 tsize_t size;
7047 return (size_t) -1;
7050 static toff_t
7051 tiff_seek_in_memory (data, off, whence)
7052 thandle_t data;
7053 toff_t off;
7054 int whence;
7056 tiff_memory_source *src = (tiff_memory_source *) data;
7057 int idx;
7059 switch (whence)
7061 case SEEK_SET: /* Go from beginning of source. */
7062 idx = off;
7063 break;
7065 case SEEK_END: /* Go from end of source. */
7066 idx = src->len + off;
7067 break;
7069 case SEEK_CUR: /* Go from current position. */
7070 idx = src->index + off;
7071 break;
7073 default: /* Invalid `whence'. */
7074 return -1;
7077 if (idx > src->len || idx < 0)
7078 return -1;
7080 src->index = idx;
7081 return src->index;
7084 static int
7085 tiff_close_memory (data)
7086 thandle_t data;
7088 /* NOOP */
7089 return 0;
7092 static int
7093 tiff_mmap_memory (data, pbase, psize)
7094 thandle_t data;
7095 tdata_t *pbase;
7096 toff_t *psize;
7098 /* It is already _IN_ memory. */
7099 return 0;
7102 static void
7103 tiff_unmap_memory (data, base, size)
7104 thandle_t data;
7105 tdata_t base;
7106 toff_t size;
7108 /* We don't need to do this. */
7111 static toff_t
7112 tiff_size_of_memory (data)
7113 thandle_t data;
7115 return ((tiff_memory_source *) data)->len;
7119 static void
7120 tiff_error_handler (title, format, ap)
7121 const char *title, *format;
7122 va_list ap;
7124 char buf[512];
7125 int len;
7127 len = sprintf (buf, "TIFF error: %s ", title);
7128 vsprintf (buf + len, format, ap);
7129 add_to_log (buf, Qnil, Qnil);
7133 static void
7134 tiff_warning_handler (title, format, ap)
7135 const char *title, *format;
7136 va_list ap;
7138 char buf[512];
7139 int len;
7141 len = sprintf (buf, "TIFF warning: %s ", title);
7142 vsprintf (buf + len, format, ap);
7143 add_to_log (buf, Qnil, Qnil);
7147 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7148 successful. */
7150 static int
7151 tiff_load (f, img)
7152 struct frame *f;
7153 struct image *img;
7155 Lisp_Object file, specified_file;
7156 Lisp_Object specified_data;
7157 TIFF *tiff;
7158 int width, height, x, y, count;
7159 uint32 *buf;
7160 int rc, rc2;
7161 XImagePtr ximg;
7162 struct gcpro gcpro1;
7163 tiff_memory_source memsrc;
7164 Lisp_Object image;
7166 specified_file = image_spec_value (img->spec, QCfile, NULL);
7167 specified_data = image_spec_value (img->spec, QCdata, NULL);
7168 file = Qnil;
7169 GCPRO1 (file);
7171 fn_TIFFSetErrorHandler (tiff_error_handler);
7172 fn_TIFFSetWarningHandler (tiff_warning_handler);
7174 if (NILP (specified_data))
7176 /* Read from a file */
7177 file = x_find_image_file (specified_file);
7178 if (!STRINGP (file))
7180 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7181 UNGCPRO;
7182 return 0;
7185 /* Try to open the image file. Casting return value avoids a
7186 GCC warning on W32. */
7187 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7188 if (tiff == NULL)
7190 image_error ("Cannot open `%s'", file, Qnil);
7191 UNGCPRO;
7192 return 0;
7195 else
7197 /* Memory source! */
7198 memsrc.bytes = SDATA (specified_data);
7199 memsrc.len = SBYTES (specified_data);
7200 memsrc.index = 0;
7202 /* Casting return value avoids a GCC warning on W32. */
7203 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7204 (TIFFReadWriteProc) tiff_read_from_memory,
7205 (TIFFReadWriteProc) tiff_write_from_memory,
7206 tiff_seek_in_memory,
7207 tiff_close_memory,
7208 tiff_size_of_memory,
7209 tiff_mmap_memory,
7210 tiff_unmap_memory);
7212 if (!tiff)
7214 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7215 UNGCPRO;
7216 return 0;
7220 image = image_spec_value (img->spec, QCindex, NULL);
7221 if (INTEGERP (image))
7223 int ino = XFASTINT (image);
7224 if (!fn_TIFFSetDirectory (tiff, ino))
7226 image_error ("Invalid image number `%s' in image `%s'",
7227 image, img->spec);
7228 fn_TIFFClose (tiff);
7229 UNGCPRO;
7230 return 0;
7234 /* Get width and height of the image, and allocate a raster buffer
7235 of width x height 32-bit values. */
7236 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7237 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7239 if (!check_image_size (f, width, height))
7241 image_error ("Invalid image size", Qnil, Qnil);
7242 fn_TIFFClose (tiff);
7243 UNGCPRO;
7244 return 0;
7247 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7249 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7251 /* Count the number of images in the file. */
7252 for (count = 1, rc2 = 1; rc2; count++)
7253 rc2 = fn_TIFFSetDirectory (tiff, count);
7255 if (count > 1)
7256 img->data.lisp_val = Fcons (Qcount,
7257 Fcons (make_number (count),
7258 img->data.lisp_val));
7260 fn_TIFFClose (tiff);
7261 if (!rc)
7263 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7264 xfree (buf);
7265 UNGCPRO;
7266 return 0;
7269 /* Create the X image and pixmap. */
7270 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7272 xfree (buf);
7273 UNGCPRO;
7274 return 0;
7277 /* Initialize the color table. */
7278 init_color_table ();
7280 /* Process the pixel raster. Origin is in the lower-left corner. */
7281 for (y = 0; y < height; ++y)
7283 uint32 *row = buf + y * width;
7285 for (x = 0; x < width; ++x)
7287 uint32 abgr = row[x];
7288 int r = TIFFGetR (abgr) << 8;
7289 int g = TIFFGetG (abgr) << 8;
7290 int b = TIFFGetB (abgr) << 8;
7291 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7295 #ifdef COLOR_TABLE_SUPPORT
7296 /* Remember the colors allocated for the image. Free the color table. */
7297 img->colors = colors_in_color_table (&img->ncolors);
7298 free_color_table ();
7299 #endif /* COLOR_TABLE_SUPPORT */
7301 img->width = width;
7302 img->height = height;
7304 /* Maybe fill in the background field while we have ximg handy. */
7305 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7306 /* Casting avoids a GCC warning on W32. */
7307 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7309 /* Put the image into the pixmap, then free the X image and its buffer. */
7310 x_put_x_image (f, ximg, img->pixmap, width, height);
7311 x_destroy_x_image (ximg);
7312 xfree (buf);
7314 UNGCPRO;
7315 return 1;
7318 #else /* HAVE_TIFF */
7320 #ifdef HAVE_NS
7321 static int
7322 tiff_load (struct frame *f, struct image *img)
7324 return ns_load_image(f, img,
7325 image_spec_value (img->spec, QCfile, NULL),
7326 image_spec_value (img->spec, QCdata, NULL));
7328 #endif /* HAVE_NS */
7330 #endif /* !HAVE_TIFF */
7334 /***********************************************************************
7336 ***********************************************************************/
7338 #if defined (HAVE_GIF) || defined (HAVE_NS)
7340 static int gif_image_p P_ ((Lisp_Object object));
7341 static int gif_load P_ ((struct frame *f, struct image *img));
7342 static void gif_clear_image P_ ((struct frame *f, struct image *img));
7344 /* The symbol `gif' identifying images of this type. */
7346 Lisp_Object Qgif;
7348 /* Indices of image specification fields in gif_format, below. */
7350 enum gif_keyword_index
7352 GIF_TYPE,
7353 GIF_DATA,
7354 GIF_FILE,
7355 GIF_ASCENT,
7356 GIF_MARGIN,
7357 GIF_RELIEF,
7358 GIF_ALGORITHM,
7359 GIF_HEURISTIC_MASK,
7360 GIF_MASK,
7361 GIF_IMAGE,
7362 GIF_BACKGROUND,
7363 GIF_LAST
7366 /* Vector of image_keyword structures describing the format
7367 of valid user-defined image specifications. */
7369 static struct image_keyword gif_format[GIF_LAST] =
7371 {":type", IMAGE_SYMBOL_VALUE, 1},
7372 {":data", IMAGE_STRING_VALUE, 0},
7373 {":file", IMAGE_STRING_VALUE, 0},
7374 {":ascent", IMAGE_ASCENT_VALUE, 0},
7375 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7376 {":relief", IMAGE_INTEGER_VALUE, 0},
7377 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7378 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7379 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7380 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7381 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7384 /* Structure describing the image type `gif'. */
7386 static struct image_type gif_type =
7388 &Qgif,
7389 gif_image_p,
7390 gif_load,
7391 gif_clear_image,
7392 NULL
7395 /* Free X resources of GIF image IMG which is used on frame F. */
7397 static void
7398 gif_clear_image (f, img)
7399 struct frame *f;
7400 struct image *img;
7402 /* IMG->data.ptr_val may contain extension data. */
7403 img->data.lisp_val = Qnil;
7404 x_clear_image (f, img);
7407 /* Return non-zero if OBJECT is a valid GIF image specification. */
7409 static int
7410 gif_image_p (object)
7411 Lisp_Object object;
7413 struct image_keyword fmt[GIF_LAST];
7414 bcopy (gif_format, fmt, sizeof fmt);
7416 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7417 return 0;
7419 /* Must specify either the :data or :file keyword. */
7420 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7423 #endif /* HAVE_GIF */
7425 #ifdef HAVE_GIF
7427 #if defined (HAVE_NTGUI)
7428 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7429 Undefine before redefining to avoid a preprocessor warning. */
7430 #ifdef DrawText
7431 #undef DrawText
7432 #endif
7433 /* avoid conflict with QuickdrawText.h */
7434 #define DrawText gif_DrawText
7435 #include <gif_lib.h>
7436 #undef DrawText
7438 #else /* HAVE_NTGUI */
7440 #include <gif_lib.h>
7442 #endif /* HAVE_NTGUI */
7445 #ifdef HAVE_NTGUI
7447 /* GIF library details. */
7448 DEF_IMGLIB_FN (DGifCloseFile);
7449 DEF_IMGLIB_FN (DGifSlurp);
7450 DEF_IMGLIB_FN (DGifOpen);
7451 DEF_IMGLIB_FN (DGifOpenFileName);
7453 static int
7454 init_gif_functions (Lisp_Object libraries)
7456 HMODULE library;
7458 if (!(library = w32_delayed_load (libraries, Qgif)))
7459 return 0;
7461 LOAD_IMGLIB_FN (library, DGifCloseFile);
7462 LOAD_IMGLIB_FN (library, DGifSlurp);
7463 LOAD_IMGLIB_FN (library, DGifOpen);
7464 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7465 return 1;
7468 #else
7470 #define fn_DGifCloseFile DGifCloseFile
7471 #define fn_DGifSlurp DGifSlurp
7472 #define fn_DGifOpen DGifOpen
7473 #define fn_DGifOpenFileName DGifOpenFileName
7475 #endif /* HAVE_NTGUI */
7477 /* Reading a GIF image from memory
7478 Based on the PNG memory stuff to a certain extent. */
7480 typedef struct
7482 unsigned char *bytes;
7483 size_t len;
7484 int index;
7486 gif_memory_source;
7488 /* Make the current memory source available to gif_read_from_memory.
7489 It's done this way because not all versions of libungif support
7490 a UserData field in the GifFileType structure. */
7491 static gif_memory_source *current_gif_memory_src;
7493 static int
7494 gif_read_from_memory (file, buf, len)
7495 GifFileType *file;
7496 GifByteType *buf;
7497 int len;
7499 gif_memory_source *src = current_gif_memory_src;
7501 if (len > src->len - src->index)
7502 return -1;
7504 bcopy (src->bytes + src->index, buf, len);
7505 src->index += len;
7506 return len;
7510 /* Load GIF image IMG for use on frame F. Value is non-zero if
7511 successful. */
7513 static int interlace_start[] = {0, 4, 2, 1};
7514 static int interlace_increment[] = {8, 8, 4, 2};
7516 static int
7517 gif_load (f, img)
7518 struct frame *f;
7519 struct image *img;
7521 Lisp_Object file, specified_file;
7522 Lisp_Object specified_data;
7523 int rc, width, height, x, y, i;
7524 XImagePtr ximg;
7525 ColorMapObject *gif_color_map;
7526 unsigned long pixel_colors[256];
7527 GifFileType *gif;
7528 struct gcpro gcpro1;
7529 Lisp_Object image;
7530 int ino, image_height, image_width;
7531 gif_memory_source memsrc;
7532 unsigned char *raster;
7534 specified_file = image_spec_value (img->spec, QCfile, NULL);
7535 specified_data = image_spec_value (img->spec, QCdata, NULL);
7536 file = Qnil;
7537 GCPRO1 (file);
7539 if (NILP (specified_data))
7541 file = x_find_image_file (specified_file);
7542 if (!STRINGP (file))
7544 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7545 UNGCPRO;
7546 return 0;
7549 /* Open the GIF file. Casting return value avoids a GCC warning
7550 on W32. */
7551 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
7552 if (gif == NULL)
7554 image_error ("Cannot open `%s'", file, Qnil);
7555 UNGCPRO;
7556 return 0;
7559 else
7561 /* Read from memory! */
7562 current_gif_memory_src = &memsrc;
7563 memsrc.bytes = SDATA (specified_data);
7564 memsrc.len = SBYTES (specified_data);
7565 memsrc.index = 0;
7567 /* Casting return value avoids a GCC warning on W32. */
7568 gif = (GifFileType *) fn_DGifOpen (&memsrc, gif_read_from_memory);
7569 if (!gif)
7571 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7572 UNGCPRO;
7573 return 0;
7577 /* Before reading entire contents, check the declared image size. */
7578 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7580 image_error ("Invalid image size", Qnil, Qnil);
7581 fn_DGifCloseFile (gif);
7582 UNGCPRO;
7583 return 0;
7586 /* Read entire contents. */
7587 rc = fn_DGifSlurp (gif);
7588 if (rc == GIF_ERROR)
7590 image_error ("Error reading `%s'", img->spec, Qnil);
7591 fn_DGifCloseFile (gif);
7592 UNGCPRO;
7593 return 0;
7596 image = image_spec_value (img->spec, QCindex, NULL);
7597 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7598 if (ino >= gif->ImageCount)
7600 image_error ("Invalid image number `%s' in image `%s'",
7601 image, img->spec);
7602 fn_DGifCloseFile (gif);
7603 UNGCPRO;
7604 return 0;
7607 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
7608 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
7609 image_height = gif->SavedImages[ino].ImageDesc.Height;
7610 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
7611 image_width = gif->SavedImages[ino].ImageDesc.Width;
7612 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
7614 width = img->width = max (gif->SWidth,
7615 max (gif->Image.Left + gif->Image.Width,
7616 img->corners[RIGHT_CORNER]));
7617 height = img->height = max (gif->SHeight,
7618 max (gif->Image.Top + gif->Image.Height,
7619 img->corners[BOT_CORNER]));
7621 if (!check_image_size (f, width, height))
7623 image_error ("Invalid image size", Qnil, Qnil);
7624 fn_DGifCloseFile (gif);
7625 UNGCPRO;
7626 return 0;
7629 /* Create the X image and pixmap. */
7630 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7632 fn_DGifCloseFile (gif);
7633 UNGCPRO;
7634 return 0;
7637 /* Allocate colors. */
7638 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7639 if (!gif_color_map)
7640 gif_color_map = gif->SColorMap;
7641 init_color_table ();
7642 bzero (pixel_colors, sizeof pixel_colors);
7644 if (gif_color_map)
7645 for (i = 0; i < gif_color_map->ColorCount; ++i)
7647 int r = gif_color_map->Colors[i].Red << 8;
7648 int g = gif_color_map->Colors[i].Green << 8;
7649 int b = gif_color_map->Colors[i].Blue << 8;
7650 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7653 #ifdef COLOR_TABLE_SUPPORT
7654 img->colors = colors_in_color_table (&img->ncolors);
7655 free_color_table ();
7656 #endif /* COLOR_TABLE_SUPPORT */
7658 /* Clear the part of the screen image that are not covered by
7659 the image from the GIF file. Full animated GIF support
7660 requires more than can be done here (see the gif89 spec,
7661 disposal methods). Let's simply assume that the part
7662 not covered by a sub-image is in the frame's background color. */
7663 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
7664 for (x = 0; x < width; ++x)
7665 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7667 for (y = img->corners[BOT_CORNER]; y < height; ++y)
7668 for (x = 0; x < width; ++x)
7669 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7671 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
7673 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
7674 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7675 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
7676 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7679 /* Read the GIF image into the X image. We use a local variable
7680 `raster' here because RasterBits below is a char *, and invites
7681 problems with bytes >= 0x80. */
7682 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
7684 if (gif->SavedImages[ino].ImageDesc.Interlace)
7686 int pass;
7687 int row = interlace_start[0];
7689 pass = 0;
7691 for (y = 0; y < image_height; y++)
7693 if (row >= image_height)
7695 row = interlace_start[++pass];
7696 while (row >= image_height)
7697 row = interlace_start[++pass];
7700 for (x = 0; x < image_width; x++)
7702 int i = raster[(y * image_width) + x];
7703 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7704 row + img->corners[TOP_CORNER], pixel_colors[i]);
7707 row += interlace_increment[pass];
7710 else
7712 for (y = 0; y < image_height; ++y)
7713 for (x = 0; x < image_width; ++x)
7715 int i = raster[y * image_width + x];
7716 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7717 y + img->corners[TOP_CORNER], pixel_colors[i]);
7721 /* Save GIF image extension data for `image-extension-data'.
7722 Format is (count IMAGES FUNCTION "BYTES" ...). */
7723 img->data.lisp_val = Qnil;
7724 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
7726 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
7727 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
7728 /* Append (... FUNCTION "BYTES") */
7729 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
7730 Fcons (make_number (ext->Function),
7731 img->data.lisp_val));
7732 img->data.lisp_val = Fnreverse (img->data.lisp_val);
7734 if (gif->ImageCount > 1)
7735 img->data.lisp_val = Fcons (Qcount,
7736 Fcons (make_number (gif->ImageCount),
7737 img->data.lisp_val));
7739 fn_DGifCloseFile (gif);
7741 /* Maybe fill in the background field while we have ximg handy. */
7742 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7743 /* Casting avoids a GCC warning. */
7744 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7746 /* Put the image into the pixmap, then free the X image and its buffer. */
7747 x_put_x_image (f, ximg, img->pixmap, width, height);
7748 x_destroy_x_image (ximg);
7750 UNGCPRO;
7751 return 1;
7754 #else /* !HAVE_GIF */
7756 #ifdef HAVE_NS
7757 static int
7758 gif_load (struct frame *f, struct image *img)
7760 return ns_load_image(f, img,
7761 image_spec_value (img->spec, QCfile, NULL),
7762 image_spec_value (img->spec, QCdata, NULL));
7764 #endif /* HAVE_NS */
7766 #endif /* HAVE_GIF */
7770 /***********************************************************************
7772 ***********************************************************************/
7774 #if defined (HAVE_RSVG)
7776 /* Function prototypes. */
7778 static int svg_image_p P_ ((Lisp_Object object));
7779 static int svg_load P_ ((struct frame *f, struct image *img));
7781 static int svg_load_image P_ ((struct frame *, struct image *,
7782 unsigned char *, unsigned int));
7784 /* The symbol `svg' identifying images of this type. */
7786 Lisp_Object Qsvg;
7788 /* Indices of image specification fields in svg_format, below. */
7790 enum svg_keyword_index
7792 SVG_TYPE,
7793 SVG_DATA,
7794 SVG_FILE,
7795 SVG_ASCENT,
7796 SVG_MARGIN,
7797 SVG_RELIEF,
7798 SVG_ALGORITHM,
7799 SVG_HEURISTIC_MASK,
7800 SVG_MASK,
7801 SVG_BACKGROUND,
7802 SVG_LAST
7805 /* Vector of image_keyword structures describing the format
7806 of valid user-defined image specifications. */
7808 static struct image_keyword svg_format[SVG_LAST] =
7810 {":type", IMAGE_SYMBOL_VALUE, 1},
7811 {":data", IMAGE_STRING_VALUE, 0},
7812 {":file", IMAGE_STRING_VALUE, 0},
7813 {":ascent", IMAGE_ASCENT_VALUE, 0},
7814 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7815 {":relief", IMAGE_INTEGER_VALUE, 0},
7816 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7817 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7818 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7819 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7822 /* Structure describing the image type `svg'. Its the same type of
7823 structure defined for all image formats, handled by emacs image
7824 functions. See struct image_type in dispextern.h. */
7826 static struct image_type svg_type =
7828 /* An identifier showing that this is an image structure for the SVG format. */
7829 &Qsvg,
7830 /* Handle to a function that can be used to identify a SVG file. */
7831 svg_image_p,
7832 /* Handle to function used to load a SVG file. */
7833 svg_load,
7834 /* Handle to function to free sresources for SVG. */
7835 x_clear_image,
7836 /* An internal field to link to the next image type in a list of
7837 image types, will be filled in when registering the format. */
7838 NULL
7842 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7843 this by calling parse_image_spec and supplying the keywords that
7844 identify the SVG format. */
7846 static int
7847 svg_image_p (object)
7848 Lisp_Object object;
7850 struct image_keyword fmt[SVG_LAST];
7851 bcopy (svg_format, fmt, sizeof fmt);
7853 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
7854 return 0;
7856 /* Must specify either the :data or :file keyword. */
7857 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
7860 #include <librsvg/rsvg.h>
7862 #ifdef HAVE_NTGUI
7864 /* SVG library functions. */
7865 DEF_IMGLIB_FN (rsvg_handle_new);
7866 DEF_IMGLIB_FN (rsvg_handle_get_dimensions);
7867 DEF_IMGLIB_FN (rsvg_handle_write);
7868 DEF_IMGLIB_FN (rsvg_handle_close);
7869 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf);
7870 DEF_IMGLIB_FN (rsvg_handle_free);
7872 DEF_IMGLIB_FN (gdk_pixbuf_get_width);
7873 DEF_IMGLIB_FN (gdk_pixbuf_get_height);
7874 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels);
7875 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride);
7876 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace);
7877 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels);
7878 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha);
7879 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample);
7881 DEF_IMGLIB_FN (g_type_init);
7882 DEF_IMGLIB_FN (g_object_unref);
7883 DEF_IMGLIB_FN (g_error_free);
7885 Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
7887 static int
7888 init_svg_functions (Lisp_Object libraries)
7890 HMODULE library, gdklib, glib, gobject;
7892 if (!(glib = w32_delayed_load (libraries, Qglib))
7893 || !(gobject = w32_delayed_load (libraries, Qgobject))
7894 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
7895 || !(library = w32_delayed_load (libraries, Qsvg)))
7896 return 0;
7898 LOAD_IMGLIB_FN (library, rsvg_handle_new);
7899 LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions);
7900 LOAD_IMGLIB_FN (library, rsvg_handle_write);
7901 LOAD_IMGLIB_FN (library, rsvg_handle_close);
7902 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
7903 LOAD_IMGLIB_FN (library, rsvg_handle_free);
7905 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
7906 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
7907 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
7908 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
7909 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
7910 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
7911 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
7912 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
7914 LOAD_IMGLIB_FN (gobject, g_type_init);
7915 LOAD_IMGLIB_FN (gobject, g_object_unref);
7916 LOAD_IMGLIB_FN (glib, g_error_free);
7918 return 1;
7921 #else
7922 /* The following aliases for library functions allow dynamic loading
7923 to be used on some platforms. */
7924 #define fn_rsvg_handle_new rsvg_handle_new
7925 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7926 #define fn_rsvg_handle_write rsvg_handle_write
7927 #define fn_rsvg_handle_close rsvg_handle_close
7928 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7929 #define fn_rsvg_handle_free rsvg_handle_free
7931 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7932 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7933 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7934 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7935 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7936 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7937 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7938 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7940 #define fn_g_type_init g_type_init
7941 #define fn_g_object_unref g_object_unref
7942 #define fn_g_error_free g_error_free
7943 #endif /* !HAVE_NTGUI */
7945 /* Load SVG image IMG for use on frame F. Value is non-zero if
7946 successful. this function will go into the svg_type structure, and
7947 the prototype thus needs to be compatible with that structure. */
7949 static int
7950 svg_load (f, img)
7951 struct frame *f;
7952 struct image *img;
7954 int success_p = 0;
7955 Lisp_Object file_name;
7957 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7958 file_name = image_spec_value (img->spec, QCfile, NULL);
7959 if (STRINGP (file_name))
7961 Lisp_Object file;
7962 unsigned char *contents;
7963 int size;
7964 struct gcpro gcpro1;
7966 file = x_find_image_file (file_name);
7967 GCPRO1 (file);
7968 if (!STRINGP (file))
7970 image_error ("Cannot find image file `%s'", file_name, Qnil);
7971 UNGCPRO;
7972 return 0;
7975 /* Read the entire file into memory. */
7976 contents = slurp_file (SDATA (file), &size);
7977 if (contents == NULL)
7979 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
7980 UNGCPRO;
7981 return 0;
7983 /* If the file was slurped into memory properly, parse it. */
7984 success_p = svg_load_image (f, img, contents, size);
7985 xfree (contents);
7986 UNGCPRO;
7988 /* Else its not a file, its a lisp object. Load the image from a
7989 lisp object rather than a file. */
7990 else
7992 Lisp_Object data;
7994 data = image_spec_value (img->spec, QCdata, NULL);
7995 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
7998 return success_p;
8001 /* svg_load_image is a helper function for svg_load, which does the
8002 actual loading given contents and size, apart from frame and image
8003 structures, passed from svg_load.
8005 Uses librsvg to do most of the image processing.
8007 Returns non-zero when successful. */
8008 static int
8009 svg_load_image (f, img, contents, size)
8010 /* Pointer to emacs frame structure. */
8011 struct frame *f;
8012 /* Pointer to emacs image structure. */
8013 struct image *img;
8014 /* String containing the SVG XML data to be parsed. */
8015 unsigned char *contents;
8016 /* Size of data in bytes. */
8017 unsigned int size;
8019 RsvgHandle *rsvg_handle;
8020 RsvgDimensionData dimension_data;
8021 GError *error = NULL;
8022 GdkPixbuf *pixbuf;
8023 int width;
8024 int height;
8025 const guint8 *pixels;
8026 int rowstride;
8027 XImagePtr ximg;
8028 Lisp_Object specified_bg;
8029 XColor background;
8030 int x;
8031 int y;
8033 /* g_type_init is a glib function that must be called prior to using
8034 gnome type library functions. */
8035 fn_g_type_init ();
8036 /* Make a handle to a new rsvg object. */
8037 rsvg_handle = (RsvgHandle *) fn_rsvg_handle_new ();
8039 /* Parse the contents argument and fill in the rsvg_handle. */
8040 fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
8041 if (error) goto rsvg_error;
8043 /* The parsing is complete, rsvg_handle is ready to used, close it
8044 for further writes. */
8045 fn_rsvg_handle_close (rsvg_handle, &error);
8046 if (error) goto rsvg_error;
8048 fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
8049 if (! check_image_size (f, dimension_data.width, dimension_data.height))
8050 goto rsvg_error;
8052 /* We can now get a valid pixel buffer from the svg file, if all
8053 went ok. */
8054 pixbuf = (GdkPixbuf *) fn_rsvg_handle_get_pixbuf (rsvg_handle);
8055 if (!pixbuf) goto rsvg_error;
8056 fn_g_object_unref (rsvg_handle);
8058 /* Extract some meta data from the svg handle. */
8059 width = fn_gdk_pixbuf_get_width (pixbuf);
8060 height = fn_gdk_pixbuf_get_height (pixbuf);
8061 pixels = (const guint8 *) fn_gdk_pixbuf_get_pixels (pixbuf);
8062 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
8064 /* Validate the svg meta data. */
8065 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
8066 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
8067 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
8068 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8070 /* Try to create a x pixmap to hold the svg pixmap. */
8071 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8073 fn_g_object_unref (pixbuf);
8074 return 0;
8077 init_color_table ();
8079 /* Handle alpha channel by combining the image with a background
8080 color. */
8081 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8082 if (!STRINGP (specified_bg)
8083 || !x_defined_color (f, SDATA (specified_bg), &background, 0))
8085 #ifndef HAVE_NS
8086 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8087 x_query_color (f, &background);
8088 #else
8089 ns_query_color(FRAME_BACKGROUND_COLOR (f), &background, 1);
8090 #endif
8093 /* SVG pixmaps specify transparency in the last byte, so right
8094 shift 8 bits to get rid of it, since emacs doesn't support
8095 transparency. */
8096 background.red >>= 8;
8097 background.green >>= 8;
8098 background.blue >>= 8;
8100 /* This loop handles opacity values, since Emacs assumes
8101 non-transparent images. Each pixel must be "flattened" by
8102 calculating the resulting color, given the transparency of the
8103 pixel, and the image background color. */
8104 for (y = 0; y < height; ++y)
8106 for (x = 0; x < width; ++x)
8108 unsigned red;
8109 unsigned green;
8110 unsigned blue;
8111 unsigned opacity;
8113 red = *pixels++;
8114 green = *pixels++;
8115 blue = *pixels++;
8116 opacity = *pixels++;
8118 red = ((red * opacity)
8119 + (background.red * ((1 << 8) - opacity)));
8120 green = ((green * opacity)
8121 + (background.green * ((1 << 8) - opacity)));
8122 blue = ((blue * opacity)
8123 + (background.blue * ((1 << 8) - opacity)));
8125 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
8128 pixels += rowstride - 4 * width;
8131 #ifdef COLOR_TABLE_SUPPORT
8132 /* Remember colors allocated for this image. */
8133 img->colors = colors_in_color_table (&img->ncolors);
8134 free_color_table ();
8135 #endif /* COLOR_TABLE_SUPPORT */
8137 fn_g_object_unref (pixbuf);
8139 img->width = width;
8140 img->height = height;
8142 /* Maybe fill in the background field while we have ximg handy.
8143 Casting avoids a GCC warning. */
8144 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8146 /* Put the image into the pixmap, then free the X image and its
8147 buffer. */
8148 x_put_x_image (f, ximg, img->pixmap, width, height);
8149 x_destroy_x_image (ximg);
8151 return 1;
8153 rsvg_error:
8154 fn_g_object_unref (rsvg_handle);
8155 /* FIXME: Use error->message so the user knows what is the actual
8156 problem with the image. */
8157 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
8158 fn_g_error_free (error);
8159 return 0;
8162 #endif /* defined (HAVE_RSVG) */
8167 /***********************************************************************
8168 Ghostscript
8169 ***********************************************************************/
8171 #ifdef HAVE_X_WINDOWS
8172 #define HAVE_GHOSTSCRIPT 1
8173 #endif /* HAVE_X_WINDOWS */
8175 /* The symbol `postscript' identifying images of this type. */
8177 Lisp_Object Qpostscript;
8179 #ifdef HAVE_GHOSTSCRIPT
8181 static int gs_image_p P_ ((Lisp_Object object));
8182 static int gs_load P_ ((struct frame *f, struct image *img));
8183 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8185 /* Keyword symbols. */
8187 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8189 /* Indices of image specification fields in gs_format, below. */
8191 enum gs_keyword_index
8193 GS_TYPE,
8194 GS_PT_WIDTH,
8195 GS_PT_HEIGHT,
8196 GS_FILE,
8197 GS_LOADER,
8198 GS_BOUNDING_BOX,
8199 GS_ASCENT,
8200 GS_MARGIN,
8201 GS_RELIEF,
8202 GS_ALGORITHM,
8203 GS_HEURISTIC_MASK,
8204 GS_MASK,
8205 GS_BACKGROUND,
8206 GS_LAST
8209 /* Vector of image_keyword structures describing the format
8210 of valid user-defined image specifications. */
8212 static struct image_keyword gs_format[GS_LAST] =
8214 {":type", IMAGE_SYMBOL_VALUE, 1},
8215 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8216 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8217 {":file", IMAGE_STRING_VALUE, 1},
8218 {":loader", IMAGE_FUNCTION_VALUE, 0},
8219 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8220 {":ascent", IMAGE_ASCENT_VALUE, 0},
8221 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8222 {":relief", IMAGE_INTEGER_VALUE, 0},
8223 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8224 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8225 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8226 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8229 /* Structure describing the image type `ghostscript'. */
8231 static struct image_type gs_type =
8233 &Qpostscript,
8234 gs_image_p,
8235 gs_load,
8236 gs_clear_image,
8237 NULL
8241 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8243 static void
8244 gs_clear_image (f, img)
8245 struct frame *f;
8246 struct image *img;
8248 /* IMG->data.ptr_val may contain a recorded colormap. */
8249 xfree (img->data.ptr_val);
8250 x_clear_image (f, img);
8254 /* Return non-zero if OBJECT is a valid Ghostscript image
8255 specification. */
8257 static int
8258 gs_image_p (object)
8259 Lisp_Object object;
8261 struct image_keyword fmt[GS_LAST];
8262 Lisp_Object tem;
8263 int i;
8265 bcopy (gs_format, fmt, sizeof fmt);
8267 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8268 return 0;
8270 /* Bounding box must be a list or vector containing 4 integers. */
8271 tem = fmt[GS_BOUNDING_BOX].value;
8272 if (CONSP (tem))
8274 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8275 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8276 return 0;
8277 if (!NILP (tem))
8278 return 0;
8280 else if (VECTORP (tem))
8282 if (XVECTOR (tem)->size != 4)
8283 return 0;
8284 for (i = 0; i < 4; ++i)
8285 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8286 return 0;
8288 else
8289 return 0;
8291 return 1;
8295 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8296 if successful. */
8298 static int
8299 gs_load (f, img)
8300 struct frame *f;
8301 struct image *img;
8303 char buffer[100];
8304 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8305 struct gcpro gcpro1, gcpro2;
8306 Lisp_Object frame;
8307 double in_width, in_height;
8308 Lisp_Object pixel_colors = Qnil;
8310 /* Compute pixel size of pixmap needed from the given size in the
8311 image specification. Sizes in the specification are in pt. 1 pt
8312 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8313 info. */
8314 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8315 in_width = XFASTINT (pt_width) / 72.0;
8316 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
8317 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8318 in_height = XFASTINT (pt_height) / 72.0;
8319 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
8321 if (!check_image_size (f, img->width, img->height))
8323 image_error ("Invalid image size", Qnil, Qnil);
8324 return 0;
8327 /* Create the pixmap. */
8328 xassert (img->pixmap == NO_PIXMAP);
8330 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8331 BLOCK_INPUT;
8332 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8333 img->width, img->height,
8334 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8335 UNBLOCK_INPUT;
8337 if (!img->pixmap)
8339 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8340 return 0;
8343 /* Call the loader to fill the pixmap. It returns a process object
8344 if successful. We do not record_unwind_protect here because
8345 other places in redisplay like calling window scroll functions
8346 don't either. Let the Lisp loader use `unwind-protect' instead. */
8347 GCPRO2 (window_and_pixmap_id, pixel_colors);
8349 sprintf (buffer, "%lu %lu",
8350 (unsigned long) FRAME_X_WINDOW (f),
8351 (unsigned long) img->pixmap);
8352 window_and_pixmap_id = build_string (buffer);
8354 sprintf (buffer, "%lu %lu",
8355 FRAME_FOREGROUND_PIXEL (f),
8356 FRAME_BACKGROUND_PIXEL (f));
8357 pixel_colors = build_string (buffer);
8359 XSETFRAME (frame, f);
8360 loader = image_spec_value (img->spec, QCloader, NULL);
8361 if (NILP (loader))
8362 loader = intern ("gs-load-image");
8364 img->data.lisp_val = call6 (loader, frame, img->spec,
8365 make_number (img->width),
8366 make_number (img->height),
8367 window_and_pixmap_id,
8368 pixel_colors);
8369 UNGCPRO;
8370 return PROCESSP (img->data.lisp_val);
8374 /* Kill the Ghostscript process that was started to fill PIXMAP on
8375 frame F. Called from XTread_socket when receiving an event
8376 telling Emacs that Ghostscript has finished drawing. */
8378 void
8379 x_kill_gs_process (pixmap, f)
8380 Pixmap pixmap;
8381 struct frame *f;
8383 struct image_cache *c = FRAME_IMAGE_CACHE (f);
8384 int class, i;
8385 struct image *img;
8387 /* Find the image containing PIXMAP. */
8388 for (i = 0; i < c->used; ++i)
8389 if (c->images[i]->pixmap == pixmap)
8390 break;
8392 /* Should someone in between have cleared the image cache, for
8393 instance, give up. */
8394 if (i == c->used)
8395 return;
8397 /* Kill the GS process. We should have found PIXMAP in the image
8398 cache and its image should contain a process object. */
8399 img = c->images[i];
8400 xassert (PROCESSP (img->data.lisp_val));
8401 Fkill_process (img->data.lisp_val, Qnil);
8402 img->data.lisp_val = Qnil;
8404 #if defined (HAVE_X_WINDOWS)
8406 /* On displays with a mutable colormap, figure out the colors
8407 allocated for the image by looking at the pixels of an XImage for
8408 img->pixmap. */
8409 class = FRAME_X_VISUAL (f)->class;
8410 if (class != StaticColor && class != StaticGray && class != TrueColor)
8412 XImagePtr ximg;
8414 BLOCK_INPUT;
8416 /* Try to get an XImage for img->pixmep. */
8417 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8418 0, 0, img->width, img->height, ~0, ZPixmap);
8419 if (ximg)
8421 int x, y;
8423 /* Initialize the color table. */
8424 init_color_table ();
8426 /* For each pixel of the image, look its color up in the
8427 color table. After having done so, the color table will
8428 contain an entry for each color used by the image. */
8429 for (y = 0; y < img->height; ++y)
8430 for (x = 0; x < img->width; ++x)
8432 unsigned long pixel = XGetPixel (ximg, x, y);
8433 lookup_pixel_color (f, pixel);
8436 /* Record colors in the image. Free color table and XImage. */
8437 #ifdef COLOR_TABLE_SUPPORT
8438 img->colors = colors_in_color_table (&img->ncolors);
8439 free_color_table ();
8440 #endif
8441 XDestroyImage (ximg);
8443 #if 0 /* This doesn't seem to be the case. If we free the colors
8444 here, we get a BadAccess later in x_clear_image when
8445 freeing the colors. */
8446 /* We have allocated colors once, but Ghostscript has also
8447 allocated colors on behalf of us. So, to get the
8448 reference counts right, free them once. */
8449 if (img->ncolors)
8450 x_free_colors (f, img->colors, img->ncolors);
8451 #endif
8453 else
8454 image_error ("Cannot get X image of `%s'; colors will not be freed",
8455 img->spec, Qnil);
8457 UNBLOCK_INPUT;
8459 #endif /* HAVE_X_WINDOWS */
8461 /* Now that we have the pixmap, compute mask and transform the
8462 image if requested. */
8463 BLOCK_INPUT;
8464 postprocess_image (f, img);
8465 UNBLOCK_INPUT;
8468 #endif /* HAVE_GHOSTSCRIPT */
8471 /***********************************************************************
8472 Tests
8473 ***********************************************************************/
8475 #if GLYPH_DEBUG
8477 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8478 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8479 (spec)
8480 Lisp_Object spec;
8482 return valid_image_p (spec) ? Qt : Qnil;
8486 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8487 (spec)
8488 Lisp_Object spec;
8490 int id = -1;
8492 if (valid_image_p (spec))
8493 id = lookup_image (SELECTED_FRAME (), spec);
8495 debug_print (spec);
8496 return make_number (id);
8499 #endif /* GLYPH_DEBUG != 0 */
8502 /***********************************************************************
8503 Initialization
8504 ***********************************************************************/
8506 #ifdef HAVE_NTGUI
8507 /* Image types that rely on external libraries are loaded dynamically
8508 if the library is available. */
8509 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8510 define_image_type (image_type, init_lib_fn (libraries))
8511 #else
8512 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8513 define_image_type (image_type, 1)
8514 #endif /* HAVE_NTGUI */
8516 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8517 doc: /* Initialize image library implementing image type TYPE.
8518 Return non-nil if TYPE is a supported image type.
8520 Image types pbm and xbm are prebuilt; other types are loaded here.
8521 Libraries to load are specified in alist LIBRARIES (usually, the value
8522 of `image-library-alist', which see). */)
8523 (type, libraries)
8524 Lisp_Object type, libraries;
8526 Lisp_Object tested;
8528 /* Don't try to reload the library. */
8529 tested = Fassq (type, Vimage_type_cache);
8530 if (CONSP (tested))
8531 return XCDR (tested);
8533 #if defined (HAVE_XPM) || defined (HAVE_NS)
8534 if (EQ (type, Qxpm))
8535 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
8536 #endif
8538 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8539 if (EQ (type, Qjpeg))
8540 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
8541 #endif
8543 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8544 if (EQ (type, Qtiff))
8545 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
8546 #endif
8548 #if defined (HAVE_GIF) || defined (HAVE_NS)
8549 if (EQ (type, Qgif))
8550 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
8551 #endif
8553 #if defined (HAVE_PNG) || defined (HAVE_NS)
8554 if (EQ (type, Qpng))
8555 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
8556 #endif
8558 #if defined (HAVE_RSVG)
8559 if (EQ (type, Qsvg))
8560 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
8561 #endif
8563 #ifdef HAVE_GHOSTSCRIPT
8564 if (EQ (type, Qpostscript))
8565 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
8566 #endif
8568 /* If the type is not recognized, avoid testing it ever again. */
8569 CACHE_IMAGE_TYPE (type, Qnil);
8570 return Qnil;
8573 void
8574 syms_of_image ()
8576 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
8578 /* Initialize this only once, since that's what we do with Vimage_types
8579 and they are supposed to be in sync. Initializing here gives correct
8580 operation on GNU/Linux of calling dump-emacs after loading some images. */
8581 image_types = NULL;
8583 /* Must be defined now becase we're going to update it below, while
8584 defining the supported image types. */
8585 DEFVAR_LISP ("image-types", &Vimage_types,
8586 doc: /* List of potentially supported image types.
8587 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8588 To check whether it is really supported, use `image-type-available-p'. */);
8589 Vimage_types = Qnil;
8591 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
8592 doc: /* Alist of image types vs external libraries needed to display them.
8594 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8595 representing a supported image type, and the rest are strings giving
8596 alternate filenames for the corresponding external libraries.
8598 Emacs tries to load the libraries in the order they appear on the
8599 list; if none is loaded, the running session of Emacs won't
8600 support the image type. Types 'pbm and 'xbm don't need to be
8601 listed; they are always supported. */);
8602 Vimage_library_alist = Qnil;
8603 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
8605 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
8606 doc: /* Maximum size of images.
8607 Emacs will not load an image into memory if its pixel width or
8608 pixel height exceeds this limit.
8610 If the value is an integer, it directly specifies the maximum
8611 image height and width, measured in pixels. If it is a floating
8612 point number, it specifies the maximum image height and width
8613 as a ratio to the frame height and width. If the value is
8614 non-numeric, there is no explicit limit on the size of images. */);
8615 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8617 Vimage_type_cache = Qnil;
8618 staticpro (&Vimage_type_cache);
8620 Qpbm = intern ("pbm");
8621 staticpro (&Qpbm);
8622 ADD_IMAGE_TYPE (Qpbm);
8624 Qxbm = intern ("xbm");
8625 staticpro (&Qxbm);
8626 ADD_IMAGE_TYPE (Qxbm);
8628 define_image_type (&xbm_type, 1);
8629 define_image_type (&pbm_type, 1);
8631 Qcount = intern ("count");
8632 staticpro (&Qcount);
8634 QCascent = intern (":ascent");
8635 staticpro (&QCascent);
8636 QCmargin = intern (":margin");
8637 staticpro (&QCmargin);
8638 QCrelief = intern (":relief");
8639 staticpro (&QCrelief);
8640 QCconversion = intern (":conversion");
8641 staticpro (&QCconversion);
8642 QCcolor_symbols = intern (":color-symbols");
8643 staticpro (&QCcolor_symbols);
8644 QCheuristic_mask = intern (":heuristic-mask");
8645 staticpro (&QCheuristic_mask);
8646 QCindex = intern (":index");
8647 staticpro (&QCindex);
8648 QCmatrix = intern (":matrix");
8649 staticpro (&QCmatrix);
8650 QCcolor_adjustment = intern (":color-adjustment");
8651 staticpro (&QCcolor_adjustment);
8652 QCmask = intern (":mask");
8653 staticpro (&QCmask);
8655 Qlaplace = intern ("laplace");
8656 staticpro (&Qlaplace);
8657 Qemboss = intern ("emboss");
8658 staticpro (&Qemboss);
8659 Qedge_detection = intern ("edge-detection");
8660 staticpro (&Qedge_detection);
8661 Qheuristic = intern ("heuristic");
8662 staticpro (&Qheuristic);
8664 Qpostscript = intern ("postscript");
8665 staticpro (&Qpostscript);
8666 #ifdef HAVE_GHOSTSCRIPT
8667 ADD_IMAGE_TYPE (Qpostscript);
8668 QCloader = intern (":loader");
8669 staticpro (&QCloader);
8670 QCbounding_box = intern (":bounding-box");
8671 staticpro (&QCbounding_box);
8672 QCpt_width = intern (":pt-width");
8673 staticpro (&QCpt_width);
8674 QCpt_height = intern (":pt-height");
8675 staticpro (&QCpt_height);
8676 #endif /* HAVE_GHOSTSCRIPT */
8678 #if defined (HAVE_XPM) || defined (HAVE_NS)
8679 Qxpm = intern ("xpm");
8680 staticpro (&Qxpm);
8681 ADD_IMAGE_TYPE (Qxpm);
8682 #endif
8684 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8685 Qjpeg = intern ("jpeg");
8686 staticpro (&Qjpeg);
8687 ADD_IMAGE_TYPE (Qjpeg);
8688 #endif
8690 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8691 Qtiff = intern ("tiff");
8692 staticpro (&Qtiff);
8693 ADD_IMAGE_TYPE (Qtiff);
8694 #endif
8696 #if defined (HAVE_GIF) || defined (HAVE_NS)
8697 Qgif = intern ("gif");
8698 staticpro (&Qgif);
8699 ADD_IMAGE_TYPE (Qgif);
8700 #endif
8702 #if defined (HAVE_PNG) || defined (HAVE_NS)
8703 Qpng = intern ("png");
8704 staticpro (&Qpng);
8705 ADD_IMAGE_TYPE (Qpng);
8706 #endif
8708 #if defined (HAVE_RSVG)
8709 Qsvg = intern ("svg");
8710 staticpro (&Qsvg);
8711 ADD_IMAGE_TYPE (Qsvg);
8712 #ifdef HAVE_NTGUI
8713 /* Other libraries used directly by svg code. */
8714 Qgdk_pixbuf = intern ("gdk-pixbuf");
8715 staticpro (&Qgdk_pixbuf);
8716 Qglib = intern ("glib");
8717 staticpro (&Qglib);
8718 Qgobject = intern ("gobject");
8719 staticpro (&Qgobject);
8720 #endif /* HAVE_NTGUI */
8721 #endif /* HAVE_RSVG */
8723 defsubr (&Sinit_image_library);
8724 defsubr (&Sclear_image_cache);
8725 defsubr (&Simage_refresh);
8726 defsubr (&Simage_size);
8727 defsubr (&Simage_mask_p);
8728 defsubr (&Simage_extension_data);
8730 #if GLYPH_DEBUG
8731 defsubr (&Simagep);
8732 defsubr (&Slookup_image);
8733 #endif
8735 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
8736 doc: /* Non-nil means always draw a cross over disabled images.
8737 Disabled images are those having a `:conversion disabled' property.
8738 A cross is always drawn on black & white displays. */);
8739 cross_disabled_images = 0;
8741 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8742 doc: /* List of directories to search for window system bitmap files. */);
8743 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
8745 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
8746 doc: /* Time after which cached images are removed from the cache.
8747 When an image has not been displayed this many seconds, remove it
8748 from the image cache. Value must be an integer or nil with nil
8749 meaning don't clear the cache. */);
8750 Vimage_cache_eviction_delay = make_number (30 * 60);
8753 void
8754 init_image ()
8758 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8759 (do not change this comment) */