Merge from emacs--rel--22
[bpt/emacs.git] / src / image.c
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <ctype.h>
25
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 /* This makes the fields of a Display accessible, in Xlib header files. */
31
32 #define XLIB_ILLEGAL_ACCESS
33
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"
45
46 #ifdef HAVE_X_WINDOWS
47 #include "xterm.h"
48 #include <sys/types.h>
49 #include <sys/stat.h>
50
51 #define COLOR_TABLE_SUPPORT 1
52
53 typedef struct x_bitmap_record Bitmap_Record;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
56
57 #define RGB_PIXEL_COLOR unsigned long
58
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
62
63
64 #ifdef HAVE_NTGUI
65 #include "w32term.h"
66
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
69
70 typedef struct w32_bitmap_record Bitmap_Record;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
72 #define NO_PIXMAP 0
73
74 #define RGB_PIXEL_COLOR COLORREF
75
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
78
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
82 #endif /* HAVE_NTGUI */
83
84
85 #ifdef MAC_OS
86 #include "macterm.h"
87 #include <sys/stat.h>
88 #ifndef MAC_OSX
89 #include <alloca.h>
90 #include <sys/param.h>
91 #endif
92 #if TARGET_API_MAC_CARBON
93 #ifdef MAC_OSX
94 #include <QuickTime/QuickTime.h>
95 #else /* not MAC_OSX */
96 #include <QuickTime.h>
97 #endif /* not MAC_OSX */
98 #else /* not TARGET_API_MAC_CARBON */
99 #include <Windows.h>
100 #include <Gestalt.h>
101 #include <TextUtils.h>
102 #include <ImageCompression.h>
103 #include <QuickTimeComponents.h>
104 #endif /* not TARGET_API_MAC_CARBON */
105
106 /* MAC_TODO : Color tables on Mac. */
107 #undef COLOR_TABLE_SUPPORT
108
109 #define ZPixmap 0 /* arbitrary */
110 typedef struct mac_bitmap_record Bitmap_Record;
111
112 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
113 #define NO_PIXMAP 0
114
115 #define RGB_PIXEL_COLOR unsigned long
116
117 #if USE_MAC_IMAGE_IO
118 #define PIX_MASK_DRAW 255
119 #define PIX_MASK_RETAIN 0
120 #else
121 /* A black pixel in a mask bitmap/pixmap means ``draw a source
122 pixel''. A white pixel means ``retain the current pixel''. */
123 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
124 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
125 #endif
126
127 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
128 #define x_defined_color mac_defined_color
129 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
130
131 #endif /* MAC_OS */
132
133
134 /* Search path for bitmap files. */
135
136 Lisp_Object Vx_bitmap_file_path;
137
138
139 static void x_disable_image P_ ((struct frame *, struct image *));
140 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
141 Lisp_Object));
142
143 static void init_color_table P_ ((void));
144 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
145 #ifdef COLOR_TABLE_SUPPORT
146 static void free_color_table P_ ((void));
147 static unsigned long *colors_in_color_table P_ ((int *n));
148 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
149 #endif
150
151 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
152 id, which is just an int that this section returns. Bitmaps are
153 reference counted so they can be shared among frames.
154
155 Bitmap indices are guaranteed to be > 0, so a negative number can
156 be used to indicate no bitmap.
157
158 If you use x_create_bitmap_from_data, then you must keep track of
159 the bitmaps yourself. That is, creating a bitmap from the same
160 data more than once will not be caught. */
161
162 #ifdef MAC_OS
163
164 static XImagePtr
165 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
166 Display *display; /* not used */
167 Pixmap pixmap;
168 int x, y; /* not used */
169 unsigned int width, height; /* not used */
170 unsigned long plane_mask; /* not used */
171 int format; /* not used */
172 {
173 #if !USE_MAC_IMAGE_IO
174 #if GLYPH_DEBUG
175 xassert (x == 0 && y == 0);
176 {
177 Rect ri, rp;
178 SetRect (&ri, 0, 0, width, height);
179 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
180 }
181 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
182 #endif
183
184 LockPixels (GetGWorldPixMap (pixmap));
185 #endif
186
187 return pixmap;
188 }
189
190 static void
191 XPutPixel (ximage, x, y, pixel)
192 XImagePtr ximage;
193 int x, y;
194 unsigned long pixel;
195 {
196 #if USE_MAC_IMAGE_IO
197 if (ximage->bits_per_pixel == 32)
198 ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
199 else
200 ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
201 #else
202 PixMapHandle pixmap = GetGWorldPixMap (ximage);
203 short depth = GetPixDepth (pixmap);
204
205 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
206 if (depth == 32)
207 {
208 char *base_addr = GetPixBaseAddr (pixmap);
209 short row_bytes = GetPixRowBytes (pixmap);
210
211 ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
212 }
213 else
214 #endif
215 if (depth == 1)
216 {
217 char *base_addr = GetPixBaseAddr (pixmap);
218 short row_bytes = GetPixRowBytes (pixmap);
219
220 if (pixel == PIX_MASK_DRAW)
221 base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
222 else
223 base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
224 }
225 else
226 {
227 CGrafPtr old_port;
228 GDHandle old_gdh;
229 RGBColor color;
230
231 GetGWorld (&old_port, &old_gdh);
232 SetGWorld (ximage, NULL);
233
234 color.red = RED16_FROM_ULONG (pixel);
235 color.green = GREEN16_FROM_ULONG (pixel);
236 color.blue = BLUE16_FROM_ULONG (pixel);
237
238 SetCPixel (x, y, &color);
239
240 SetGWorld (old_port, old_gdh);
241 }
242 #endif
243 }
244
245 static unsigned long
246 XGetPixel (ximage, x, y)
247 XImagePtr ximage;
248 int x, y;
249 {
250 #if USE_MAC_IMAGE_IO
251 if (ximage->bits_per_pixel == 32)
252 return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
253 else
254 return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
255 #else
256 PixMapHandle pixmap = GetGWorldPixMap (ximage);
257 short depth = GetPixDepth (pixmap);
258
259 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
260 if (depth == 32)
261 {
262 char *base_addr = GetPixBaseAddr (pixmap);
263 short row_bytes = GetPixRowBytes (pixmap);
264
265 return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
266 }
267 else
268 #endif
269 if (depth == 1)
270 {
271 char *base_addr = GetPixBaseAddr (pixmap);
272 short row_bytes = GetPixRowBytes (pixmap);
273
274 if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
275 return PIX_MASK_DRAW;
276 else
277 return PIX_MASK_RETAIN;
278 }
279 else
280 {
281 CGrafPtr old_port;
282 GDHandle old_gdh;
283 RGBColor color;
284
285 GetGWorld (&old_port, &old_gdh);
286 SetGWorld (ximage, NULL);
287
288 GetCPixel (x, y, &color);
289
290 SetGWorld (old_port, old_gdh);
291 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
292 }
293 #endif
294 }
295
296 static void
297 XDestroyImage (ximg)
298 XImagePtr ximg;
299 {
300 #if !USE_MAC_IMAGE_IO
301 UnlockPixels (GetGWorldPixMap (ximg));
302 #endif
303 }
304
305 #if USE_CG_DRAWING
306 #if USE_MAC_IMAGE_IO
307 void
308 mac_data_provider_release_data (info, data, size)
309 void *info;
310 const void *data;
311 size_t size;
312 {
313 xfree ((void *)data);
314 }
315 #endif
316
317 static CGImageRef
318 mac_create_cg_image_from_image (f, img)
319 struct frame *f;
320 struct image *img;
321 {
322 #if USE_MAC_IMAGE_IO
323 XImagePtr ximg = img->pixmap;
324 CGDataProviderRef provider;
325 CGImageRef result;
326
327 if (img->mask)
328 {
329 int x, y;
330 unsigned long color, alpha;
331
332 for (y = 0; y < ximg->height; y++)
333 for (x = 0; x < ximg->width; x++)
334 {
335 color = XGetPixel (ximg, x, y);
336 alpha = XGetPixel (img->mask, x, y);
337 XPutPixel (ximg, x, y,
338 ARGB_TO_ULONG (alpha,
339 RED_FROM_ULONG (color)
340 * alpha / PIX_MASK_DRAW,
341 GREEN_FROM_ULONG (color)
342 * alpha / PIX_MASK_DRAW,
343 BLUE_FROM_ULONG (color)
344 * alpha / PIX_MASK_DRAW));
345 }
346 xfree (img->mask->data);
347 img->mask->data = NULL;
348 }
349 BLOCK_INPUT;
350 provider = CGDataProviderCreateWithData (NULL, ximg->data,
351 ximg->bytes_per_line * ximg->height,
352 mac_data_provider_release_data);
353 ximg->data = NULL;
354 result = CGImageCreate (ximg->width, ximg->height, 8, 32,
355 ximg->bytes_per_line, mac_cg_color_space_rgb,
356 (img->mask ? kCGImageAlphaPremultipliedFirst
357 : kCGImageAlphaNoneSkipFirst)
358 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
359 | kCGBitmapByteOrder32Host
360 #endif
361 , provider, NULL, 0, kCGRenderingIntentDefault);
362 CGDataProviderRelease (provider);
363 UNBLOCK_INPUT;
364
365 return result;
366 #else
367 Pixmap mask;
368 CGImageRef result = NULL;
369
370 BLOCK_INPUT;
371 if (img->mask)
372 mask = img->mask;
373 else
374 {
375 mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
376 img->width, img->height, 1);
377 if (mask)
378 {
379 CGrafPtr old_port;
380 GDHandle old_gdh;
381 Rect r;
382
383 GetGWorld (&old_port, &old_gdh);
384 SetGWorld (mask, NULL);
385 BackColor (blackColor); /* Don't mask. */
386 SetRect (&r, 0, 0, img->width, img->height);
387 EraseRect (&r);
388 SetGWorld (old_port, old_gdh);
389 }
390 }
391 if (mask)
392 {
393 CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
394 GetGWorldPixMap (mask), &result);
395 if (mask != img->mask)
396 XFreePixmap (FRAME_X_DISPLAY (f), mask);
397 }
398 UNBLOCK_INPUT;
399
400 return result;
401 #endif
402 }
403 #endif /* USE_CG_DRAWING */
404 #endif /* MAC_OS */
405
406
407 /* Functions to access the contents of a bitmap, given an id. */
408
409 int
410 x_bitmap_height (f, id)
411 FRAME_PTR f;
412 int id;
413 {
414 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
415 }
416
417 int
418 x_bitmap_width (f, id)
419 FRAME_PTR f;
420 int id;
421 {
422 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
423 }
424
425 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
426 int
427 x_bitmap_pixmap (f, id)
428 FRAME_PTR f;
429 int id;
430 {
431 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
432 }
433 #endif
434
435 #ifdef HAVE_X_WINDOWS
436 int
437 x_bitmap_mask (f, id)
438 FRAME_PTR f;
439 int id;
440 {
441 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
442 }
443 #endif
444
445 /* Allocate a new bitmap record. Returns index of new record. */
446
447 static int
448 x_allocate_bitmap_record (f)
449 FRAME_PTR f;
450 {
451 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
452 int i;
453
454 if (dpyinfo->bitmaps == NULL)
455 {
456 dpyinfo->bitmaps_size = 10;
457 dpyinfo->bitmaps
458 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
459 dpyinfo->bitmaps_last = 1;
460 return 1;
461 }
462
463 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
464 return ++dpyinfo->bitmaps_last;
465
466 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
467 if (dpyinfo->bitmaps[i].refcount == 0)
468 return i + 1;
469
470 dpyinfo->bitmaps_size *= 2;
471 dpyinfo->bitmaps
472 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
473 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
474 return ++dpyinfo->bitmaps_last;
475 }
476
477 /* Add one reference to the reference count of the bitmap with id ID. */
478
479 void
480 x_reference_bitmap (f, id)
481 FRAME_PTR f;
482 int id;
483 {
484 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
485 }
486
487 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
488
489 int
490 x_create_bitmap_from_data (f, bits, width, height)
491 struct frame *f;
492 char *bits;
493 unsigned int width, height;
494 {
495 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
496 int id;
497
498 #ifdef HAVE_X_WINDOWS
499 Pixmap bitmap;
500 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
501 bits, width, height);
502 if (! bitmap)
503 return -1;
504 #endif /* HAVE_X_WINDOWS */
505
506 #ifdef HAVE_NTGUI
507 Pixmap bitmap;
508 bitmap = CreateBitmap (width, height,
509 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
510 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
511 bits);
512 if (! bitmap)
513 return -1;
514 #endif /* HAVE_NTGUI */
515
516 #ifdef MAC_OS
517 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
518 if (width % 16 != 0)
519 return -1;
520 #endif
521
522 id = x_allocate_bitmap_record (f);
523 #ifdef MAC_OS
524 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
525 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
526 #endif /* MAC_OS */
527
528 dpyinfo->bitmaps[id - 1].file = NULL;
529 dpyinfo->bitmaps[id - 1].height = height;
530 dpyinfo->bitmaps[id - 1].width = width;
531 dpyinfo->bitmaps[id - 1].refcount = 1;
532
533 #ifdef HAVE_X_WINDOWS
534 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
535 dpyinfo->bitmaps[id - 1].have_mask = 0;
536 dpyinfo->bitmaps[id - 1].depth = 1;
537 #endif /* HAVE_X_WINDOWS */
538
539 #ifdef HAVE_NTGUI
540 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
541 dpyinfo->bitmaps[id - 1].hinst = NULL;
542 dpyinfo->bitmaps[id - 1].depth = 1;
543 #endif /* HAVE_NTGUI */
544
545 return id;
546 }
547
548 /* Create bitmap from file FILE for frame F. */
549
550 int
551 x_create_bitmap_from_file (f, file)
552 struct frame *f;
553 Lisp_Object file;
554 {
555 #ifdef MAC_OS
556 return -1; /* MAC_TODO : bitmap support */
557 #endif /* MAC_OS */
558
559 #ifdef HAVE_NTGUI
560 return -1; /* W32_TODO : bitmap support */
561 #endif /* HAVE_NTGUI */
562
563 #ifdef HAVE_X_WINDOWS
564 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
565 unsigned int width, height;
566 Pixmap bitmap;
567 int xhot, yhot, result, id;
568 Lisp_Object found;
569 int fd;
570 char *filename;
571
572 /* Look for an existing bitmap with the same name. */
573 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
574 {
575 if (dpyinfo->bitmaps[id].refcount
576 && dpyinfo->bitmaps[id].file
577 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
578 {
579 ++dpyinfo->bitmaps[id].refcount;
580 return id + 1;
581 }
582 }
583
584 /* Search bitmap-file-path for the file, if appropriate. */
585 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
586 if (fd < 0)
587 return -1;
588 emacs_close (fd);
589
590 filename = (char *) SDATA (found);
591
592 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
593 filename, &width, &height, &bitmap, &xhot, &yhot);
594 if (result != BitmapSuccess)
595 return -1;
596
597 id = x_allocate_bitmap_record (f);
598 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
599 dpyinfo->bitmaps[id - 1].have_mask = 0;
600 dpyinfo->bitmaps[id - 1].refcount = 1;
601 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
602 dpyinfo->bitmaps[id - 1].depth = 1;
603 dpyinfo->bitmaps[id - 1].height = height;
604 dpyinfo->bitmaps[id - 1].width = width;
605 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
606
607 return id;
608 #endif /* HAVE_X_WINDOWS */
609 }
610
611 /* Free bitmap B. */
612
613 static void
614 free_bitmap_record (dpyinfo, bm)
615 Display_Info *dpyinfo;
616 Bitmap_Record *bm;
617 {
618 #ifdef HAVE_X_WINDOWS
619 XFreePixmap (dpyinfo->display, bm->pixmap);
620 if (bm->have_mask)
621 XFreePixmap (dpyinfo->display, bm->mask);
622 #endif /* HAVE_X_WINDOWS */
623
624 #ifdef HAVE_NTGUI
625 DeleteObject (bm->pixmap);
626 #endif /* HAVE_NTGUI */
627
628 #ifdef MAC_OS
629 xfree (bm->bitmap_data); /* Added ++kfs */
630 bm->bitmap_data = NULL;
631 #endif /* MAC_OS */
632
633 if (bm->file)
634 {
635 xfree (bm->file);
636 bm->file = NULL;
637 }
638 }
639
640 /* Remove reference to bitmap with id number ID. */
641
642 void
643 x_destroy_bitmap (f, id)
644 FRAME_PTR f;
645 int id;
646 {
647 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
648
649 if (id > 0)
650 {
651 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
652
653 if (--bm->refcount == 0)
654 {
655 BLOCK_INPUT;
656 free_bitmap_record (dpyinfo, bm);
657 UNBLOCK_INPUT;
658 }
659 }
660 }
661
662 /* Free all the bitmaps for the display specified by DPYINFO. */
663
664 void
665 x_destroy_all_bitmaps (dpyinfo)
666 Display_Info *dpyinfo;
667 {
668 int i;
669 Bitmap_Record *bm = dpyinfo->bitmaps;
670
671 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
672 if (bm->refcount > 0)
673 free_bitmap_record (dpyinfo, bm);
674
675 dpyinfo->bitmaps_last = 0;
676 }
677
678
679 #ifdef HAVE_X_WINDOWS
680
681 /* Useful functions defined in the section
682 `Image type independent image structures' below. */
683
684 static unsigned long four_corners_best P_ ((XImagePtr ximg,
685 int *corners,
686 unsigned long width,
687 unsigned long height));
688
689 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
690 int depth, XImagePtr *ximg,
691 Pixmap *pixmap));
692
693 static void x_destroy_x_image P_ ((XImagePtr ximg));
694
695
696 /* Create a mask of a bitmap. Note is this not a perfect mask.
697 It's nicer with some borders in this context */
698
699 int
700 x_create_bitmap_mask (f, id)
701 struct frame *f;
702 int id;
703 {
704 Pixmap pixmap, mask;
705 XImagePtr ximg, mask_img;
706 unsigned long width, height;
707 int result;
708 unsigned long bg;
709 unsigned long x, y, xp, xm, yp, ym;
710 GC gc;
711
712 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
713
714 if (!(id > 0))
715 return -1;
716
717 pixmap = x_bitmap_pixmap (f, id);
718 width = x_bitmap_width (f, id);
719 height = x_bitmap_height (f, id);
720
721 BLOCK_INPUT;
722 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
723 ~0, ZPixmap);
724
725 if (!ximg)
726 {
727 UNBLOCK_INPUT;
728 return -1;
729 }
730
731 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
732
733 UNBLOCK_INPUT;
734 if (!result)
735 {
736 XDestroyImage (ximg);
737 return -1;
738 }
739
740 bg = four_corners_best (ximg, NULL, width, height);
741
742 for (y = 0; y < ximg->height; ++y)
743 {
744 for (x = 0; x < ximg->width; ++x)
745 {
746 xp = x != ximg->width - 1 ? x + 1 : 0;
747 xm = x != 0 ? x - 1 : ximg->width - 1;
748 yp = y != ximg->height - 1 ? y + 1 : 0;
749 ym = y != 0 ? y - 1 : ximg->height - 1;
750 if (XGetPixel (ximg, x, y) == bg
751 && XGetPixel (ximg, x, yp) == bg
752 && XGetPixel (ximg, x, ym) == bg
753 && XGetPixel (ximg, xp, y) == bg
754 && XGetPixel (ximg, xp, yp) == bg
755 && XGetPixel (ximg, xp, ym) == bg
756 && XGetPixel (ximg, xm, y) == bg
757 && XGetPixel (ximg, xm, yp) == bg
758 && XGetPixel (ximg, xm, ym) == bg)
759 XPutPixel (mask_img, x, y, 0);
760 else
761 XPutPixel (mask_img, x, y, 1);
762 }
763 }
764
765 xassert (interrupt_input_blocked);
766 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
767 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
768 width, height);
769 XFreeGC (FRAME_X_DISPLAY (f), gc);
770
771 dpyinfo->bitmaps[id - 1].have_mask = 1;
772 dpyinfo->bitmaps[id - 1].mask = mask;
773
774 XDestroyImage (ximg);
775 x_destroy_x_image (mask_img);
776
777 return 0;
778 }
779
780 #endif /* HAVE_X_WINDOWS */
781
782
783 /***********************************************************************
784 Image types
785 ***********************************************************************/
786
787 /* Value is the number of elements of vector VECTOR. */
788
789 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
790
791 /* List of supported image types. Use define_image_type to add new
792 types. Use lookup_image_type to find a type for a given symbol. */
793
794 static struct image_type *image_types;
795
796 /* A list of symbols, one for each supported image type. */
797
798 Lisp_Object Vimage_types;
799
800 /* An alist of image types and libraries that implement the type. */
801
802 Lisp_Object Vimage_library_alist;
803
804 /* Cache for delayed-loading image types. */
805
806 static Lisp_Object Vimage_type_cache;
807
808 /* The symbol `xbm' which is used as the type symbol for XBM images. */
809
810 Lisp_Object Qxbm;
811
812 /* Keywords. */
813
814 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
815 extern Lisp_Object QCdata, QCtype;
816 extern Lisp_Object Qcenter;
817 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
818 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
819 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
820
821 /* Other symbols. */
822
823 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
824
825 /* Time in seconds after which images should be removed from the cache
826 if not displayed. */
827
828 Lisp_Object Vimage_cache_eviction_delay;
829
830 /* Function prototypes. */
831
832 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
833 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
834 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
835 static void x_laplace P_ ((struct frame *, struct image *));
836 static void x_emboss P_ ((struct frame *, struct image *));
837 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
838 Lisp_Object));
839
840 #define CACHE_IMAGE_TYPE(type, status) \
841 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
842
843 #define ADD_IMAGE_TYPE(type) \
844 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
845
846 /* Define a new image type from TYPE. This adds a copy of TYPE to
847 image_types and caches the loading status of TYPE. */
848
849 static Lisp_Object
850 define_image_type (type, loaded)
851 struct image_type *type;
852 int loaded;
853 {
854 Lisp_Object success;
855
856 if (!loaded)
857 success = Qnil;
858 else
859 {
860 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
861 The initialized data segment is read-only. */
862 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
863 bcopy (type, p, sizeof *p);
864 p->next = image_types;
865 image_types = p;
866 success = Qt;
867 }
868
869 CACHE_IMAGE_TYPE (*type->type, success);
870 return success;
871 }
872
873
874 /* Look up image type SYMBOL, and return a pointer to its image_type
875 structure. Value is null if SYMBOL is not a known image type. */
876
877 static INLINE struct image_type *
878 lookup_image_type (symbol)
879 Lisp_Object symbol;
880 {
881 struct image_type *type;
882
883 /* We must initialize the image-type if it hasn't been already. */
884 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
885 return 0; /* unimplemented */
886
887 for (type = image_types; type; type = type->next)
888 if (EQ (symbol, *type->type))
889 break;
890
891 return type;
892 }
893
894
895 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
896 valid image specification is a list whose car is the symbol
897 `image', and whose rest is a property list. The property list must
898 contain a value for key `:type'. That value must be the name of a
899 supported image type. The rest of the property list depends on the
900 image type. */
901
902 int
903 valid_image_p (object)
904 Lisp_Object object;
905 {
906 int valid_p = 0;
907
908 if (IMAGEP (object))
909 {
910 Lisp_Object tem;
911
912 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
913 if (EQ (XCAR (tem), QCtype))
914 {
915 tem = XCDR (tem);
916 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
917 {
918 struct image_type *type;
919 type = lookup_image_type (XCAR (tem));
920 if (type)
921 valid_p = type->valid_p (object);
922 }
923
924 break;
925 }
926 }
927
928 return valid_p;
929 }
930
931
932 /* Log error message with format string FORMAT and argument ARG.
933 Signaling an error, e.g. when an image cannot be loaded, is not a
934 good idea because this would interrupt redisplay, and the error
935 message display would lead to another redisplay. This function
936 therefore simply displays a message. */
937
938 static void
939 image_error (format, arg1, arg2)
940 char *format;
941 Lisp_Object arg1, arg2;
942 {
943 add_to_log (format, arg1, arg2);
944 }
945
946
947 \f
948 /***********************************************************************
949 Image specifications
950 ***********************************************************************/
951
952 enum image_value_type
953 {
954 IMAGE_DONT_CHECK_VALUE_TYPE,
955 IMAGE_STRING_VALUE,
956 IMAGE_STRING_OR_NIL_VALUE,
957 IMAGE_SYMBOL_VALUE,
958 IMAGE_POSITIVE_INTEGER_VALUE,
959 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
960 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
961 IMAGE_ASCENT_VALUE,
962 IMAGE_INTEGER_VALUE,
963 IMAGE_FUNCTION_VALUE,
964 IMAGE_NUMBER_VALUE,
965 IMAGE_BOOL_VALUE
966 };
967
968 /* Structure used when parsing image specifications. */
969
970 struct image_keyword
971 {
972 /* Name of keyword. */
973 char *name;
974
975 /* The type of value allowed. */
976 enum image_value_type type;
977
978 /* Non-zero means key must be present. */
979 int mandatory_p;
980
981 /* Used to recognize duplicate keywords in a property list. */
982 int count;
983
984 /* The value that was found. */
985 Lisp_Object value;
986 };
987
988
989 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
990 int, Lisp_Object));
991 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
992
993
994 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
995 has the format (image KEYWORD VALUE ...). One of the keyword/
996 value pairs must be `:type TYPE'. KEYWORDS is a vector of
997 image_keywords structures of size NKEYWORDS describing other
998 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
999
1000 static int
1001 parse_image_spec (spec, keywords, nkeywords, type)
1002 Lisp_Object spec;
1003 struct image_keyword *keywords;
1004 int nkeywords;
1005 Lisp_Object type;
1006 {
1007 int i;
1008 Lisp_Object plist;
1009
1010 if (!IMAGEP (spec))
1011 return 0;
1012
1013 plist = XCDR (spec);
1014 while (CONSP (plist))
1015 {
1016 Lisp_Object key, value;
1017
1018 /* First element of a pair must be a symbol. */
1019 key = XCAR (plist);
1020 plist = XCDR (plist);
1021 if (!SYMBOLP (key))
1022 return 0;
1023
1024 /* There must follow a value. */
1025 if (!CONSP (plist))
1026 return 0;
1027 value = XCAR (plist);
1028 plist = XCDR (plist);
1029
1030 /* Find key in KEYWORDS. Error if not found. */
1031 for (i = 0; i < nkeywords; ++i)
1032 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
1033 break;
1034
1035 if (i == nkeywords)
1036 continue;
1037
1038 /* Record that we recognized the keyword. If a keywords
1039 was found more than once, it's an error. */
1040 keywords[i].value = value;
1041 ++keywords[i].count;
1042
1043 if (keywords[i].count > 1)
1044 return 0;
1045
1046 /* Check type of value against allowed type. */
1047 switch (keywords[i].type)
1048 {
1049 case IMAGE_STRING_VALUE:
1050 if (!STRINGP (value))
1051 return 0;
1052 break;
1053
1054 case IMAGE_STRING_OR_NIL_VALUE:
1055 if (!STRINGP (value) && !NILP (value))
1056 return 0;
1057 break;
1058
1059 case IMAGE_SYMBOL_VALUE:
1060 if (!SYMBOLP (value))
1061 return 0;
1062 break;
1063
1064 case IMAGE_POSITIVE_INTEGER_VALUE:
1065 if (!INTEGERP (value) || XINT (value) <= 0)
1066 return 0;
1067 break;
1068
1069 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
1070 if (INTEGERP (value) && XINT (value) >= 0)
1071 break;
1072 if (CONSP (value)
1073 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
1074 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
1075 break;
1076 return 0;
1077
1078 case IMAGE_ASCENT_VALUE:
1079 if (SYMBOLP (value) && EQ (value, Qcenter))
1080 break;
1081 else if (INTEGERP (value)
1082 && XINT (value) >= 0
1083 && XINT (value) <= 100)
1084 break;
1085 return 0;
1086
1087 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
1088 if (!INTEGERP (value) || XINT (value) < 0)
1089 return 0;
1090 break;
1091
1092 case IMAGE_DONT_CHECK_VALUE_TYPE:
1093 break;
1094
1095 case IMAGE_FUNCTION_VALUE:
1096 value = indirect_function (value);
1097 if (SUBRP (value)
1098 || COMPILEDP (value)
1099 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
1100 break;
1101 return 0;
1102
1103 case IMAGE_NUMBER_VALUE:
1104 if (!INTEGERP (value) && !FLOATP (value))
1105 return 0;
1106 break;
1107
1108 case IMAGE_INTEGER_VALUE:
1109 if (!INTEGERP (value))
1110 return 0;
1111 break;
1112
1113 case IMAGE_BOOL_VALUE:
1114 if (!NILP (value) && !EQ (value, Qt))
1115 return 0;
1116 break;
1117
1118 default:
1119 abort ();
1120 break;
1121 }
1122
1123 if (EQ (key, QCtype) && !EQ (type, value))
1124 return 0;
1125 }
1126
1127 /* Check that all mandatory fields are present. */
1128 for (i = 0; i < nkeywords; ++i)
1129 if (keywords[i].mandatory_p && keywords[i].count == 0)
1130 return 0;
1131
1132 return NILP (plist);
1133 }
1134
1135
1136 /* Return the value of KEY in image specification SPEC. Value is nil
1137 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1138 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1139
1140 static Lisp_Object
1141 image_spec_value (spec, key, found)
1142 Lisp_Object spec, key;
1143 int *found;
1144 {
1145 Lisp_Object tail;
1146
1147 xassert (valid_image_p (spec));
1148
1149 for (tail = XCDR (spec);
1150 CONSP (tail) && CONSP (XCDR (tail));
1151 tail = XCDR (XCDR (tail)))
1152 {
1153 if (EQ (XCAR (tail), key))
1154 {
1155 if (found)
1156 *found = 1;
1157 return XCAR (XCDR (tail));
1158 }
1159 }
1160
1161 if (found)
1162 *found = 0;
1163 return Qnil;
1164 }
1165
1166
1167 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
1168 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1169 PIXELS non-nil means return the size in pixels, otherwise return the
1170 size in canonical character units.
1171 FRAME is the frame on which the image will be displayed. FRAME nil
1172 or omitted means use the selected frame. */)
1173 (spec, pixels, frame)
1174 Lisp_Object spec, pixels, frame;
1175 {
1176 Lisp_Object size;
1177
1178 size = Qnil;
1179 if (valid_image_p (spec))
1180 {
1181 struct frame *f = check_x_frame (frame);
1182 int id = lookup_image (f, spec);
1183 struct image *img = IMAGE_FROM_ID (f, id);
1184 int width = img->width + 2 * img->hmargin;
1185 int height = img->height + 2 * img->vmargin;
1186
1187 if (NILP (pixels))
1188 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
1189 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
1190 else
1191 size = Fcons (make_number (width), make_number (height));
1192 }
1193 else
1194 error ("Invalid image specification");
1195
1196 return size;
1197 }
1198
1199
1200 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
1201 doc: /* Return t if image SPEC has a mask bitmap.
1202 FRAME is the frame on which the image will be displayed. FRAME nil
1203 or omitted means use the selected frame. */)
1204 (spec, frame)
1205 Lisp_Object spec, frame;
1206 {
1207 Lisp_Object mask;
1208
1209 mask = Qnil;
1210 if (valid_image_p (spec))
1211 {
1212 struct frame *f = check_x_frame (frame);
1213 int id = lookup_image (f, spec);
1214 struct image *img = IMAGE_FROM_ID (f, id);
1215 if (img->mask)
1216 mask = Qt;
1217 }
1218 else
1219 error ("Invalid image specification");
1220
1221 return mask;
1222 }
1223
1224 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1225 doc: /* Return extension data for image SPEC.
1226 FRAME is the frame on which the image will be displayed. FRAME nil
1227 or omitted means use the selected frame. */)
1228 (spec, frame)
1229 Lisp_Object spec, frame;
1230 {
1231 Lisp_Object ext;
1232
1233 ext = Qnil;
1234 if (valid_image_p (spec))
1235 {
1236 struct frame *f = check_x_frame (frame);
1237 int id = lookup_image (f, spec);
1238 struct image *img = IMAGE_FROM_ID (f, id);
1239 ext = img->data.lisp_val;
1240 }
1241
1242 return ext;
1243 }
1244
1245 \f
1246 /***********************************************************************
1247 Image type independent image structures
1248 ***********************************************************************/
1249
1250 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1251 static void free_image P_ ((struct frame *f, struct image *img));
1252 static int check_image_size P_ ((struct frame *f, int width, int height));
1253
1254 #define MAX_IMAGE_SIZE 6.0
1255 Lisp_Object Vmax_image_size;
1256
1257 /* Allocate and return a new image structure for image specification
1258 SPEC. SPEC has a hash value of HASH. */
1259
1260 static struct image *
1261 make_image (spec, hash)
1262 Lisp_Object spec;
1263 unsigned hash;
1264 {
1265 struct image *img = (struct image *) xmalloc (sizeof *img);
1266 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
1267
1268 xassert (valid_image_p (spec));
1269 bzero (img, sizeof *img);
1270 img->dependencies = NILP (file) ? Qnil : list1 (file);
1271 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1272 xassert (img->type != NULL);
1273 img->spec = spec;
1274 img->data.lisp_val = Qnil;
1275 img->ascent = DEFAULT_IMAGE_ASCENT;
1276 img->hash = hash;
1277 img->corners[BOT_CORNER] = -1; /* Full image */
1278 return img;
1279 }
1280
1281
1282 /* Free image IMG which was used on frame F, including its resources. */
1283
1284 static void
1285 free_image (f, img)
1286 struct frame *f;
1287 struct image *img;
1288 {
1289 if (img)
1290 {
1291 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1292
1293 /* Remove IMG from the hash table of its cache. */
1294 if (img->prev)
1295 img->prev->next = img->next;
1296 else
1297 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1298
1299 if (img->next)
1300 img->next->prev = img->prev;
1301
1302 c->images[img->id] = NULL;
1303
1304 /* Free resources, then free IMG. */
1305 img->type->free (f, img);
1306 xfree (img);
1307 }
1308 }
1309
1310 /* Return 1 if the given widths and heights are valid for display;
1311 otherwise, return 0. */
1312
1313 int
1314 check_image_size (f, width, height)
1315 struct frame *f;
1316 int width;
1317 int height;
1318 {
1319 int w, h;
1320
1321 if (width <= 0 || height <= 0)
1322 return 0;
1323
1324 if (INTEGERP (Vmax_image_size))
1325 w = h = XINT (Vmax_image_size);
1326 else if (FLOATP (Vmax_image_size))
1327 {
1328 if (f != NULL)
1329 {
1330 w = FRAME_PIXEL_WIDTH (f);
1331 h = FRAME_PIXEL_HEIGHT (f);
1332 }
1333 else
1334 w = h = 1024; /* Arbitrary size for unknown frame. */
1335 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1336 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1337 }
1338 else
1339 return 1;
1340
1341 return (width <= w && height <= h);
1342 }
1343
1344 /* Prepare image IMG for display on frame F. Must be called before
1345 drawing an image. */
1346
1347 void
1348 prepare_image_for_display (f, img)
1349 struct frame *f;
1350 struct image *img;
1351 {
1352 EMACS_TIME t;
1353
1354 /* We're about to display IMG, so set its timestamp to `now'. */
1355 EMACS_GET_TIME (t);
1356 img->timestamp = EMACS_SECS (t);
1357
1358 /* If IMG doesn't have a pixmap yet, load it now, using the image
1359 type dependent loader function. */
1360 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1361 img->load_failed_p = img->type->load (f, img) == 0;
1362
1363 #if defined (MAC_OS) && USE_CG_DRAWING
1364 if (!img->load_failed_p && img->data.ptr_val == NULL)
1365 {
1366 img->data.ptr_val = mac_create_cg_image_from_image (f, img);
1367 if (img->data.ptr_val == NULL)
1368 {
1369 img->load_failed_p = 1;
1370 img->type->free (f, img);
1371 }
1372 }
1373 #endif
1374 }
1375
1376
1377 /* Value is the number of pixels for the ascent of image IMG when
1378 drawn in face FACE. */
1379
1380 int
1381 image_ascent (img, face, slice)
1382 struct image *img;
1383 struct face *face;
1384 struct glyph_slice *slice;
1385 {
1386 int height;
1387 int ascent;
1388
1389 if (slice->height == img->height)
1390 height = img->height + img->vmargin;
1391 else if (slice->y == 0)
1392 height = slice->height + img->vmargin;
1393 else
1394 height = slice->height;
1395
1396 if (img->ascent == CENTERED_IMAGE_ASCENT)
1397 {
1398 if (face->font)
1399 {
1400 #ifdef HAVE_NTGUI
1401 /* W32 specific version. Why?. ++kfs */
1402 ascent = height / 2 - (FONT_DESCENT (face->font)
1403 - FONT_BASE (face->font)) / 2;
1404 #else
1405 /* This expression is arranged so that if the image can't be
1406 exactly centered, it will be moved slightly up. This is
1407 because a typical font is `top-heavy' (due to the presence
1408 uppercase letters), so the image placement should err towards
1409 being top-heavy too. It also just generally looks better. */
1410 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
1411 #endif /* HAVE_NTGUI */
1412 }
1413 else
1414 ascent = height / 2;
1415 }
1416 else
1417 ascent = (int) (height * img->ascent / 100.0);
1418
1419 return ascent;
1420 }
1421
1422 \f
1423 /* Image background colors. */
1424
1425 /* Find the "best" corner color of a bitmap.
1426 On W32, XIMG is assumed to a device context with the bitmap selected. */
1427
1428 static RGB_PIXEL_COLOR
1429 four_corners_best (ximg, corners, width, height)
1430 XImagePtr_or_DC ximg;
1431 int *corners;
1432 unsigned long width, height;
1433 {
1434 RGB_PIXEL_COLOR corner_pixels[4], best;
1435 int i, best_count;
1436
1437 if (corners && corners[BOT_CORNER] >= 0)
1438 {
1439 /* Get the colors at the corner_pixels of ximg. */
1440 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1441 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1442 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1443 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1444 }
1445 else
1446 {
1447 /* Get the colors at the corner_pixels of ximg. */
1448 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1449 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1450 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1451 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1452 }
1453 /* Choose the most frequently found color as background. */
1454 for (i = best_count = 0; i < 4; ++i)
1455 {
1456 int j, n;
1457
1458 for (j = n = 0; j < 4; ++j)
1459 if (corner_pixels[i] == corner_pixels[j])
1460 ++n;
1461
1462 if (n > best_count)
1463 best = corner_pixels[i], best_count = n;
1464 }
1465
1466 return best;
1467 }
1468
1469 /* Portability macros */
1470
1471 #ifdef HAVE_NTGUI
1472
1473 #define Destroy_Image(img_dc, prev) \
1474 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1475
1476 #define Free_Pixmap(display, pixmap) \
1477 DeleteObject (pixmap)
1478
1479 #else
1480
1481 #define Destroy_Image(ximg, dummy) \
1482 XDestroyImage (ximg)
1483
1484 #define Free_Pixmap(display, pixmap) \
1485 XFreePixmap (display, pixmap)
1486
1487 #endif /* HAVE_NTGUI */
1488
1489
1490 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1491 it is guessed heuristically. If non-zero, XIMG is an existing
1492 XImage object (or device context with the image selected on W32) to
1493 use for the heuristic. */
1494
1495 RGB_PIXEL_COLOR
1496 image_background (img, f, ximg)
1497 struct image *img;
1498 struct frame *f;
1499 XImagePtr_or_DC ximg;
1500 {
1501 if (! img->background_valid)
1502 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1503 {
1504 int free_ximg = !ximg;
1505 #ifdef HAVE_NTGUI
1506 HGDIOBJ prev;
1507 #endif /* HAVE_NTGUI */
1508
1509 if (free_ximg)
1510 {
1511 #ifndef HAVE_NTGUI
1512 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1513 0, 0, img->width, img->height, ~0, ZPixmap);
1514 #else
1515 HDC frame_dc = get_frame_dc (f);
1516 ximg = CreateCompatibleDC (frame_dc);
1517 release_frame_dc (f, frame_dc);
1518 prev = SelectObject (ximg, img->pixmap);
1519 #endif /* !HAVE_NTGUI */
1520 }
1521
1522 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1523
1524 if (free_ximg)
1525 Destroy_Image (ximg, prev);
1526
1527 img->background_valid = 1;
1528 }
1529
1530 return img->background;
1531 }
1532
1533 /* Return the `background_transparent' field of IMG. If IMG doesn't
1534 have one yet, it is guessed heuristically. If non-zero, MASK is an
1535 existing XImage object to use for the heuristic. */
1536
1537 int
1538 image_background_transparent (img, f, mask)
1539 struct image *img;
1540 struct frame *f;
1541 XImagePtr_or_DC mask;
1542 {
1543 if (! img->background_transparent_valid)
1544 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1545 {
1546 if (img->mask)
1547 {
1548 int free_mask = !mask;
1549 #ifdef HAVE_NTGUI
1550 HGDIOBJ prev;
1551 #endif /* HAVE_NTGUI */
1552
1553 if (free_mask)
1554 {
1555 #ifndef HAVE_NTGUI
1556 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1557 0, 0, img->width, img->height, ~0, ZPixmap);
1558 #else
1559 HDC frame_dc = get_frame_dc (f);
1560 mask = CreateCompatibleDC (frame_dc);
1561 release_frame_dc (f, frame_dc);
1562 prev = SelectObject (mask, img->mask);
1563 #endif /* HAVE_NTGUI */
1564 }
1565
1566 img->background_transparent
1567 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1568
1569 if (free_mask)
1570 Destroy_Image (mask, prev);
1571 }
1572 else
1573 img->background_transparent = 0;
1574
1575 img->background_transparent_valid = 1;
1576 }
1577
1578 return img->background_transparent;
1579 }
1580
1581 \f
1582 /***********************************************************************
1583 Helper functions for X image types
1584 ***********************************************************************/
1585
1586 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1587 int, int));
1588 static void x_clear_image P_ ((struct frame *f, struct image *img));
1589 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1590 struct image *img,
1591 Lisp_Object color_name,
1592 unsigned long dflt));
1593
1594
1595 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1596 free the pixmap if any. MASK_P non-zero means clear the mask
1597 pixmap if any. COLORS_P non-zero means free colors allocated for
1598 the image, if any. */
1599
1600 static void
1601 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1602 struct frame *f;
1603 struct image *img;
1604 int pixmap_p, mask_p, colors_p;
1605 {
1606 if (pixmap_p && img->pixmap)
1607 {
1608 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1609 img->pixmap = NO_PIXMAP;
1610 img->background_valid = 0;
1611 }
1612
1613 if (mask_p && img->mask)
1614 {
1615 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1616 img->mask = NO_PIXMAP;
1617 img->background_transparent_valid = 0;
1618 }
1619
1620 if (colors_p && img->ncolors)
1621 {
1622 /* MAC_TODO: color table support. */
1623 /* W32_TODO: color table support. */
1624 #ifdef HAVE_X_WINDOWS
1625 x_free_colors (f, img->colors, img->ncolors);
1626 #endif /* HAVE_X_WINDOWS */
1627 xfree (img->colors);
1628 img->colors = NULL;
1629 img->ncolors = 0;
1630 }
1631
1632 #if defined (MAC_OS) && USE_CG_DRAWING
1633 if (img->data.ptr_val)
1634 {
1635 CGImageRelease (img->data.ptr_val);
1636 img->data.ptr_val = NULL;
1637 }
1638 #endif
1639 }
1640
1641 /* Free X resources of image IMG which is used on frame F. */
1642
1643 static void
1644 x_clear_image (f, img)
1645 struct frame *f;
1646 struct image *img;
1647 {
1648 BLOCK_INPUT;
1649 x_clear_image_1 (f, img, 1, 1, 1);
1650 UNBLOCK_INPUT;
1651 }
1652
1653
1654 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1655 cannot be allocated, use DFLT. Add a newly allocated color to
1656 IMG->colors, so that it can be freed again. Value is the pixel
1657 color. */
1658
1659 static unsigned long
1660 x_alloc_image_color (f, img, color_name, dflt)
1661 struct frame *f;
1662 struct image *img;
1663 Lisp_Object color_name;
1664 unsigned long dflt;
1665 {
1666 XColor color;
1667 unsigned long result;
1668
1669 xassert (STRINGP (color_name));
1670
1671 if (x_defined_color (f, SDATA (color_name), &color, 1))
1672 {
1673 /* This isn't called frequently so we get away with simply
1674 reallocating the color vector to the needed size, here. */
1675 ++img->ncolors;
1676 img->colors =
1677 (unsigned long *) xrealloc (img->colors,
1678 img->ncolors * sizeof *img->colors);
1679 img->colors[img->ncolors - 1] = color.pixel;
1680 result = color.pixel;
1681 }
1682 else
1683 result = dflt;
1684
1685 return result;
1686 }
1687
1688
1689 \f
1690 /***********************************************************************
1691 Image Cache
1692 ***********************************************************************/
1693
1694 static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
1695 static void cache_image P_ ((struct frame *f, struct image *img));
1696 static void postprocess_image P_ ((struct frame *, struct image *));
1697
1698 /* Return a new, initialized image cache that is allocated from the
1699 heap. Call free_image_cache to free an image cache. */
1700
1701 struct image_cache *
1702 make_image_cache ()
1703 {
1704 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1705 int size;
1706
1707 bzero (c, sizeof *c);
1708 c->size = 50;
1709 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1710 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1711 c->buckets = (struct image **) xmalloc (size);
1712 bzero (c->buckets, size);
1713 return c;
1714 }
1715
1716
1717 /* Find an image matching SPEC in the cache, and return it. If no
1718 image is found, return NULL. */
1719 static struct image *
1720 search_image_cache (f, spec, hash)
1721 struct frame *f;
1722 Lisp_Object spec;
1723 unsigned hash;
1724 {
1725 struct image *img;
1726 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1727 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1728
1729 if (!c) return NULL;
1730
1731 /* If the image spec does not specify a background color, the cached
1732 image must have the same background color as the current frame.
1733 The foreground color must also match, for the sake of monochrome
1734 images.
1735
1736 In fact, we could ignore the foreground color matching condition
1737 for color images, or if the image spec specifies :foreground;
1738 similarly we could ignore the background color matching condition
1739 for formats that don't use transparency (such as jpeg), or if the
1740 image spec specifies :background. However, the extra memory
1741 usage is probably negligible in practice, so we don't bother. */
1742
1743 for (img = c->buckets[i]; img; img = img->next)
1744 if (img->hash == hash
1745 && !NILP (Fequal (img->spec, spec))
1746 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1747 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1748 break;
1749 return img;
1750 }
1751
1752
1753 /* Search frame F for an image with spec SPEC, and free it. */
1754
1755 static void
1756 uncache_image (f, spec)
1757 struct frame *f;
1758 Lisp_Object spec;
1759 {
1760 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1761 if (img)
1762 free_image (f, img);
1763 }
1764
1765
1766 /* Free image cache of frame F. Be aware that X frames share images
1767 caches. */
1768
1769 void
1770 free_image_cache (f)
1771 struct frame *f;
1772 {
1773 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1774 if (c)
1775 {
1776 int i;
1777
1778 /* Cache should not be referenced by any frame when freed. */
1779 xassert (c->refcount == 0);
1780
1781 for (i = 0; i < c->used; ++i)
1782 free_image (f, c->images[i]);
1783 xfree (c->images);
1784 xfree (c->buckets);
1785 xfree (c);
1786 FRAME_IMAGE_CACHE (f) = NULL;
1787 }
1788 }
1789
1790
1791 /* Clear image cache of frame F. FILTER=t means free all images.
1792 FILTER=nil means clear only images that haven't been
1793 displayed for some time.
1794 Else, only free the images which have FILTER in their `dependencies'.
1795 Should be called from time to time to reduce the number of loaded images.
1796 If image-cache-eviction-delay is non-nil, this frees images in the cache
1797 which weren't displayed for at least that many seconds. */
1798
1799 void
1800 clear_image_cache (struct frame *f, Lisp_Object filter)
1801 {
1802 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1803
1804 if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
1805 {
1806 EMACS_TIME t;
1807 unsigned long old;
1808 int i, nfreed;
1809
1810 EMACS_GET_TIME (t);
1811 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1812
1813 /* Block input so that we won't be interrupted by a SIGIO
1814 while being in an inconsistent state. */
1815 BLOCK_INPUT;
1816
1817 for (i = nfreed = 0; i < c->used; ++i)
1818 {
1819 struct image *img = c->images[i];
1820 if (img != NULL
1821 && (NILP (filter) ? img->timestamp < old
1822 : (EQ (Qt, filter)
1823 || !NILP (Fmember (filter, img->dependencies)))))
1824 {
1825 free_image (f, img);
1826 ++nfreed;
1827 }
1828 }
1829
1830 /* We may be clearing the image cache because, for example,
1831 Emacs was iconified for a longer period of time. In that
1832 case, current matrices may still contain references to
1833 images freed above. So, clear these matrices. */
1834 if (nfreed)
1835 {
1836 Lisp_Object tail, frame;
1837
1838 FOR_EACH_FRAME (tail, frame)
1839 {
1840 struct frame *f = XFRAME (frame);
1841 if (FRAME_IMAGE_CACHE (f) == c)
1842 clear_current_matrices (f);
1843 }
1844
1845 ++windows_or_buffers_changed;
1846 }
1847
1848 UNBLOCK_INPUT;
1849 }
1850 }
1851
1852 void
1853 clear_image_caches (Lisp_Object filter)
1854 {
1855 /* FIXME: We want to do
1856 * struct terminal *t;
1857 * for (t = terminal_list; t; t = t->next_terminal)
1858 * clear_image_cache (t, filter); */
1859 Lisp_Object tail, frame;
1860 FOR_EACH_FRAME (tail, frame)
1861 if (FRAME_WINDOW_P (XFRAME (frame)))
1862 clear_image_cache (XFRAME (frame), filter);
1863 }
1864
1865 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1866 0, 1, 0,
1867 doc: /* Clear the image cache.
1868 FILTER nil or a frame means clear all images in the selected frame.
1869 FILTER t means clear the image caches of all frames.
1870 Anything else, means only clear those images which refer to FILTER,
1871 which is then usually a filename. */)
1872 (filter)
1873 Lisp_Object filter;
1874 {
1875 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1876 clear_image_caches (filter);
1877 else
1878 clear_image_cache (check_x_frame (filter), Qt);
1879
1880 return Qnil;
1881 }
1882
1883
1884 DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
1885 1, 2, 0,
1886 doc: /* Refresh the image with specification SPEC on frame FRAME.
1887 If SPEC specifies an image file, the displayed image is updated with
1888 the current contents of that file.
1889 FRAME nil or omitted means use the selected frame.
1890 FRAME t means refresh the image on all frames. */)
1891 (spec, frame)
1892 Lisp_Object spec, frame;
1893 {
1894 if (!valid_image_p (spec))
1895 error ("Invalid image specification");
1896
1897 if (EQ (frame, Qt))
1898 {
1899 Lisp_Object tail;
1900 FOR_EACH_FRAME (tail, frame)
1901 {
1902 struct frame *f = XFRAME (frame);
1903 if (FRAME_WINDOW_P (f))
1904 uncache_image (f, spec);
1905 }
1906 }
1907 else
1908 uncache_image (check_x_frame (frame), spec);
1909
1910 return Qnil;
1911 }
1912
1913
1914 /* Compute masks and transform image IMG on frame F, as specified
1915 by the image's specification, */
1916
1917 static void
1918 postprocess_image (f, img)
1919 struct frame *f;
1920 struct image *img;
1921 {
1922 /* Manipulation of the image's mask. */
1923 if (img->pixmap)
1924 {
1925 Lisp_Object conversion, spec;
1926 Lisp_Object mask;
1927
1928 spec = img->spec;
1929
1930 /* `:heuristic-mask t'
1931 `:mask heuristic'
1932 means build a mask heuristically.
1933 `:heuristic-mask (R G B)'
1934 `:mask (heuristic (R G B))'
1935 means build a mask from color (R G B) in the
1936 image.
1937 `:mask nil'
1938 means remove a mask, if any. */
1939
1940 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1941 if (!NILP (mask))
1942 x_build_heuristic_mask (f, img, mask);
1943 else
1944 {
1945 int found_p;
1946
1947 mask = image_spec_value (spec, QCmask, &found_p);
1948
1949 if (EQ (mask, Qheuristic))
1950 x_build_heuristic_mask (f, img, Qt);
1951 else if (CONSP (mask)
1952 && EQ (XCAR (mask), Qheuristic))
1953 {
1954 if (CONSP (XCDR (mask)))
1955 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1956 else
1957 x_build_heuristic_mask (f, img, XCDR (mask));
1958 }
1959 else if (NILP (mask) && found_p && img->mask)
1960 {
1961 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1962 img->mask = NO_PIXMAP;
1963 }
1964 }
1965
1966
1967 /* Should we apply an image transformation algorithm? */
1968 conversion = image_spec_value (spec, QCconversion, NULL);
1969 if (EQ (conversion, Qdisabled))
1970 x_disable_image (f, img);
1971 else if (EQ (conversion, Qlaplace))
1972 x_laplace (f, img);
1973 else if (EQ (conversion, Qemboss))
1974 x_emboss (f, img);
1975 else if (CONSP (conversion)
1976 && EQ (XCAR (conversion), Qedge_detection))
1977 {
1978 Lisp_Object tem;
1979 tem = XCDR (conversion);
1980 if (CONSP (tem))
1981 x_edge_detection (f, img,
1982 Fplist_get (tem, QCmatrix),
1983 Fplist_get (tem, QCcolor_adjustment));
1984 }
1985 }
1986 }
1987
1988
1989 /* Return the id of image with Lisp specification SPEC on frame F.
1990 SPEC must be a valid Lisp image specification (see valid_image_p). */
1991
1992 int
1993 lookup_image (f, spec)
1994 struct frame *f;
1995 Lisp_Object spec;
1996 {
1997 struct image_cache *c;
1998 struct image *img;
1999 unsigned hash;
2000 struct gcpro gcpro1;
2001 EMACS_TIME now;
2002
2003 /* F must be a window-system frame, and SPEC must be a valid image
2004 specification. */
2005 xassert (FRAME_WINDOW_P (f));
2006 xassert (valid_image_p (spec));
2007
2008 c = FRAME_IMAGE_CACHE (f);
2009
2010 GCPRO1 (spec);
2011
2012 /* Look up SPEC in the hash table of the image cache. */
2013 hash = sxhash (spec, 0);
2014 img = search_image_cache (f, spec, hash);
2015 if (img && img->load_failed_p)
2016 {
2017 free_image (f, img);
2018 img = NULL;
2019 }
2020
2021 /* If not found, create a new image and cache it. */
2022 if (img == NULL)
2023 {
2024 extern Lisp_Object Qpostscript;
2025
2026 BLOCK_INPUT;
2027 img = make_image (spec, hash);
2028 cache_image (f, img);
2029 img->load_failed_p = img->type->load (f, img) == 0;
2030 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
2031 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
2032
2033 /* If we can't load the image, and we don't have a width and
2034 height, use some arbitrary width and height so that we can
2035 draw a rectangle for it. */
2036 if (img->load_failed_p)
2037 {
2038 Lisp_Object value;
2039
2040 value = image_spec_value (spec, QCwidth, NULL);
2041 img->width = (INTEGERP (value)
2042 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
2043 value = image_spec_value (spec, QCheight, NULL);
2044 img->height = (INTEGERP (value)
2045 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
2046 }
2047 else
2048 {
2049 /* Handle image type independent image attributes
2050 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2051 `:background COLOR'. */
2052 Lisp_Object ascent, margin, relief, bg;
2053
2054 ascent = image_spec_value (spec, QCascent, NULL);
2055 if (INTEGERP (ascent))
2056 img->ascent = XFASTINT (ascent);
2057 else if (EQ (ascent, Qcenter))
2058 img->ascent = CENTERED_IMAGE_ASCENT;
2059
2060 margin = image_spec_value (spec, QCmargin, NULL);
2061 if (INTEGERP (margin) && XINT (margin) >= 0)
2062 img->vmargin = img->hmargin = XFASTINT (margin);
2063 else if (CONSP (margin) && INTEGERP (XCAR (margin))
2064 && INTEGERP (XCDR (margin)))
2065 {
2066 if (XINT (XCAR (margin)) > 0)
2067 img->hmargin = XFASTINT (XCAR (margin));
2068 if (XINT (XCDR (margin)) > 0)
2069 img->vmargin = XFASTINT (XCDR (margin));
2070 }
2071
2072 relief = image_spec_value (spec, QCrelief, NULL);
2073 if (INTEGERP (relief))
2074 {
2075 img->relief = XINT (relief);
2076 img->hmargin += eabs (img->relief);
2077 img->vmargin += eabs (img->relief);
2078 }
2079
2080 if (! img->background_valid)
2081 {
2082 bg = image_spec_value (img->spec, QCbackground, NULL);
2083 if (!NILP (bg))
2084 {
2085 img->background
2086 = x_alloc_image_color (f, img, bg,
2087 FRAME_BACKGROUND_PIXEL (f));
2088 img->background_valid = 1;
2089 }
2090 }
2091
2092 /* Do image transformations and compute masks, unless we
2093 don't have the image yet. */
2094 if (!EQ (*img->type->type, Qpostscript))
2095 postprocess_image (f, img);
2096 }
2097
2098 UNBLOCK_INPUT;
2099 }
2100
2101 /* We're using IMG, so set its timestamp to `now'. */
2102 EMACS_GET_TIME (now);
2103 img->timestamp = EMACS_SECS (now);
2104
2105 UNGCPRO;
2106
2107 /* Value is the image id. */
2108 return img->id;
2109 }
2110
2111
2112 /* Cache image IMG in the image cache of frame F. */
2113
2114 static void
2115 cache_image (f, img)
2116 struct frame *f;
2117 struct image *img;
2118 {
2119 struct image_cache *c = FRAME_IMAGE_CACHE (f);
2120 int i;
2121
2122 /* Find a free slot in c->images. */
2123 for (i = 0; i < c->used; ++i)
2124 if (c->images[i] == NULL)
2125 break;
2126
2127 /* If no free slot found, maybe enlarge c->images. */
2128 if (i == c->used && c->used == c->size)
2129 {
2130 c->size *= 2;
2131 c->images = (struct image **) xrealloc (c->images,
2132 c->size * sizeof *c->images);
2133 }
2134
2135 /* Add IMG to c->images, and assign IMG an id. */
2136 c->images[i] = img;
2137 img->id = i;
2138 if (i == c->used)
2139 ++c->used;
2140
2141 /* Add IMG to the cache's hash table. */
2142 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
2143 img->next = c->buckets[i];
2144 if (img->next)
2145 img->next->prev = img;
2146 img->prev = NULL;
2147 c->buckets[i] = img;
2148 }
2149
2150
2151 /* Call FN on every image in the image cache of frame F. Used to mark
2152 Lisp Objects in the image cache. */
2153
2154 /* Mark Lisp objects in image IMG. */
2155
2156 static void
2157 mark_image (img)
2158 struct image *img;
2159 {
2160 mark_object (img->spec);
2161 mark_object (img->dependencies);
2162
2163 if (!NILP (img->data.lisp_val))
2164 mark_object (img->data.lisp_val);
2165 }
2166
2167
2168 void
2169 mark_image_cache (struct image_cache *c)
2170 {
2171 if (c)
2172 {
2173 int i;
2174 for (i = 0; i < c->used; ++i)
2175 if (c->images[i])
2176 mark_image (c->images[i]);
2177 }
2178 }
2179
2180
2181 \f
2182 /***********************************************************************
2183 X / MAC / W32 support code
2184 ***********************************************************************/
2185
2186 #ifdef HAVE_NTGUI
2187
2188 /* Macro for defining functions that will be loaded from image DLLs. */
2189 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2190
2191 /* Macro for loading those image functions from the library. */
2192 #define LOAD_IMGLIB_FN(lib,func) { \
2193 fn_##func = (void *) GetProcAddress (lib, #func); \
2194 if (!fn_##func) return 0; \
2195 }
2196
2197 /* Load a DLL implementing an image type.
2198 The `image-library-alist' variable associates a symbol,
2199 identifying an image type, to a list of possible filenames.
2200 The function returns NULL if no library could be loaded for
2201 the given image type, or if the library was previously loaded;
2202 else the handle of the DLL. */
2203 static HMODULE
2204 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
2205 {
2206 HMODULE library = NULL;
2207
2208 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2209 {
2210 Lisp_Object dlls = Fassq (type, libraries);
2211
2212 if (CONSP (dlls))
2213 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2214 {
2215 CHECK_STRING_CAR (dlls);
2216 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2217 break;
2218 }
2219 }
2220
2221 return library;
2222 }
2223
2224 #endif /* HAVE_NTGUI */
2225
2226 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2227 XImagePtr *, Pixmap *));
2228 static void x_destroy_x_image P_ ((XImagePtr));
2229 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2230
2231
2232 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2233 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2234 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2235 via xmalloc. Print error messages via image_error if an error
2236 occurs. Value is non-zero if successful.
2237
2238 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2239 should indicate the bit depth of the image. */
2240
2241 static int
2242 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2243 struct frame *f;
2244 int width, height, depth;
2245 XImagePtr *ximg;
2246 Pixmap *pixmap;
2247 {
2248 #ifdef HAVE_X_WINDOWS
2249 Display *display = FRAME_X_DISPLAY (f);
2250 Window window = FRAME_X_WINDOW (f);
2251 Screen *screen = FRAME_X_SCREEN (f);
2252
2253 xassert (interrupt_input_blocked);
2254
2255 if (depth <= 0)
2256 depth = DefaultDepthOfScreen (screen);
2257 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2258 depth, ZPixmap, 0, NULL, width, height,
2259 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2260 if (*ximg == NULL)
2261 {
2262 image_error ("Unable to allocate X image", Qnil, Qnil);
2263 return 0;
2264 }
2265
2266 /* Allocate image raster. */
2267 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2268
2269 /* Allocate a pixmap of the same size. */
2270 *pixmap = XCreatePixmap (display, window, width, height, depth);
2271 if (*pixmap == NO_PIXMAP)
2272 {
2273 x_destroy_x_image (*ximg);
2274 *ximg = NULL;
2275 image_error ("Unable to create X pixmap", Qnil, Qnil);
2276 return 0;
2277 }
2278
2279 return 1;
2280 #endif /* HAVE_X_WINDOWS */
2281
2282 #ifdef HAVE_NTGUI
2283
2284 BITMAPINFOHEADER *header;
2285 HDC hdc;
2286 int scanline_width_bits;
2287 int remainder;
2288 int palette_colors = 0;
2289
2290 if (depth == 0)
2291 depth = 24;
2292
2293 if (depth != 1 && depth != 4 && depth != 8
2294 && depth != 16 && depth != 24 && depth != 32)
2295 {
2296 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2297 return 0;
2298 }
2299
2300 scanline_width_bits = width * depth;
2301 remainder = scanline_width_bits % 32;
2302
2303 if (remainder)
2304 scanline_width_bits += 32 - remainder;
2305
2306 /* Bitmaps with a depth less than 16 need a palette. */
2307 /* BITMAPINFO structure already contains the first RGBQUAD. */
2308 if (depth < 16)
2309 palette_colors = 1 << depth - 1;
2310
2311 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2312 if (*ximg == NULL)
2313 {
2314 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2315 return 0;
2316 }
2317
2318 header = &((*ximg)->info.bmiHeader);
2319 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2320 header->biSize = sizeof (*header);
2321 header->biWidth = width;
2322 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2323 header->biPlanes = 1;
2324 header->biBitCount = depth;
2325 header->biCompression = BI_RGB;
2326 header->biClrUsed = palette_colors;
2327
2328 /* TODO: fill in palette. */
2329 if (depth == 1)
2330 {
2331 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2332 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2333 (*ximg)->info.bmiColors[0].rgbRed = 0;
2334 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2335 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2336 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2337 (*ximg)->info.bmiColors[1].rgbRed = 255;
2338 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2339 }
2340
2341 hdc = get_frame_dc (f);
2342
2343 /* Create a DIBSection and raster array for the bitmap,
2344 and store its handle in *pixmap. */
2345 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2346 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2347 /* casting avoids a GCC warning */
2348 (void **)&((*ximg)->data), NULL, 0);
2349
2350 /* Realize display palette and garbage all frames. */
2351 release_frame_dc (f, hdc);
2352
2353 if (*pixmap == NULL)
2354 {
2355 DWORD err = GetLastError ();
2356 Lisp_Object errcode;
2357 /* All system errors are < 10000, so the following is safe. */
2358 XSETINT (errcode, (int) err);
2359 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2360 x_destroy_x_image (*ximg);
2361 return 0;
2362 }
2363
2364 return 1;
2365
2366 #endif /* HAVE_NTGUI */
2367
2368 #ifdef MAC_OS
2369 Display *display = FRAME_X_DISPLAY (f);
2370 Window window = FRAME_X_WINDOW (f);
2371
2372 xassert (interrupt_input_blocked);
2373
2374 /* Allocate a pixmap of the same size. */
2375 *pixmap = XCreatePixmap (display, window, width, height, depth);
2376 if (*pixmap == NO_PIXMAP)
2377 {
2378 *ximg = NULL;
2379 image_error ("Unable to create X pixmap", Qnil, Qnil);
2380 return 0;
2381 }
2382
2383 #if !USE_MAC_IMAGE_IO
2384 LockPixels (GetGWorldPixMap (*pixmap));
2385 #endif
2386 *ximg = *pixmap;
2387 return 1;
2388
2389 #endif /* MAC_OS */
2390 }
2391
2392
2393 /* Destroy XImage XIMG. Free XIMG->data. */
2394
2395 static void
2396 x_destroy_x_image (ximg)
2397 XImagePtr ximg;
2398 {
2399 xassert (interrupt_input_blocked);
2400 if (ximg)
2401 {
2402 #ifdef HAVE_X_WINDOWS
2403 xfree (ximg->data);
2404 ximg->data = NULL;
2405 XDestroyImage (ximg);
2406 #endif /* HAVE_X_WINDOWS */
2407 #ifdef HAVE_NTGUI
2408 /* Data will be freed by DestroyObject. */
2409 ximg->data = NULL;
2410 xfree (ximg);
2411 #endif /* HAVE_NTGUI */
2412 #ifdef MAC_OS
2413 XDestroyImage (ximg);
2414 #endif /* MAC_OS */
2415 }
2416 }
2417
2418
2419 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2420 are width and height of both the image and pixmap. */
2421
2422 static void
2423 x_put_x_image (f, ximg, pixmap, width, height)
2424 struct frame *f;
2425 XImagePtr ximg;
2426 Pixmap pixmap;
2427 int width, height;
2428 {
2429 #ifdef HAVE_X_WINDOWS
2430 GC gc;
2431
2432 xassert (interrupt_input_blocked);
2433 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2434 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2435 XFreeGC (FRAME_X_DISPLAY (f), gc);
2436 #endif /* HAVE_X_WINDOWS */
2437
2438 #ifdef HAVE_NTGUI
2439 #if 0 /* I don't think this is necessary looking at where it is used. */
2440 HDC hdc = get_frame_dc (f);
2441 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2442 release_frame_dc (f, hdc);
2443 #endif
2444 #endif /* HAVE_NTGUI */
2445
2446 #ifdef MAC_OS
2447 xassert (ximg == pixmap);
2448 #endif /* MAC_OS */
2449 }
2450
2451 \f
2452 /***********************************************************************
2453 File Handling
2454 ***********************************************************************/
2455
2456 static unsigned char *slurp_file P_ ((char *, int *));
2457
2458
2459 /* Find image file FILE. Look in data-directory/images, then
2460 x-bitmap-file-path. Value is the encoded full name of the file
2461 found, or nil if not found. */
2462
2463 Lisp_Object
2464 x_find_image_file (file)
2465 Lisp_Object file;
2466 {
2467 Lisp_Object file_found, search_path;
2468 struct gcpro gcpro1, gcpro2;
2469 int fd;
2470
2471 file_found = Qnil;
2472 /* TODO I think this should use something like image-load-path
2473 instead. Unfortunately, that can contain non-string elements. */
2474 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2475 Vdata_directory),
2476 Vx_bitmap_file_path);
2477 GCPRO2 (file_found, search_path);
2478
2479 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2480 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2481
2482 if (fd == -1)
2483 file_found = Qnil;
2484 else
2485 {
2486 file_found = ENCODE_FILE (file_found);
2487 close (fd);
2488 }
2489
2490 UNGCPRO;
2491 return file_found;
2492 }
2493
2494
2495 /* Read FILE into memory. Value is a pointer to a buffer allocated
2496 with xmalloc holding FILE's contents. Value is null if an error
2497 occurred. *SIZE is set to the size of the file. */
2498
2499 static unsigned char *
2500 slurp_file (file, size)
2501 char *file;
2502 int *size;
2503 {
2504 FILE *fp = NULL;
2505 unsigned char *buf = NULL;
2506 struct stat st;
2507
2508 if (stat (file, &st) == 0
2509 && (fp = fopen (file, "rb")) != NULL
2510 && (buf = (unsigned char *) xmalloc (st.st_size),
2511 fread (buf, 1, st.st_size, fp) == st.st_size))
2512 {
2513 *size = st.st_size;
2514 fclose (fp);
2515 }
2516 else
2517 {
2518 if (fp)
2519 fclose (fp);
2520 if (buf)
2521 {
2522 xfree (buf);
2523 buf = NULL;
2524 }
2525 }
2526
2527 return buf;
2528 }
2529
2530
2531 \f
2532 #ifdef MAC_OS
2533
2534 /***********************************************************************
2535 MAC Image Load Functions
2536 ***********************************************************************/
2537
2538 #if USE_MAC_IMAGE_IO
2539 static int
2540 image_load_image_io (f, img, type)
2541 struct frame *f;
2542 struct image *img;
2543 CFStringRef type;
2544 {
2545 CFDictionaryRef options, src_props = NULL, props = NULL;
2546 CFStringRef keys[2];
2547 CFTypeRef values[2];
2548 Lisp_Object specified_file, specified_data;
2549 CGImageSourceRef source = NULL;
2550 size_t count;
2551 CGImageRef image = NULL;
2552 int loop_count = -1;
2553 double delay_time = -1.0;
2554 int width, height;
2555 XImagePtr ximg = NULL;
2556 CGContextRef context;
2557 CGRect rectangle;
2558 int has_alpha_p, gif_p;
2559
2560 gif_p = UTTypeEqual (type, kUTTypeGIF);
2561
2562 keys[0] = kCGImageSourceTypeIdentifierHint;
2563 values[0] = (CFTypeRef) type;
2564 keys[1] = kCGImageSourceShouldCache;
2565 values[1] = (CFTypeRef) kCFBooleanFalse;
2566 options = CFDictionaryCreate (NULL, (const void **) keys,
2567 (const void **) values,
2568 sizeof (keys) / sizeof (keys[0]),
2569 &kCFTypeDictionaryKeyCallBacks,
2570 &kCFTypeDictionaryValueCallBacks);
2571 if (options == NULL)
2572 {
2573 image_error ("Error creating options for image `%s'", img->spec, Qnil);
2574 return 0;
2575 }
2576
2577 /* Open the file. */
2578 specified_file = image_spec_value (img->spec, QCfile, NULL);
2579 specified_data = image_spec_value (img->spec, QCdata, NULL);
2580
2581 if (NILP (specified_data))
2582 {
2583 Lisp_Object file;
2584 CFStringRef path;
2585 CFURLRef url;
2586
2587 file = x_find_image_file (specified_file);
2588 if (!STRINGP (file))
2589 {
2590 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2591 return 0;
2592 }
2593 path = cfstring_create_with_utf8_cstring (SDATA (file));
2594 if (path)
2595 {
2596 url = CFURLCreateWithFileSystemPath (NULL, path,
2597 kCFURLPOSIXPathStyle, 0);
2598 CFRelease (path);
2599 if (url)
2600 {
2601 source = CGImageSourceCreateWithURL (url, NULL);
2602 CFRelease (url);
2603 }
2604 }
2605 }
2606 else
2607 {
2608 CFDataRef data = CFDataCreate (NULL, SDATA (specified_data),
2609 SBYTES (specified_data));
2610
2611 if (data)
2612 {
2613 source = CGImageSourceCreateWithData (data, options);
2614 CFRelease (data);
2615 }
2616 }
2617 CFRelease (options);
2618
2619 if (source)
2620 {
2621 CFStringRef real_type = CGImageSourceGetType (source);
2622
2623 if (real_type && UTTypeEqual (type, real_type))
2624 src_props = CGImageSourceCopyProperties (source, NULL);
2625 if (src_props)
2626 {
2627 EMACS_INT ino = 0;
2628
2629 count = CGImageSourceGetCount (source);
2630 if (gif_p)
2631 {
2632 Lisp_Object image = image_spec_value (img->spec, QCindex, NULL);
2633
2634 if (INTEGERP (image))
2635 ino = XFASTINT (image);
2636 }
2637 if (ino >= 0 && ino < count)
2638 {
2639 props = CGImageSourceCopyPropertiesAtIndex (source, ino, NULL);
2640 if (props)
2641 image = CGImageSourceCreateImageAtIndex (source, ino, NULL);
2642 }
2643 }
2644 CFRelease (source);
2645 }
2646
2647 if (image == NULL)
2648 {
2649 if (src_props)
2650 CFRelease (src_props);
2651 if (props)
2652 CFRelease (props);
2653 image_error ("Error reading image `%s'", img->spec, Qnil);
2654 return 0;
2655 }
2656 else
2657 {
2658 CFBooleanRef boolean;
2659
2660 if (CFDictionaryGetValueIfPresent (props, kCGImagePropertyHasAlpha,
2661 (const void **) &boolean))
2662 has_alpha_p = CFBooleanGetValue (boolean);
2663 if (gif_p)
2664 {
2665 CFDictionaryRef dict;
2666 CFNumberRef number;
2667
2668 dict = CFDictionaryGetValue (src_props,
2669 kCGImagePropertyGIFDictionary);
2670 if (dict
2671 && CFDictionaryGetValueIfPresent (dict,
2672 kCGImagePropertyGIFLoopCount,
2673 (const void **) &number))
2674 CFNumberGetValue (number, kCFNumberIntType, &loop_count);
2675
2676 dict = CFDictionaryGetValue (props, kCGImagePropertyGIFDictionary);
2677 if (dict
2678 && CFDictionaryGetValueIfPresent (dict,
2679 kCGImagePropertyGIFDelayTime,
2680 (const void **) &number))
2681 CFNumberGetValue (number, kCFNumberDoubleType, &delay_time);
2682 }
2683 CFRelease (src_props);
2684 CFRelease (props);
2685 }
2686
2687 width = img->width = CGImageGetWidth (image);
2688 height = img->height = CGImageGetHeight (image);
2689
2690 if (!check_image_size (f, width, height))
2691 {
2692 CGImageRelease (image);
2693 image_error ("Invalid image size", Qnil, Qnil);
2694 return 0;
2695 }
2696
2697 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2698 {
2699 CGImageRelease (image);
2700 image_error ("Out of memory (%s)", img->spec, Qnil);
2701 return 0;
2702 }
2703 rectangle = CGRectMake (0, 0, width, height);
2704
2705 context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
2706 ximg->bytes_per_line,
2707 mac_cg_color_space_rgb,
2708 kCGImageAlphaNoneSkipFirst
2709 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
2710 | kCGBitmapByteOrder32Host
2711 #endif
2712 );
2713 if (has_alpha_p)
2714 {
2715 Lisp_Object specified_bg;
2716 XColor color;
2717
2718 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2719 if (!STRINGP (specified_bg)
2720 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2721 {
2722 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2723 color.red = RED16_FROM_ULONG (color.pixel);
2724 color.green = GREEN16_FROM_ULONG (color.pixel);
2725 color.blue = BLUE16_FROM_ULONG (color.pixel);
2726 }
2727 CGContextSetRGBFillColor (context, color.red / 65535.0,
2728 color.green / 65535.0,
2729 color.blue / 65535.0, 1.0);
2730 CGContextFillRect (context, rectangle);
2731 }
2732 CGContextDrawImage (context, rectangle, image);
2733 CGContextRelease (context);
2734 CGImageRelease (image);
2735
2736 /* Save GIF image extension data for `image-extension-data'.
2737 Format is (count IMAGES
2738 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2739 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2740 if (gif_p)
2741 {
2742 img->data.lisp_val = Qnil;
2743 if (delay_time >= 0)
2744 {
2745 Lisp_Object gce = make_uninit_string (4);
2746 int centisec = delay_time * 100.0 + 0.5;
2747
2748 /* Fill the delay time field. */
2749 SSET (gce, 1, centisec & 0xff);
2750 SSET (gce, 2, (centisec >> 8) & 0xff);
2751 /* We don't know about other fields. */
2752 SSET (gce, 0, 0);
2753 SSET (gce, 3, 0);
2754 img->data.lisp_val = Fcons (make_number (0xf9),
2755 Fcons (gce,
2756 img->data.lisp_val));
2757 }
2758 if (loop_count >= 0)
2759 {
2760 Lisp_Object data_sub_block = make_uninit_string (3);
2761
2762 SSET (data_sub_block, 0, 0x01);
2763 SSET (data_sub_block, 1, loop_count & 0xff);
2764 SSET (data_sub_block, 2, (loop_count >> 8) & 0xff);
2765 img->data.lisp_val = Fcons (make_number (0),
2766 Fcons (data_sub_block,
2767 img->data.lisp_val));
2768 img->data.lisp_val = Fcons (make_number (0xff),
2769 Fcons (build_string ("NETSCAPE2.0"),
2770 img->data.lisp_val));
2771 }
2772 if (count > 1)
2773 img->data.lisp_val = Fcons (Qcount,
2774 Fcons (make_number (count),
2775 img->data.lisp_val));
2776 }
2777
2778 /* Maybe fill in the background field while we have ximg handy. */
2779 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2780 IMAGE_BACKGROUND (img, f, ximg);
2781
2782 /* Put the image into the pixmap. */
2783 x_put_x_image (f, ximg, img->pixmap, width, height);
2784 x_destroy_x_image (ximg);
2785 return 1;
2786 }
2787 #else /* !USE_MAC_IMAGE_IO */
2788 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2789 OSType));
2790 #ifdef MAC_OSX
2791 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2792 #endif
2793
2794 static OSErr
2795 find_image_fsspec (specified_file, file, fss)
2796 Lisp_Object specified_file, *file;
2797 FSSpec *fss;
2798 {
2799 OSErr err;
2800 AEDesc desc;
2801
2802 *file = x_find_image_file (specified_file);
2803 if (!STRINGP (*file))
2804 return fnfErr; /* file or directory not found;
2805 incomplete pathname */
2806 /* Try to open the image file. */
2807 err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
2808 SBYTES (*file), typeFSS, &desc);
2809 if (err == noErr)
2810 {
2811 #if TARGET_API_MAC_CARBON
2812 err = AEGetDescData (&desc, fss, sizeof (FSSpec));
2813 #else
2814 *fss = *(FSSpec *)(*(desc.dataHandle));
2815 #endif
2816 AEDisposeDesc (&desc);
2817 }
2818 return err;
2819 }
2820
2821 static int
2822 image_load_qt_1 (f, img, type, fss, dh)
2823 struct frame *f;
2824 struct image *img;
2825 OSType type;
2826 const FSSpec *fss;
2827 Handle dh;
2828 {
2829 ComponentResult err;
2830 GraphicsImportComponent gi;
2831 Rect rect;
2832 int width, height;
2833 ImageDescriptionHandle desc_handle;
2834 short draw_all_pixels;
2835 Lisp_Object specified_bg;
2836 XColor color;
2837 XImagePtr ximg;
2838 RGBColor bg_color;
2839
2840 err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
2841 if (err != noErr)
2842 {
2843 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2844 return 0;
2845 }
2846 if (dh == NULL)
2847 {
2848 /* read from file system spec */
2849 err = GraphicsImportSetDataFile (gi, fss);
2850 if (err != noErr)
2851 {
2852 image_error ("Cannot set fsspec to graphics importer for '%s'",
2853 img->spec, Qnil);
2854 goto error;
2855 }
2856 }
2857 else
2858 {
2859 /* read from data handle */
2860 err = GraphicsImportSetDataHandle (gi, dh);
2861 if (err != noErr)
2862 {
2863 image_error ("Cannot set data handle to graphics importer for `%s'",
2864 img->spec, Qnil);
2865 goto error;
2866 }
2867 }
2868 err = GraphicsImportGetImageDescription (gi, &desc_handle);
2869 if (err != noErr || desc_handle == NULL)
2870 {
2871 image_error ("Error reading `%s'", img->spec, Qnil);
2872 goto error;
2873 }
2874 width = img->width = (*desc_handle)->width;
2875 height = img->height = (*desc_handle)->height;
2876 DisposeHandle ((Handle)desc_handle);
2877
2878 if (!check_image_size (f, width, height))
2879 {
2880 image_error ("Invalid image size", Qnil, Qnil);
2881 goto error;
2882 }
2883
2884 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
2885 #if 0
2886 /* Don't check the error code here. It may have an undocumented
2887 value -32766. */
2888 if (err != noErr)
2889 {
2890 image_error ("Error reading `%s'", img->spec, Qnil);
2891 goto error;
2892 }
2893 #endif
2894 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2895 {
2896 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2897 if (!STRINGP (specified_bg) ||
2898 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2899 {
2900 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2901 color.red = RED16_FROM_ULONG (color.pixel);
2902 color.green = GREEN16_FROM_ULONG (color.pixel);
2903 color.blue = BLUE16_FROM_ULONG (color.pixel);
2904 }
2905 }
2906
2907 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2908 goto error;
2909 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2910 {
2911 CGrafPtr old_port;
2912 GDHandle old_gdh;
2913
2914 GetGWorld (&old_port, &old_gdh);
2915 SetGWorld (ximg, NULL);
2916 bg_color.red = color.red;
2917 bg_color.green = color.green;
2918 bg_color.blue = color.blue;
2919 RGBBackColor (&bg_color);
2920 #if TARGET_API_MAC_CARBON
2921 GetPortBounds (ximg, &rect);
2922 EraseRect (&rect);
2923 #else
2924 EraseRect (&(ximg->portRect));
2925 #endif
2926 SetGWorld (old_port, old_gdh);
2927 }
2928 GraphicsImportSetGWorld (gi, ximg, NULL);
2929 GraphicsImportDraw (gi);
2930 CloseComponent (gi);
2931
2932 /* Maybe fill in the background field while we have ximg handy. */
2933 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2934 IMAGE_BACKGROUND (img, f, ximg);
2935
2936 /* Put the image into the pixmap. */
2937 x_put_x_image (f, ximg, img->pixmap, width, height);
2938 x_destroy_x_image (ximg);
2939 return 1;
2940
2941 error:
2942 CloseComponent (gi);
2943 return 0;
2944 }
2945
2946
2947 /* Load an image using the QuickTime Graphics Importer.
2948 Note: The alpha channel does not work for PNG images. */
2949 static int
2950 image_load_quicktime (f, img, type)
2951 struct frame *f;
2952 struct image *img;
2953 OSType type;
2954 {
2955 Lisp_Object specified_file;
2956 Lisp_Object specified_data;
2957 OSErr err;
2958
2959 specified_file = image_spec_value (img->spec, QCfile, NULL);
2960 specified_data = image_spec_value (img->spec, QCdata, NULL);
2961
2962 if (NILP (specified_data))
2963 {
2964 /* Read from a file */
2965 Lisp_Object file;
2966 FSSpec fss;
2967
2968 err = find_image_fsspec (specified_file, &file, &fss);
2969 if (err != noErr)
2970 {
2971 if (err == fnfErr)
2972 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2973 else
2974 image_error ("Cannot open `%s'", file, Qnil);
2975 return 0;
2976 }
2977 return image_load_qt_1 (f, img, type, &fss, NULL);
2978 }
2979 else
2980 {
2981 /* Memory source! */
2982 int success_p;
2983 Handle dh;
2984
2985 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
2986 if (err != noErr)
2987 {
2988 image_error ("Cannot allocate data handle for `%s'",
2989 img->spec, Qnil);
2990 return 0;
2991 }
2992 success_p = image_load_qt_1 (f, img, type, NULL, dh);
2993 DisposeHandle (dh);
2994 return success_p;
2995 }
2996 }
2997
2998
2999 #ifdef MAC_OSX
3000 static int
3001 image_load_quartz2d (f, img, png_p)
3002 struct frame *f;
3003 struct image *img;
3004 int png_p;
3005 {
3006 Lisp_Object file, specified_file;
3007 Lisp_Object specified_data, specified_bg;
3008 struct gcpro gcpro1;
3009 CGDataProviderRef source;
3010 CGImageRef image;
3011 int width, height;
3012 XColor color;
3013 XImagePtr ximg = NULL;
3014 CGContextRef context;
3015 CGRect rectangle;
3016
3017 /* Open the file. */
3018 specified_file = image_spec_value (img->spec, QCfile, NULL);
3019 specified_data = image_spec_value (img->spec, QCdata, NULL);
3020
3021 file = Qnil;
3022 GCPRO1 (file);
3023
3024 if (NILP (specified_data))
3025 {
3026 CFStringRef path;
3027 CFURLRef url;
3028
3029 file = x_find_image_file (specified_file);
3030 if (!STRINGP (file))
3031 {
3032 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3033 UNGCPRO;
3034 return 0;
3035 }
3036 path = cfstring_create_with_utf8_cstring (SDATA (file));
3037 url = CFURLCreateWithFileSystemPath (NULL, path,
3038 kCFURLPOSIXPathStyle, 0);
3039 CFRelease (path);
3040 source = CGDataProviderCreateWithURL (url);
3041 CFRelease (url);
3042 }
3043 else
3044 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
3045 SBYTES (specified_data), NULL);
3046
3047 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3048 if (png_p)
3049 image = CGImageCreateWithPNGDataProvider (source, NULL, false,
3050 kCGRenderingIntentDefault);
3051 else
3052 #endif
3053 image = CGImageCreateWithJPEGDataProvider (source, NULL, false,
3054 kCGRenderingIntentDefault);
3055
3056 CGDataProviderRelease (source);
3057 if (image == NULL)
3058 {
3059 UNGCPRO;
3060 image_error ("Error reading image `%s'", img->spec, Qnil);
3061 return 0;
3062 }
3063 width = img->width = CGImageGetWidth (image);
3064 height = img->height = CGImageGetHeight (image);
3065
3066 if (!check_image_size (f, width, height))
3067 {
3068 CGImageRelease (image);
3069 UNGCPRO;
3070 image_error ("Invalid image size", Qnil, Qnil);
3071 return 0;
3072 }
3073
3074 if (png_p)
3075 {
3076 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
3077 if (!STRINGP (specified_bg) ||
3078 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
3079 {
3080 color.pixel = FRAME_BACKGROUND_PIXEL (f);
3081 color.red = RED16_FROM_ULONG (color.pixel);
3082 color.green = GREEN16_FROM_ULONG (color.pixel);
3083 color.blue = BLUE16_FROM_ULONG (color.pixel);
3084 }
3085 }
3086
3087 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
3088 {
3089 CGImageRelease (image);
3090 UNGCPRO;
3091 return 0;
3092 }
3093 rectangle = CGRectMake (0, 0, width, height);
3094 QDBeginCGContext (ximg, &context);
3095 if (png_p)
3096 {
3097 CGContextSetRGBFillColor (context, color.red / 65535.0,
3098 color.green / 65535.0,
3099 color.blue / 65535.0, 1.0);
3100 CGContextFillRect (context, rectangle);
3101 }
3102 CGContextDrawImage (context, rectangle, image);
3103 QDEndCGContext (ximg, &context);
3104 CGImageRelease (image);
3105
3106 /* Maybe fill in the background field while we have ximg handy. */
3107 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3108 IMAGE_BACKGROUND (img, f, ximg);
3109
3110 /* Put the image into the pixmap. */
3111 x_put_x_image (f, ximg, img->pixmap, width, height);
3112 x_destroy_x_image (ximg);
3113 UNGCPRO;
3114 return 1;
3115 }
3116 #endif
3117 #endif /* !USE_MAC_IMAGE_IO */
3118
3119 #endif /* MAC_OS */
3120
3121 \f
3122 /***********************************************************************
3123 XBM images
3124 ***********************************************************************/
3125
3126 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
3127 static int xbm_load P_ ((struct frame *f, struct image *img));
3128 static int xbm_load_image P_ ((struct frame *f, struct image *img,
3129 unsigned char *, unsigned char *));
3130 static int xbm_image_p P_ ((Lisp_Object object));
3131 static int xbm_read_bitmap_data P_ ((struct frame *f,
3132 unsigned char *, unsigned char *,
3133 int *, int *, unsigned char **));
3134 static int xbm_file_p P_ ((Lisp_Object));
3135
3136
3137 /* Indices of image specification fields in xbm_format, below. */
3138
3139 enum xbm_keyword_index
3140 {
3141 XBM_TYPE,
3142 XBM_FILE,
3143 XBM_WIDTH,
3144 XBM_HEIGHT,
3145 XBM_DATA,
3146 XBM_FOREGROUND,
3147 XBM_BACKGROUND,
3148 XBM_ASCENT,
3149 XBM_MARGIN,
3150 XBM_RELIEF,
3151 XBM_ALGORITHM,
3152 XBM_HEURISTIC_MASK,
3153 XBM_MASK,
3154 XBM_LAST
3155 };
3156
3157 /* Vector of image_keyword structures describing the format
3158 of valid XBM image specifications. */
3159
3160 static struct image_keyword xbm_format[XBM_LAST] =
3161 {
3162 {":type", IMAGE_SYMBOL_VALUE, 1},
3163 {":file", IMAGE_STRING_VALUE, 0},
3164 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3165 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3166 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3167 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
3168 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
3169 {":ascent", IMAGE_ASCENT_VALUE, 0},
3170 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3171 {":relief", IMAGE_INTEGER_VALUE, 0},
3172 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3173 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3174 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
3175 };
3176
3177 /* Structure describing the image type XBM. */
3178
3179 static struct image_type xbm_type =
3180 {
3181 &Qxbm,
3182 xbm_image_p,
3183 xbm_load,
3184 x_clear_image,
3185 NULL
3186 };
3187
3188 /* Tokens returned from xbm_scan. */
3189
3190 enum xbm_token
3191 {
3192 XBM_TK_IDENT = 256,
3193 XBM_TK_NUMBER
3194 };
3195
3196
3197 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3198 A valid specification is a list starting with the symbol `image'
3199 The rest of the list is a property list which must contain an
3200 entry `:type xbm..
3201
3202 If the specification specifies a file to load, it must contain
3203 an entry `:file FILENAME' where FILENAME is a string.
3204
3205 If the specification is for a bitmap loaded from memory it must
3206 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3207 WIDTH and HEIGHT are integers > 0. DATA may be:
3208
3209 1. a string large enough to hold the bitmap data, i.e. it must
3210 have a size >= (WIDTH + 7) / 8 * HEIGHT
3211
3212 2. a bool-vector of size >= WIDTH * HEIGHT
3213
3214 3. a vector of strings or bool-vectors, one for each line of the
3215 bitmap.
3216
3217 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3218 may not be specified in this case because they are defined in the
3219 XBM file.
3220
3221 Both the file and data forms may contain the additional entries
3222 `:background COLOR' and `:foreground COLOR'. If not present,
3223 foreground and background of the frame on which the image is
3224 displayed is used. */
3225
3226 static int
3227 xbm_image_p (object)
3228 Lisp_Object object;
3229 {
3230 struct image_keyword kw[XBM_LAST];
3231
3232 bcopy (xbm_format, kw, sizeof kw);
3233 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
3234 return 0;
3235
3236 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
3237
3238 if (kw[XBM_FILE].count)
3239 {
3240 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
3241 return 0;
3242 }
3243 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
3244 {
3245 /* In-memory XBM file. */
3246 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
3247 return 0;
3248 }
3249 else
3250 {
3251 Lisp_Object data;
3252 int width, height;
3253
3254 /* Entries for `:width', `:height' and `:data' must be present. */
3255 if (!kw[XBM_WIDTH].count
3256 || !kw[XBM_HEIGHT].count
3257 || !kw[XBM_DATA].count)
3258 return 0;
3259
3260 data = kw[XBM_DATA].value;
3261 width = XFASTINT (kw[XBM_WIDTH].value);
3262 height = XFASTINT (kw[XBM_HEIGHT].value);
3263
3264 /* Check type of data, and width and height against contents of
3265 data. */
3266 if (VECTORP (data))
3267 {
3268 int i;
3269
3270 /* Number of elements of the vector must be >= height. */
3271 if (XVECTOR (data)->size < height)
3272 return 0;
3273
3274 /* Each string or bool-vector in data must be large enough
3275 for one line of the image. */
3276 for (i = 0; i < height; ++i)
3277 {
3278 Lisp_Object elt = XVECTOR (data)->contents[i];
3279
3280 if (STRINGP (elt))
3281 {
3282 if (SCHARS (elt)
3283 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
3284 return 0;
3285 }
3286 else if (BOOL_VECTOR_P (elt))
3287 {
3288 if (XBOOL_VECTOR (elt)->size < width)
3289 return 0;
3290 }
3291 else
3292 return 0;
3293 }
3294 }
3295 else if (STRINGP (data))
3296 {
3297 if (SCHARS (data)
3298 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
3299 return 0;
3300 }
3301 else if (BOOL_VECTOR_P (data))
3302 {
3303 if (XBOOL_VECTOR (data)->size < width * height)
3304 return 0;
3305 }
3306 else
3307 return 0;
3308 }
3309
3310 return 1;
3311 }
3312
3313
3314 /* Scan a bitmap file. FP is the stream to read from. Value is
3315 either an enumerator from enum xbm_token, or a character for a
3316 single-character token, or 0 at end of file. If scanning an
3317 identifier, store the lexeme of the identifier in SVAL. If
3318 scanning a number, store its value in *IVAL. */
3319
3320 static int
3321 xbm_scan (s, end, sval, ival)
3322 unsigned char **s, *end;
3323 char *sval;
3324 int *ival;
3325 {
3326 unsigned int c;
3327
3328 loop:
3329
3330 /* Skip white space. */
3331 while (*s < end && (c = *(*s)++, isspace (c)))
3332 ;
3333
3334 if (*s >= end)
3335 c = 0;
3336 else if (isdigit (c))
3337 {
3338 int value = 0, digit;
3339
3340 if (c == '0' && *s < end)
3341 {
3342 c = *(*s)++;
3343 if (c == 'x' || c == 'X')
3344 {
3345 while (*s < end)
3346 {
3347 c = *(*s)++;
3348 if (isdigit (c))
3349 digit = c - '0';
3350 else if (c >= 'a' && c <= 'f')
3351 digit = c - 'a' + 10;
3352 else if (c >= 'A' && c <= 'F')
3353 digit = c - 'A' + 10;
3354 else
3355 break;
3356 value = 16 * value + digit;
3357 }
3358 }
3359 else if (isdigit (c))
3360 {
3361 value = c - '0';
3362 while (*s < end
3363 && (c = *(*s)++, isdigit (c)))
3364 value = 8 * value + c - '0';
3365 }
3366 }
3367 else
3368 {
3369 value = c - '0';
3370 while (*s < end
3371 && (c = *(*s)++, isdigit (c)))
3372 value = 10 * value + c - '0';
3373 }
3374
3375 if (*s < end)
3376 *s = *s - 1;
3377 *ival = value;
3378 c = XBM_TK_NUMBER;
3379 }
3380 else if (isalpha (c) || c == '_')
3381 {
3382 *sval++ = c;
3383 while (*s < end
3384 && (c = *(*s)++, (isalnum (c) || c == '_')))
3385 *sval++ = c;
3386 *sval = 0;
3387 if (*s < end)
3388 *s = *s - 1;
3389 c = XBM_TK_IDENT;
3390 }
3391 else if (c == '/' && **s == '*')
3392 {
3393 /* C-style comment. */
3394 ++*s;
3395 while (**s && (**s != '*' || *(*s + 1) != '/'))
3396 ++*s;
3397 if (**s)
3398 {
3399 *s += 2;
3400 goto loop;
3401 }
3402 }
3403
3404 return c;
3405 }
3406
3407 #ifdef HAVE_NTGUI
3408
3409 /* Create a Windows bitmap from X bitmap data. */
3410 static HBITMAP
3411 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
3412 {
3413 static unsigned char swap_nibble[16]
3414 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3415 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3416 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3417 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3418 int i, j, w1, w2;
3419 unsigned char *bits, *p;
3420 HBITMAP bmp;
3421
3422 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
3423 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3424 bits = (unsigned char *) alloca (height * w2);
3425 bzero (bits, height * w2);
3426 for (i = 0; i < height; i++)
3427 {
3428 p = bits + i*w2;
3429 for (j = 0; j < w1; j++)
3430 {
3431 /* Bitswap XBM bytes to match how Windows does things. */
3432 unsigned char c = *data++;
3433 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
3434 | (swap_nibble[(c>>4) & 0xf]));
3435 }
3436 }
3437 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
3438
3439 return bmp;
3440 }
3441
3442 static void
3443 convert_mono_to_color_image (f, img, foreground, background)
3444 struct frame *f;
3445 struct image *img;
3446 COLORREF foreground, background;
3447 {
3448 HDC hdc, old_img_dc, new_img_dc;
3449 HGDIOBJ old_prev, new_prev;
3450 HBITMAP new_pixmap;
3451
3452 hdc = get_frame_dc (f);
3453 old_img_dc = CreateCompatibleDC (hdc);
3454 new_img_dc = CreateCompatibleDC (hdc);
3455 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
3456 release_frame_dc (f, hdc);
3457 old_prev = SelectObject (old_img_dc, img->pixmap);
3458 new_prev = SelectObject (new_img_dc, new_pixmap);
3459 /* Windows convention for mono bitmaps is black = background,
3460 white = foreground. */
3461 SetTextColor (new_img_dc, background);
3462 SetBkColor (new_img_dc, foreground);
3463
3464 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
3465 0, 0, SRCCOPY);
3466
3467 SelectObject (old_img_dc, old_prev);
3468 SelectObject (new_img_dc, new_prev);
3469 DeleteDC (old_img_dc);
3470 DeleteDC (new_img_dc);
3471 DeleteObject (img->pixmap);
3472 if (new_pixmap == 0)
3473 fprintf (stderr, "Failed to convert image to color.\n");
3474 else
3475 img->pixmap = new_pixmap;
3476 }
3477
3478 #define XBM_BIT_SHUFFLE(b) (~(b))
3479
3480 #else
3481
3482 #define XBM_BIT_SHUFFLE(b) (b)
3483
3484 #endif /* HAVE_NTGUI */
3485
3486
3487 static void
3488 Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
3489 struct frame *f;
3490 struct image *img;
3491 char *data;
3492 RGB_PIXEL_COLOR fg, bg;
3493 int non_default_colors;
3494 {
3495 #ifdef HAVE_NTGUI
3496 img->pixmap
3497 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
3498
3499 /* If colors were specified, transfer the bitmap to a color one. */
3500 if (non_default_colors)
3501 convert_mono_to_color_image (f, img, fg, bg);
3502 #else
3503 img->pixmap
3504 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
3505 FRAME_X_WINDOW (f),
3506 data,
3507 img->width, img->height,
3508 fg, bg,
3509 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3510 #endif /* HAVE_NTGUI */
3511 }
3512
3513
3514
3515 /* Replacement for XReadBitmapFileData which isn't available under old
3516 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3517 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3518 the image. Return in *DATA the bitmap data allocated with xmalloc.
3519 Value is non-zero if successful. DATA null means just test if
3520 CONTENTS looks like an in-memory XBM file. */
3521
3522 static int
3523 xbm_read_bitmap_data (f, contents, end, width, height, data)
3524 struct frame *f;
3525 unsigned char *contents, *end;
3526 int *width, *height;
3527 unsigned char **data;
3528 {
3529 unsigned char *s = contents;
3530 char buffer[BUFSIZ];
3531 int padding_p = 0;
3532 int v10 = 0;
3533 int bytes_per_line, i, nbytes;
3534 unsigned char *p;
3535 int value;
3536 int LA1;
3537
3538 #define match() \
3539 LA1 = xbm_scan (&s, end, buffer, &value)
3540
3541 #define expect(TOKEN) \
3542 if (LA1 != (TOKEN)) \
3543 goto failure; \
3544 else \
3545 match ()
3546
3547 #define expect_ident(IDENT) \
3548 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3549 match (); \
3550 else \
3551 goto failure
3552
3553 *width = *height = -1;
3554 if (data)
3555 *data = NULL;
3556 LA1 = xbm_scan (&s, end, buffer, &value);
3557
3558 /* Parse defines for width, height and hot-spots. */
3559 while (LA1 == '#')
3560 {
3561 match ();
3562 expect_ident ("define");
3563 expect (XBM_TK_IDENT);
3564
3565 if (LA1 == XBM_TK_NUMBER)
3566 {
3567 char *p = strrchr (buffer, '_');
3568 p = p ? p + 1 : buffer;
3569 if (strcmp (p, "width") == 0)
3570 *width = value;
3571 else if (strcmp (p, "height") == 0)
3572 *height = value;
3573 }
3574 expect (XBM_TK_NUMBER);
3575 }
3576
3577 if (!check_image_size (f, *width, *height))
3578 goto failure;
3579 else if (data == NULL)
3580 goto success;
3581
3582 /* Parse bits. Must start with `static'. */
3583 expect_ident ("static");
3584 if (LA1 == XBM_TK_IDENT)
3585 {
3586 if (strcmp (buffer, "unsigned") == 0)
3587 {
3588 match ();
3589 expect_ident ("char");
3590 }
3591 else if (strcmp (buffer, "short") == 0)
3592 {
3593 match ();
3594 v10 = 1;
3595 if (*width % 16 && *width % 16 < 9)
3596 padding_p = 1;
3597 }
3598 else if (strcmp (buffer, "char") == 0)
3599 match ();
3600 else
3601 goto failure;
3602 }
3603 else
3604 goto failure;
3605
3606 expect (XBM_TK_IDENT);
3607 expect ('[');
3608 expect (']');
3609 expect ('=');
3610 expect ('{');
3611
3612 bytes_per_line = (*width + 7) / 8 + padding_p;
3613 nbytes = bytes_per_line * *height;
3614 p = *data = (unsigned char *) xmalloc (nbytes);
3615
3616 if (v10)
3617 {
3618 for (i = 0; i < nbytes; i += 2)
3619 {
3620 int val = value;
3621 expect (XBM_TK_NUMBER);
3622
3623 *p++ = XBM_BIT_SHUFFLE (val);
3624 if (!padding_p || ((i + 2) % bytes_per_line))
3625 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3626
3627 if (LA1 == ',' || LA1 == '}')
3628 match ();
3629 else
3630 goto failure;
3631 }
3632 }
3633 else
3634 {
3635 for (i = 0; i < nbytes; ++i)
3636 {
3637 int val = value;
3638 expect (XBM_TK_NUMBER);
3639
3640 *p++ = XBM_BIT_SHUFFLE (val);
3641
3642 if (LA1 == ',' || LA1 == '}')
3643 match ();
3644 else
3645 goto failure;
3646 }
3647 }
3648
3649 success:
3650 return 1;
3651
3652 failure:
3653
3654 if (data && *data)
3655 {
3656 xfree (*data);
3657 *data = NULL;
3658 }
3659 return 0;
3660
3661 #undef match
3662 #undef expect
3663 #undef expect_ident
3664 }
3665
3666
3667 /* Load XBM image IMG which will be displayed on frame F from buffer
3668 CONTENTS. END is the end of the buffer. Value is non-zero if
3669 successful. */
3670
3671 static int
3672 xbm_load_image (f, img, contents, end)
3673 struct frame *f;
3674 struct image *img;
3675 unsigned char *contents, *end;
3676 {
3677 int rc;
3678 unsigned char *data;
3679 int success_p = 0;
3680
3681 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3682 if (rc)
3683 {
3684 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3685 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3686 int non_default_colors = 0;
3687 Lisp_Object value;
3688
3689 xassert (img->width > 0 && img->height > 0);
3690
3691 /* Get foreground and background colors, maybe allocate colors. */
3692 value = image_spec_value (img->spec, QCforeground, NULL);
3693 if (!NILP (value))
3694 {
3695 foreground = x_alloc_image_color (f, img, value, foreground);
3696 non_default_colors = 1;
3697 }
3698 value = image_spec_value (img->spec, QCbackground, NULL);
3699 if (!NILP (value))
3700 {
3701 background = x_alloc_image_color (f, img, value, background);
3702 img->background = background;
3703 img->background_valid = 1;
3704 non_default_colors = 1;
3705 }
3706
3707 Create_Pixmap_From_Bitmap_Data (f, img, data,
3708 foreground, background,
3709 non_default_colors);
3710 xfree (data);
3711
3712 if (img->pixmap == NO_PIXMAP)
3713 {
3714 x_clear_image (f, img);
3715 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3716 }
3717 else
3718 success_p = 1;
3719 }
3720 else
3721 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3722
3723 return success_p;
3724 }
3725
3726
3727 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3728
3729 static int
3730 xbm_file_p (data)
3731 Lisp_Object data;
3732 {
3733 int w, h;
3734 return (STRINGP (data)
3735 && xbm_read_bitmap_data (NULL, SDATA (data),
3736 (SDATA (data)
3737 + SBYTES (data)),
3738 &w, &h, NULL));
3739 }
3740
3741
3742 /* Fill image IMG which is used on frame F with pixmap data. Value is
3743 non-zero if successful. */
3744
3745 static int
3746 xbm_load (f, img)
3747 struct frame *f;
3748 struct image *img;
3749 {
3750 int success_p = 0;
3751 Lisp_Object file_name;
3752
3753 xassert (xbm_image_p (img->spec));
3754
3755 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3756 file_name = image_spec_value (img->spec, QCfile, NULL);
3757 if (STRINGP (file_name))
3758 {
3759 Lisp_Object file;
3760 unsigned char *contents;
3761 int size;
3762 struct gcpro gcpro1;
3763
3764 file = x_find_image_file (file_name);
3765 GCPRO1 (file);
3766 if (!STRINGP (file))
3767 {
3768 image_error ("Cannot find image file `%s'", file_name, Qnil);
3769 UNGCPRO;
3770 return 0;
3771 }
3772
3773 contents = slurp_file (SDATA (file), &size);
3774 if (contents == NULL)
3775 {
3776 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3777 UNGCPRO;
3778 return 0;
3779 }
3780
3781 success_p = xbm_load_image (f, img, contents, contents + size);
3782 UNGCPRO;
3783 }
3784 else
3785 {
3786 struct image_keyword fmt[XBM_LAST];
3787 Lisp_Object data;
3788 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3789 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3790 int non_default_colors = 0;
3791 char *bits;
3792 int parsed_p;
3793 int in_memory_file_p = 0;
3794
3795 /* See if data looks like an in-memory XBM file. */
3796 data = image_spec_value (img->spec, QCdata, NULL);
3797 in_memory_file_p = xbm_file_p (data);
3798
3799 /* Parse the image specification. */
3800 bcopy (xbm_format, fmt, sizeof fmt);
3801 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3802 xassert (parsed_p);
3803
3804 /* Get specified width, and height. */
3805 if (!in_memory_file_p)
3806 {
3807 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3808 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3809 xassert (img->width > 0 && img->height > 0);
3810 }
3811
3812 /* Get foreground and background colors, maybe allocate colors. */
3813 if (fmt[XBM_FOREGROUND].count
3814 && STRINGP (fmt[XBM_FOREGROUND].value))
3815 {
3816 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3817 foreground);
3818 non_default_colors = 1;
3819 }
3820
3821 if (fmt[XBM_BACKGROUND].count
3822 && STRINGP (fmt[XBM_BACKGROUND].value))
3823 {
3824 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3825 background);
3826 non_default_colors = 1;
3827 }
3828
3829 if (in_memory_file_p)
3830 success_p = xbm_load_image (f, img, SDATA (data),
3831 (SDATA (data)
3832 + SBYTES (data)));
3833 else
3834 {
3835 if (VECTORP (data))
3836 {
3837 int i;
3838 char *p;
3839 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3840
3841 p = bits = (char *) alloca (nbytes * img->height);
3842 for (i = 0; i < img->height; ++i, p += nbytes)
3843 {
3844 Lisp_Object line = XVECTOR (data)->contents[i];
3845 if (STRINGP (line))
3846 bcopy (SDATA (line), p, nbytes);
3847 else
3848 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3849 }
3850 }
3851 else if (STRINGP (data))
3852 bits = SDATA (data);
3853 else
3854 bits = XBOOL_VECTOR (data)->data;
3855
3856 #ifdef WINDOWSNT
3857 {
3858 char *invertedBits;
3859 int nbytes, i;
3860 /* Windows mono bitmaps are reversed compared with X. */
3861 invertedBits = bits;
3862 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
3863 * img->height;
3864 bits = (char *) alloca(nbytes);
3865 for (i = 0; i < nbytes; i++)
3866 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3867 }
3868 #endif
3869 /* Create the pixmap. */
3870
3871 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3872 foreground, background,
3873 non_default_colors);
3874 if (img->pixmap)
3875 success_p = 1;
3876 else
3877 {
3878 image_error ("Unable to create pixmap for XBM image `%s'",
3879 img->spec, Qnil);
3880 x_clear_image (f, img);
3881 }
3882 }
3883 }
3884
3885 return success_p;
3886 }
3887
3888
3889 \f
3890 /***********************************************************************
3891 XPM images
3892 ***********************************************************************/
3893
3894 #if defined (HAVE_XPM) || defined (MAC_OS)
3895
3896 static int xpm_image_p P_ ((Lisp_Object object));
3897 static int xpm_load P_ ((struct frame *f, struct image *img));
3898 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3899
3900 #endif /* HAVE_XPM || MAC_OS */
3901
3902 #ifdef HAVE_XPM
3903 #ifdef HAVE_NTGUI
3904 /* Indicate to xpm.h that we don't have Xlib. */
3905 #define FOR_MSW
3906 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3907 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3908 #define XColor xpm_XColor
3909 #define XImage xpm_XImage
3910 #define Display xpm_Display
3911 #define PIXEL_ALREADY_TYPEDEFED
3912 #include "X11/xpm.h"
3913 #undef FOR_MSW
3914 #undef XColor
3915 #undef XImage
3916 #undef Display
3917 #undef PIXEL_ALREADY_TYPEDEFED
3918 #else
3919 #include "X11/xpm.h"
3920 #endif /* HAVE_NTGUI */
3921 #endif /* HAVE_XPM */
3922
3923 #if defined (HAVE_XPM) || defined (MAC_OS)
3924 /* The symbol `xpm' identifying XPM-format images. */
3925
3926 Lisp_Object Qxpm;
3927
3928 /* Indices of image specification fields in xpm_format, below. */
3929
3930 enum xpm_keyword_index
3931 {
3932 XPM_TYPE,
3933 XPM_FILE,
3934 XPM_DATA,
3935 XPM_ASCENT,
3936 XPM_MARGIN,
3937 XPM_RELIEF,
3938 XPM_ALGORITHM,
3939 XPM_HEURISTIC_MASK,
3940 XPM_MASK,
3941 XPM_COLOR_SYMBOLS,
3942 XPM_BACKGROUND,
3943 XPM_LAST
3944 };
3945
3946 /* Vector of image_keyword structures describing the format
3947 of valid XPM image specifications. */
3948
3949 static struct image_keyword xpm_format[XPM_LAST] =
3950 {
3951 {":type", IMAGE_SYMBOL_VALUE, 1},
3952 {":file", IMAGE_STRING_VALUE, 0},
3953 {":data", IMAGE_STRING_VALUE, 0},
3954 {":ascent", IMAGE_ASCENT_VALUE, 0},
3955 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3956 {":relief", IMAGE_INTEGER_VALUE, 0},
3957 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3958 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3959 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3960 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3961 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3962 };
3963
3964 /* Structure describing the image type XPM. */
3965
3966 static struct image_type xpm_type =
3967 {
3968 &Qxpm,
3969 xpm_image_p,
3970 xpm_load,
3971 x_clear_image,
3972 NULL
3973 };
3974
3975 #ifdef HAVE_X_WINDOWS
3976
3977 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3978 functions for allocating image colors. Our own functions handle
3979 color allocation failures more gracefully than the ones on the XPM
3980 lib. */
3981
3982 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3983 #define ALLOC_XPM_COLORS
3984 #endif
3985 #endif /* HAVE_X_WINDOWS */
3986
3987 #ifdef ALLOC_XPM_COLORS
3988
3989 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3990 static void xpm_free_color_cache P_ ((void));
3991 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3992 static int xpm_color_bucket P_ ((char *));
3993 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3994 XColor *, int));
3995
3996 /* An entry in a hash table used to cache color definitions of named
3997 colors. This cache is necessary to speed up XPM image loading in
3998 case we do color allocations ourselves. Without it, we would need
3999 a call to XParseColor per pixel in the image. */
4000
4001 struct xpm_cached_color
4002 {
4003 /* Next in collision chain. */
4004 struct xpm_cached_color *next;
4005
4006 /* Color definition (RGB and pixel color). */
4007 XColor color;
4008
4009 /* Color name. */
4010 char name[1];
4011 };
4012
4013 /* The hash table used for the color cache, and its bucket vector
4014 size. */
4015
4016 #define XPM_COLOR_CACHE_BUCKETS 1001
4017 struct xpm_cached_color **xpm_color_cache;
4018
4019 /* Initialize the color cache. */
4020
4021 static void
4022 xpm_init_color_cache (f, attrs)
4023 struct frame *f;
4024 XpmAttributes *attrs;
4025 {
4026 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
4027 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
4028 memset (xpm_color_cache, 0, nbytes);
4029 init_color_table ();
4030
4031 if (attrs->valuemask & XpmColorSymbols)
4032 {
4033 int i;
4034 XColor color;
4035
4036 for (i = 0; i < attrs->numsymbols; ++i)
4037 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4038 attrs->colorsymbols[i].value, &color))
4039 {
4040 color.pixel = lookup_rgb_color (f, color.red, color.green,
4041 color.blue);
4042 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
4043 }
4044 }
4045 }
4046
4047 /* Free the color cache. */
4048
4049 static void
4050 xpm_free_color_cache ()
4051 {
4052 struct xpm_cached_color *p, *next;
4053 int i;
4054
4055 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
4056 for (p = xpm_color_cache[i]; p; p = next)
4057 {
4058 next = p->next;
4059 xfree (p);
4060 }
4061
4062 xfree (xpm_color_cache);
4063 xpm_color_cache = NULL;
4064 free_color_table ();
4065 }
4066
4067 /* Return the bucket index for color named COLOR_NAME in the color
4068 cache. */
4069
4070 static int
4071 xpm_color_bucket (color_name)
4072 char *color_name;
4073 {
4074 unsigned h = 0;
4075 char *s;
4076
4077 for (s = color_name; *s; ++s)
4078 h = (h << 2) ^ *s;
4079 return h %= XPM_COLOR_CACHE_BUCKETS;
4080 }
4081
4082
4083 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4084 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4085 entry added. */
4086
4087 static struct xpm_cached_color *
4088 xpm_cache_color (f, color_name, color, bucket)
4089 struct frame *f;
4090 char *color_name;
4091 XColor *color;
4092 int bucket;
4093 {
4094 size_t nbytes;
4095 struct xpm_cached_color *p;
4096
4097 if (bucket < 0)
4098 bucket = xpm_color_bucket (color_name);
4099
4100 nbytes = sizeof *p + strlen (color_name);
4101 p = (struct xpm_cached_color *) xmalloc (nbytes);
4102 strcpy (p->name, color_name);
4103 p->color = *color;
4104 p->next = xpm_color_cache[bucket];
4105 xpm_color_cache[bucket] = p;
4106 return p;
4107 }
4108
4109 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4110 return the cached definition in *COLOR. Otherwise, make a new
4111 entry in the cache and allocate the color. Value is zero if color
4112 allocation failed. */
4113
4114 static int
4115 xpm_lookup_color (f, color_name, color)
4116 struct frame *f;
4117 char *color_name;
4118 XColor *color;
4119 {
4120 struct xpm_cached_color *p;
4121 int h = xpm_color_bucket (color_name);
4122
4123 for (p = xpm_color_cache[h]; p; p = p->next)
4124 if (strcmp (p->name, color_name) == 0)
4125 break;
4126
4127 if (p != NULL)
4128 *color = p->color;
4129 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4130 color_name, color))
4131 {
4132 color->pixel = lookup_rgb_color (f, color->red, color->green,
4133 color->blue);
4134 p = xpm_cache_color (f, color_name, color, h);
4135 }
4136 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4137 with transparency, and it's useful. */
4138 else if (strcmp ("opaque", color_name) == 0)
4139 {
4140 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
4141 color->pixel = FRAME_FOREGROUND_PIXEL (f);
4142 p = xpm_cache_color (f, color_name, color, h);
4143 }
4144
4145 return p != NULL;
4146 }
4147
4148
4149 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4150 CLOSURE is a pointer to the frame on which we allocate the
4151 color. Return in *COLOR the allocated color. Value is non-zero
4152 if successful. */
4153
4154 static int
4155 xpm_alloc_color (dpy, cmap, color_name, color, closure)
4156 Display *dpy;
4157 Colormap cmap;
4158 char *color_name;
4159 XColor *color;
4160 void *closure;
4161 {
4162 return xpm_lookup_color ((struct frame *) closure, color_name, color);
4163 }
4164
4165
4166 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4167 is a pointer to the frame on which we allocate the color. Value is
4168 non-zero if successful. */
4169
4170 static int
4171 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
4172 Display *dpy;
4173 Colormap cmap;
4174 Pixel *pixels;
4175 int npixels;
4176 void *closure;
4177 {
4178 return 1;
4179 }
4180
4181 #endif /* ALLOC_XPM_COLORS */
4182
4183
4184 #ifdef HAVE_NTGUI
4185
4186 /* XPM library details. */
4187
4188 DEF_IMGLIB_FN (XpmFreeAttributes);
4189 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
4190 DEF_IMGLIB_FN (XpmReadFileToImage);
4191 DEF_IMGLIB_FN (XImageFree);
4192
4193 static int
4194 init_xpm_functions (Lisp_Object libraries)
4195 {
4196 HMODULE library;
4197
4198 if (!(library = w32_delayed_load (libraries, Qxpm)))
4199 return 0;
4200
4201 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
4202 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
4203 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
4204 LOAD_IMGLIB_FN (library, XImageFree);
4205 return 1;
4206 }
4207
4208 #endif /* HAVE_NTGUI */
4209
4210
4211 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4212 for XPM images. Such a list must consist of conses whose car and
4213 cdr are strings. */
4214
4215 static int
4216 xpm_valid_color_symbols_p (color_symbols)
4217 Lisp_Object color_symbols;
4218 {
4219 while (CONSP (color_symbols))
4220 {
4221 Lisp_Object sym = XCAR (color_symbols);
4222 if (!CONSP (sym)
4223 || !STRINGP (XCAR (sym))
4224 || !STRINGP (XCDR (sym)))
4225 break;
4226 color_symbols = XCDR (color_symbols);
4227 }
4228
4229 return NILP (color_symbols);
4230 }
4231
4232
4233 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4234
4235 static int
4236 xpm_image_p (object)
4237 Lisp_Object object;
4238 {
4239 struct image_keyword fmt[XPM_LAST];
4240 bcopy (xpm_format, fmt, sizeof fmt);
4241 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
4242 /* Either `:file' or `:data' must be present. */
4243 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
4244 /* Either no `:color-symbols' or it's a list of conses
4245 whose car and cdr are strings. */
4246 && (fmt[XPM_COLOR_SYMBOLS].count == 0
4247 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
4248 }
4249
4250 #endif /* HAVE_XPM || MAC_OS */
4251
4252 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4253 int
4254 x_create_bitmap_from_xpm_data (f, bits)
4255 struct frame *f;
4256 char **bits;
4257 {
4258 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4259 int id, rc;
4260 XpmAttributes attrs;
4261 Pixmap bitmap, mask;
4262
4263 bzero (&attrs, sizeof attrs);
4264
4265 attrs.visual = FRAME_X_VISUAL (f);
4266 attrs.colormap = FRAME_X_COLORMAP (f);
4267 attrs.valuemask |= XpmVisual;
4268 attrs.valuemask |= XpmColormap;
4269
4270 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4271 bits, &bitmap, &mask, &attrs);
4272 if (rc != XpmSuccess)
4273 {
4274 XpmFreeAttributes (&attrs);
4275 return -1;
4276 }
4277
4278 id = x_allocate_bitmap_record (f);
4279 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
4280 dpyinfo->bitmaps[id - 1].have_mask = 1;
4281 dpyinfo->bitmaps[id - 1].mask = mask;
4282 dpyinfo->bitmaps[id - 1].file = NULL;
4283 dpyinfo->bitmaps[id - 1].height = attrs.height;
4284 dpyinfo->bitmaps[id - 1].width = attrs.width;
4285 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
4286 dpyinfo->bitmaps[id - 1].refcount = 1;
4287
4288 XpmFreeAttributes (&attrs);
4289 return id;
4290 }
4291 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4292
4293 /* Load image IMG which will be displayed on frame F. Value is
4294 non-zero if successful. */
4295
4296 #ifdef HAVE_XPM
4297
4298 static int
4299 xpm_load (f, img)
4300 struct frame *f;
4301 struct image *img;
4302 {
4303 int rc;
4304 XpmAttributes attrs;
4305 Lisp_Object specified_file, color_symbols;
4306 #ifdef HAVE_NTGUI
4307 HDC hdc;
4308 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
4309 #endif /* HAVE_NTGUI */
4310
4311 /* Configure the XPM lib. Use the visual of frame F. Allocate
4312 close colors. Return colors allocated. */
4313 bzero (&attrs, sizeof attrs);
4314
4315 #ifndef HAVE_NTGUI
4316 attrs.visual = FRAME_X_VISUAL (f);
4317 attrs.colormap = FRAME_X_COLORMAP (f);
4318 attrs.valuemask |= XpmVisual;
4319 attrs.valuemask |= XpmColormap;
4320 #endif /* HAVE_NTGUI */
4321
4322 #ifdef ALLOC_XPM_COLORS
4323 /* Allocate colors with our own functions which handle
4324 failing color allocation more gracefully. */
4325 attrs.color_closure = f;
4326 attrs.alloc_color = xpm_alloc_color;
4327 attrs.free_colors = xpm_free_colors;
4328 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
4329 #else /* not ALLOC_XPM_COLORS */
4330 /* Let the XPM lib allocate colors. */
4331 attrs.valuemask |= XpmReturnAllocPixels;
4332 #ifdef XpmAllocCloseColors
4333 attrs.alloc_close_colors = 1;
4334 attrs.valuemask |= XpmAllocCloseColors;
4335 #else /* not XpmAllocCloseColors */
4336 attrs.closeness = 600;
4337 attrs.valuemask |= XpmCloseness;
4338 #endif /* not XpmAllocCloseColors */
4339 #endif /* ALLOC_XPM_COLORS */
4340
4341 /* If image specification contains symbolic color definitions, add
4342 these to `attrs'. */
4343 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4344 if (CONSP (color_symbols))
4345 {
4346 Lisp_Object tail;
4347 XpmColorSymbol *xpm_syms;
4348 int i, size;
4349
4350 attrs.valuemask |= XpmColorSymbols;
4351
4352 /* Count number of symbols. */
4353 attrs.numsymbols = 0;
4354 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
4355 ++attrs.numsymbols;
4356
4357 /* Allocate an XpmColorSymbol array. */
4358 size = attrs.numsymbols * sizeof *xpm_syms;
4359 xpm_syms = (XpmColorSymbol *) alloca (size);
4360 bzero (xpm_syms, size);
4361 attrs.colorsymbols = xpm_syms;
4362
4363 /* Fill the color symbol array. */
4364 for (tail = color_symbols, i = 0;
4365 CONSP (tail);
4366 ++i, tail = XCDR (tail))
4367 {
4368 Lisp_Object name = XCAR (XCAR (tail));
4369 Lisp_Object color = XCDR (XCAR (tail));
4370 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
4371 strcpy (xpm_syms[i].name, SDATA (name));
4372 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
4373 strcpy (xpm_syms[i].value, SDATA (color));
4374 }
4375 }
4376
4377 /* Create a pixmap for the image, either from a file, or from a
4378 string buffer containing data in the same format as an XPM file. */
4379 #ifdef ALLOC_XPM_COLORS
4380 xpm_init_color_cache (f, &attrs);
4381 #endif
4382
4383 specified_file = image_spec_value (img->spec, QCfile, NULL);
4384
4385 #ifdef HAVE_NTGUI
4386 {
4387 HDC frame_dc = get_frame_dc (f);
4388 hdc = CreateCompatibleDC (frame_dc);
4389 release_frame_dc (f, frame_dc);
4390 }
4391 #endif /* HAVE_NTGUI */
4392
4393 if (STRINGP (specified_file))
4394 {
4395 Lisp_Object file = x_find_image_file (specified_file);
4396 if (!STRINGP (file))
4397 {
4398 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4399 return 0;
4400 }
4401
4402 #ifdef HAVE_NTGUI
4403 /* XpmReadFileToPixmap is not available in the Windows port of
4404 libxpm. But XpmReadFileToImage almost does what we want. */
4405 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
4406 &xpm_image, &xpm_mask,
4407 &attrs);
4408 #else
4409 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4410 SDATA (file), &img->pixmap, &img->mask,
4411 &attrs);
4412 #endif /* HAVE_NTGUI */
4413 }
4414 else
4415 {
4416 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
4417 #ifdef HAVE_NTGUI
4418 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4419 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4420 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
4421 &xpm_image, &xpm_mask,
4422 &attrs);
4423 #else
4424 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4425 SDATA (buffer),
4426 &img->pixmap, &img->mask,
4427 &attrs);
4428 #endif /* HAVE_NTGUI */
4429 }
4430
4431 if (rc == XpmSuccess)
4432 {
4433 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4434 img->colors = colors_in_color_table (&img->ncolors);
4435 #else /* not ALLOC_XPM_COLORS */
4436 int i;
4437
4438 #ifdef HAVE_NTGUI
4439 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4440 plus some duplicate attributes. */
4441 if (xpm_image && xpm_image->bitmap)
4442 {
4443 img->pixmap = xpm_image->bitmap;
4444 /* XImageFree in libXpm frees XImage struct without destroying
4445 the bitmap, which is what we want. */
4446 fn_XImageFree (xpm_image);
4447 }
4448 if (xpm_mask && xpm_mask->bitmap)
4449 {
4450 /* The mask appears to be inverted compared with what we expect.
4451 TODO: invert our expectations. See other places where we
4452 have to invert bits because our idea of masks is backwards. */
4453 HGDIOBJ old_obj;
4454 old_obj = SelectObject (hdc, xpm_mask->bitmap);
4455
4456 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
4457 SelectObject (hdc, old_obj);
4458
4459 img->mask = xpm_mask->bitmap;
4460 fn_XImageFree (xpm_mask);
4461 DeleteDC (hdc);
4462 }
4463
4464 DeleteDC (hdc);
4465 #endif /* HAVE_NTGUI */
4466
4467 /* Remember allocated colors. */
4468 img->ncolors = attrs.nalloc_pixels;
4469 img->colors = (unsigned long *) xmalloc (img->ncolors
4470 * sizeof *img->colors);
4471 for (i = 0; i < attrs.nalloc_pixels; ++i)
4472 {
4473 img->colors[i] = attrs.alloc_pixels[i];
4474 #ifdef DEBUG_X_COLORS
4475 register_color (img->colors[i]);
4476 #endif
4477 }
4478 #endif /* not ALLOC_XPM_COLORS */
4479
4480 img->width = attrs.width;
4481 img->height = attrs.height;
4482 xassert (img->width > 0 && img->height > 0);
4483
4484 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4485 #ifdef HAVE_NTGUI
4486 fn_XpmFreeAttributes (&attrs);
4487 #else
4488 XpmFreeAttributes (&attrs);
4489 #endif /* HAVE_NTGUI */
4490 }
4491 else
4492 {
4493 #ifdef HAVE_NTGUI
4494 DeleteDC (hdc);
4495 #endif /* HAVE_NTGUI */
4496
4497 switch (rc)
4498 {
4499 case XpmOpenFailed:
4500 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
4501 break;
4502
4503 case XpmFileInvalid:
4504 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4505 break;
4506
4507 case XpmNoMemory:
4508 image_error ("Out of memory (%s)", img->spec, Qnil);
4509 break;
4510
4511 case XpmColorFailed:
4512 image_error ("Color allocation error (%s)", img->spec, Qnil);
4513 break;
4514
4515 default:
4516 image_error ("Unknown error (%s)", img->spec, Qnil);
4517 break;
4518 }
4519 }
4520
4521 #ifdef ALLOC_XPM_COLORS
4522 xpm_free_color_cache ();
4523 #endif
4524 return rc == XpmSuccess;
4525 }
4526
4527 #endif /* HAVE_XPM */
4528
4529 #ifdef MAC_OS
4530
4531 /* XPM support functions for Mac OS where libxpm is not available.
4532 Only XPM version 3 (without any extensions) is supported. */
4533
4534 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
4535 const unsigned char **, int *));
4536 static Lisp_Object xpm_make_color_table_v
4537 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4538 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4539 static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
4540 int, Lisp_Object));
4541 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
4542 const unsigned char *, int));
4543 static Lisp_Object xpm_make_color_table_h
4544 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4545 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4546 static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
4547 int, Lisp_Object));
4548 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
4549 const unsigned char *, int));
4550 static int xpm_str_to_color_key P_ ((const char *));
4551 static int xpm_load_image P_ ((struct frame *, struct image *,
4552 const unsigned char *, const unsigned char *));
4553
4554 /* Tokens returned from xpm_scan. */
4555
4556 enum xpm_token
4557 {
4558 XPM_TK_IDENT = 256,
4559 XPM_TK_STRING,
4560 XPM_TK_EOF
4561 };
4562
4563 /* Scan an XPM data and return a character (< 256) or a token defined
4564 by enum xpm_token above. *S and END are the start (inclusive) and
4565 the end (exclusive) addresses of the data, respectively. Advance
4566 *S while scanning. If token is either XPM_TK_IDENT or
4567 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4568 length of the corresponding token, respectively. */
4569
4570 static int
4571 xpm_scan (s, end, beg, len)
4572 const unsigned char **s, *end, **beg;
4573 int *len;
4574 {
4575 int c;
4576
4577 while (*s < end)
4578 {
4579 /* Skip white-space. */
4580 while (*s < end && (c = *(*s)++, isspace (c)))
4581 ;
4582
4583 /* gnus-pointer.xpm uses '-' in its identifier.
4584 sb-dir-plus.xpm uses '+' in its identifier. */
4585 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4586 {
4587 *beg = *s - 1;
4588 while (*s < end
4589 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4590 ++*s;
4591 *len = *s - *beg;
4592 return XPM_TK_IDENT;
4593 }
4594 else if (c == '"')
4595 {
4596 *beg = *s;
4597 while (*s < end && **s != '"')
4598 ++*s;
4599 *len = *s - *beg;
4600 if (*s < end)
4601 ++*s;
4602 return XPM_TK_STRING;
4603 }
4604 else if (c == '/')
4605 {
4606 if (*s < end && **s == '*')
4607 {
4608 /* C-style comment. */
4609 ++*s;
4610 do
4611 {
4612 while (*s < end && *(*s)++ != '*')
4613 ;
4614 }
4615 while (*s < end && **s != '/');
4616 if (*s < end)
4617 ++*s;
4618 }
4619 else
4620 return c;
4621 }
4622 else
4623 return c;
4624 }
4625
4626 return XPM_TK_EOF;
4627 }
4628
4629 /* Functions for color table lookup in XPM data. A key is a string
4630 specifying the color of each pixel in XPM data. A value is either
4631 an integer that specifies a pixel color, Qt that specifies
4632 transparency, or Qnil for the unspecified color. If the length of
4633 the key string is one, a vector is used as a table. Otherwise, a
4634 hash table is used. */
4635
4636 static Lisp_Object
4637 xpm_make_color_table_v (put_func, get_func)
4638 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4639 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4640 {
4641 *put_func = xpm_put_color_table_v;
4642 *get_func = xpm_get_color_table_v;
4643 return Fmake_vector (make_number (256), Qnil);
4644 }
4645
4646 static void
4647 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4648 Lisp_Object color_table;
4649 const unsigned char *chars_start;
4650 int chars_len;
4651 Lisp_Object color;
4652 {
4653 XVECTOR (color_table)->contents[*chars_start] = color;
4654 }
4655
4656 static Lisp_Object
4657 xpm_get_color_table_v (color_table, chars_start, chars_len)
4658 Lisp_Object color_table;
4659 const unsigned char *chars_start;
4660 int chars_len;
4661 {
4662 return XVECTOR (color_table)->contents[*chars_start];
4663 }
4664
4665 static Lisp_Object
4666 xpm_make_color_table_h (put_func, get_func)
4667 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4668 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4669 {
4670 *put_func = xpm_put_color_table_h;
4671 *get_func = xpm_get_color_table_h;
4672 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4673 make_float (DEFAULT_REHASH_SIZE),
4674 make_float (DEFAULT_REHASH_THRESHOLD),
4675 Qnil, Qnil, Qnil);
4676 }
4677
4678 static void
4679 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4680 Lisp_Object color_table;
4681 const unsigned char *chars_start;
4682 int chars_len;
4683 Lisp_Object color;
4684 {
4685 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4686 unsigned hash_code;
4687 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4688
4689 hash_lookup (table, chars, &hash_code);
4690 hash_put (table, chars, color, hash_code);
4691 }
4692
4693 static Lisp_Object
4694 xpm_get_color_table_h (color_table, chars_start, chars_len)
4695 Lisp_Object color_table;
4696 const unsigned char *chars_start;
4697 int chars_len;
4698 {
4699 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4700 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4701 NULL);
4702
4703 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4704 }
4705
4706 enum xpm_color_key {
4707 XPM_COLOR_KEY_S,
4708 XPM_COLOR_KEY_M,
4709 XPM_COLOR_KEY_G4,
4710 XPM_COLOR_KEY_G,
4711 XPM_COLOR_KEY_C
4712 };
4713
4714 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4715
4716 static int
4717 xpm_str_to_color_key (s)
4718 const char *s;
4719 {
4720 int i;
4721
4722 for (i = 0;
4723 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4724 i++)
4725 if (strcmp (xpm_color_key_strings[i], s) == 0)
4726 return i;
4727 return -1;
4728 }
4729
4730 static int
4731 xpm_load_image (f, img, contents, end)
4732 struct frame *f;
4733 struct image *img;
4734 const unsigned char *contents, *end;
4735 {
4736 const unsigned char *s = contents, *beg, *str;
4737 unsigned char buffer[BUFSIZ];
4738 int width, height, x, y;
4739 int num_colors, chars_per_pixel;
4740 int len, LA1;
4741 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4742 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
4743 Lisp_Object frame, color_symbols, color_table;
4744 int best_key, have_mask = 0;
4745 XImagePtr ximg = NULL, mask_img = NULL;
4746
4747 #define match() \
4748 LA1 = xpm_scan (&s, end, &beg, &len)
4749
4750 #define expect(TOKEN) \
4751 if (LA1 != (TOKEN)) \
4752 goto failure; \
4753 else \
4754 match ()
4755
4756 #define expect_ident(IDENT) \
4757 if (LA1 == XPM_TK_IDENT \
4758 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4759 match (); \
4760 else \
4761 goto failure
4762
4763 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4764 goto failure;
4765 s += 9;
4766 match();
4767 expect_ident ("static");
4768 expect_ident ("char");
4769 expect ('*');
4770 expect (XPM_TK_IDENT);
4771 expect ('[');
4772 expect (']');
4773 expect ('=');
4774 expect ('{');
4775 expect (XPM_TK_STRING);
4776 if (len >= BUFSIZ)
4777 goto failure;
4778 memcpy (buffer, beg, len);
4779 buffer[len] = '\0';
4780 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4781 &num_colors, &chars_per_pixel) != 4
4782 || width <= 0 || height <= 0
4783 || num_colors <= 0 || chars_per_pixel <= 0)
4784 goto failure;
4785
4786 if (!check_image_size (f, width, height))
4787 {
4788 image_error ("Invalid image size", Qnil, Qnil);
4789 goto failure;
4790 }
4791
4792 expect (',');
4793
4794 XSETFRAME (frame, f);
4795 if (!NILP (Fxw_display_color_p (frame)))
4796 best_key = XPM_COLOR_KEY_C;
4797 else if (!NILP (Fx_display_grayscale_p (frame)))
4798 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4799 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4800 else
4801 best_key = XPM_COLOR_KEY_M;
4802
4803 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4804 if (chars_per_pixel == 1)
4805 color_table = xpm_make_color_table_v (&put_color_table,
4806 &get_color_table);
4807 else
4808 color_table = xpm_make_color_table_h (&put_color_table,
4809 &get_color_table);
4810
4811 while (num_colors-- > 0)
4812 {
4813 unsigned char *color, *max_color;
4814 int key, next_key, max_key = 0;
4815 Lisp_Object symbol_color = Qnil, color_val;
4816 XColor cdef;
4817
4818 expect (XPM_TK_STRING);
4819 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4820 goto failure;
4821 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4822 buffer[len - chars_per_pixel] = '\0';
4823
4824 str = strtok (buffer, " \t");
4825 if (str == NULL)
4826 goto failure;
4827 key = xpm_str_to_color_key (str);
4828 if (key < 0)
4829 goto failure;
4830 do
4831 {
4832 color = strtok (NULL, " \t");
4833 if (color == NULL)
4834 goto failure;
4835
4836 while ((str = strtok (NULL, " \t")) != NULL)
4837 {
4838 next_key = xpm_str_to_color_key (str);
4839 if (next_key >= 0)
4840 break;
4841 color[strlen (color)] = ' ';
4842 }
4843
4844 if (key == XPM_COLOR_KEY_S)
4845 {
4846 if (NILP (symbol_color))
4847 symbol_color = build_string (color);
4848 }
4849 else if (max_key < key && key <= best_key)
4850 {
4851 max_key = key;
4852 max_color = color;
4853 }
4854 key = next_key;
4855 }
4856 while (str);
4857
4858 color_val = Qnil;
4859 if (!NILP (color_symbols) && !NILP (symbol_color))
4860 {
4861 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4862
4863 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4864 {
4865 if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4866 color_val = Qt;
4867 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4868 &cdef, 0))
4869 color_val = make_number (cdef.pixel);
4870 }
4871 }
4872 if (NILP (color_val) && max_key > 0)
4873 {
4874 if (xstricmp (max_color, "None") == 0)
4875 color_val = Qt;
4876 else if (x_defined_color (f, max_color, &cdef, 0))
4877 color_val = make_number (cdef.pixel);
4878 }
4879 if (!NILP (color_val))
4880 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4881
4882 expect (',');
4883 }
4884
4885 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4886 &ximg, &img->pixmap)
4887 || !x_create_x_image_and_pixmap (f, width, height, 1,
4888 &mask_img, &img->mask))
4889 {
4890 image_error ("Out of memory (%s)", img->spec, Qnil);
4891 goto error;
4892 }
4893
4894 for (y = 0; y < height; y++)
4895 {
4896 expect (XPM_TK_STRING);
4897 str = beg;
4898 if (len < width * chars_per_pixel)
4899 goto failure;
4900 for (x = 0; x < width; x++, str += chars_per_pixel)
4901 {
4902 Lisp_Object color_val =
4903 (*get_color_table) (color_table, str, chars_per_pixel);
4904
4905 XPutPixel (ximg, x, y,
4906 (INTEGERP (color_val) ? XINT (color_val)
4907 : FRAME_FOREGROUND_PIXEL (f)));
4908 XPutPixel (mask_img, x, y,
4909 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4910 : (have_mask = 1, PIX_MASK_RETAIN)));
4911 }
4912 if (y + 1 < height)
4913 expect (',');
4914 }
4915
4916 img->width = width;
4917 img->height = height;
4918
4919 /* Maybe fill in the background field while we have ximg handy. */
4920 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4921 IMAGE_BACKGROUND (img, f, ximg);
4922
4923 x_put_x_image (f, ximg, img->pixmap, width, height);
4924 x_destroy_x_image (ximg);
4925 if (have_mask)
4926 {
4927 /* Fill in the background_transparent field while we have the
4928 mask handy. */
4929 image_background_transparent (img, f, mask_img);
4930
4931 x_put_x_image (f, mask_img, img->mask, width, height);
4932 x_destroy_x_image (mask_img);
4933 }
4934 else
4935 {
4936 x_destroy_x_image (mask_img);
4937 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4938 img->mask = NO_PIXMAP;
4939 }
4940
4941 return 1;
4942
4943 failure:
4944 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4945 error:
4946 x_destroy_x_image (ximg);
4947 x_destroy_x_image (mask_img);
4948 x_clear_image (f, img);
4949 return 0;
4950
4951 #undef match
4952 #undef expect
4953 #undef expect_ident
4954 }
4955
4956 static int
4957 xpm_load (f, img)
4958 struct frame *f;
4959 struct image *img;
4960 {
4961 int success_p = 0;
4962 Lisp_Object file_name;
4963
4964 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4965 file_name = image_spec_value (img->spec, QCfile, NULL);
4966 if (STRINGP (file_name))
4967 {
4968 Lisp_Object file;
4969 unsigned char *contents;
4970 int size;
4971 struct gcpro gcpro1;
4972
4973 file = x_find_image_file (file_name);
4974 GCPRO1 (file);
4975 if (!STRINGP (file))
4976 {
4977 image_error ("Cannot find image file `%s'", file_name, Qnil);
4978 UNGCPRO;
4979 return 0;
4980 }
4981
4982 contents = slurp_file (SDATA (file), &size);
4983 if (contents == NULL)
4984 {
4985 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4986 UNGCPRO;
4987 return 0;
4988 }
4989
4990 success_p = xpm_load_image (f, img, contents, contents + size);
4991 xfree (contents);
4992 UNGCPRO;
4993 }
4994 else
4995 {
4996 Lisp_Object data;
4997
4998 data = image_spec_value (img->spec, QCdata, NULL);
4999 success_p = xpm_load_image (f, img, SDATA (data),
5000 SDATA (data) + SBYTES (data));
5001 }
5002
5003 return success_p;
5004 }
5005
5006 #endif /* MAC_OS */
5007
5008
5009 \f
5010 /***********************************************************************
5011 Color table
5012 ***********************************************************************/
5013
5014 #ifdef COLOR_TABLE_SUPPORT
5015
5016 /* An entry in the color table mapping an RGB color to a pixel color. */
5017
5018 struct ct_color
5019 {
5020 int r, g, b;
5021 unsigned long pixel;
5022
5023 /* Next in color table collision list. */
5024 struct ct_color *next;
5025 };
5026
5027 /* The bucket vector size to use. Must be prime. */
5028
5029 #define CT_SIZE 101
5030
5031 /* Value is a hash of the RGB color given by R, G, and B. */
5032
5033 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5034
5035 /* The color hash table. */
5036
5037 struct ct_color **ct_table;
5038
5039 /* Number of entries in the color table. */
5040
5041 int ct_colors_allocated;
5042
5043 /* Initialize the color table. */
5044
5045 static void
5046 init_color_table ()
5047 {
5048 int size = CT_SIZE * sizeof (*ct_table);
5049 ct_table = (struct ct_color **) xmalloc (size);
5050 bzero (ct_table, size);
5051 ct_colors_allocated = 0;
5052 }
5053
5054
5055 /* Free memory associated with the color table. */
5056
5057 static void
5058 free_color_table ()
5059 {
5060 int i;
5061 struct ct_color *p, *next;
5062
5063 for (i = 0; i < CT_SIZE; ++i)
5064 for (p = ct_table[i]; p; p = next)
5065 {
5066 next = p->next;
5067 xfree (p);
5068 }
5069
5070 xfree (ct_table);
5071 ct_table = NULL;
5072 }
5073
5074
5075 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5076 entry for that color already is in the color table, return the
5077 pixel color of that entry. Otherwise, allocate a new color for R,
5078 G, B, and make an entry in the color table. */
5079
5080 static unsigned long
5081 lookup_rgb_color (f, r, g, b)
5082 struct frame *f;
5083 int r, g, b;
5084 {
5085 unsigned hash = CT_HASH_RGB (r, g, b);
5086 int i = hash % CT_SIZE;
5087 struct ct_color *p;
5088 Display_Info *dpyinfo;
5089
5090 /* Handle TrueColor visuals specially, which improves performance by
5091 two orders of magnitude. Freeing colors on TrueColor visuals is
5092 a nop, and pixel colors specify RGB values directly. See also
5093 the Xlib spec, chapter 3.1. */
5094 dpyinfo = FRAME_X_DISPLAY_INFO (f);
5095 if (dpyinfo->red_bits > 0)
5096 {
5097 unsigned long pr, pg, pb;
5098
5099 /* Apply gamma-correction like normal color allocation does. */
5100 if (f->gamma)
5101 {
5102 XColor color;
5103 color.red = r, color.green = g, color.blue = b;
5104 gamma_correct (f, &color);
5105 r = color.red, g = color.green, b = color.blue;
5106 }
5107
5108 /* Scale down RGB values to the visual's bits per RGB, and shift
5109 them to the right position in the pixel color. Note that the
5110 original RGB values are 16-bit values, as usual in X. */
5111 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
5112 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
5113 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
5114
5115 /* Assemble the pixel color. */
5116 return pr | pg | pb;
5117 }
5118
5119 for (p = ct_table[i]; p; p = p->next)
5120 if (p->r == r && p->g == g && p->b == b)
5121 break;
5122
5123 if (p == NULL)
5124 {
5125
5126 #ifdef HAVE_X_WINDOWS
5127 XColor color;
5128 Colormap cmap;
5129 int rc;
5130
5131 color.red = r;
5132 color.green = g;
5133 color.blue = b;
5134
5135 cmap = FRAME_X_COLORMAP (f);
5136 rc = x_alloc_nearest_color (f, cmap, &color);
5137 if (rc)
5138 {
5139 ++ct_colors_allocated;
5140 p = (struct ct_color *) xmalloc (sizeof *p);
5141 p->r = r;
5142 p->g = g;
5143 p->b = b;
5144 p->pixel = color.pixel;
5145 p->next = ct_table[i];
5146 ct_table[i] = p;
5147 }
5148 else
5149 return FRAME_FOREGROUND_PIXEL (f);
5150
5151 #else
5152 COLORREF color;
5153 #ifdef HAVE_NTGUI
5154 color = PALETTERGB (r, g, b);
5155 #else
5156 color = RGB_TO_ULONG (r, g, b);
5157 #endif /* HAVE_NTGUI */
5158 ++ct_colors_allocated;
5159 p = (struct ct_color *) xmalloc (sizeof *p);
5160 p->r = r;
5161 p->g = g;
5162 p->b = b;
5163 p->pixel = color;
5164 p->next = ct_table[i];
5165 ct_table[i] = p;
5166 #endif /* HAVE_X_WINDOWS */
5167
5168 }
5169
5170 return p->pixel;
5171 }
5172
5173
5174 /* Look up pixel color PIXEL which is used on frame F in the color
5175 table. If not already present, allocate it. Value is PIXEL. */
5176
5177 static unsigned long
5178 lookup_pixel_color (f, pixel)
5179 struct frame *f;
5180 unsigned long pixel;
5181 {
5182 int i = pixel % CT_SIZE;
5183 struct ct_color *p;
5184
5185 for (p = ct_table[i]; p; p = p->next)
5186 if (p->pixel == pixel)
5187 break;
5188
5189 if (p == NULL)
5190 {
5191 XColor color;
5192 Colormap cmap;
5193 int rc;
5194
5195 #ifdef HAVE_X_WINDOWS
5196 cmap = FRAME_X_COLORMAP (f);
5197 color.pixel = pixel;
5198 x_query_color (f, &color);
5199 rc = x_alloc_nearest_color (f, cmap, &color);
5200 #else
5201 BLOCK_INPUT;
5202 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5203 color.pixel = pixel;
5204 XQueryColor (NULL, cmap, &color);
5205 rc = x_alloc_nearest_color (f, cmap, &color);
5206 UNBLOCK_INPUT;
5207 #endif /* HAVE_X_WINDOWS */
5208
5209 if (rc)
5210 {
5211 ++ct_colors_allocated;
5212
5213 p = (struct ct_color *) xmalloc (sizeof *p);
5214 p->r = color.red;
5215 p->g = color.green;
5216 p->b = color.blue;
5217 p->pixel = pixel;
5218 p->next = ct_table[i];
5219 ct_table[i] = p;
5220 }
5221 else
5222 return FRAME_FOREGROUND_PIXEL (f);
5223 }
5224 return p->pixel;
5225 }
5226
5227
5228 /* Value is a vector of all pixel colors contained in the color table,
5229 allocated via xmalloc. Set *N to the number of colors. */
5230
5231 static unsigned long *
5232 colors_in_color_table (n)
5233 int *n;
5234 {
5235 int i, j;
5236 struct ct_color *p;
5237 unsigned long *colors;
5238
5239 if (ct_colors_allocated == 0)
5240 {
5241 *n = 0;
5242 colors = NULL;
5243 }
5244 else
5245 {
5246 colors = (unsigned long *) xmalloc (ct_colors_allocated
5247 * sizeof *colors);
5248 *n = ct_colors_allocated;
5249
5250 for (i = j = 0; i < CT_SIZE; ++i)
5251 for (p = ct_table[i]; p; p = p->next)
5252 colors[j++] = p->pixel;
5253 }
5254
5255 return colors;
5256 }
5257
5258 #else /* COLOR_TABLE_SUPPORT */
5259
5260 static unsigned long
5261 lookup_rgb_color (f, r, g, b)
5262 struct frame *f;
5263 int r, g, b;
5264 {
5265 unsigned long pixel;
5266
5267 #ifdef MAC_OS
5268 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
5269 gamma_correct (f, &pixel);
5270 #endif /* MAC_OS */
5271
5272 #ifdef HAVE_NTGUI
5273 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
5274 #endif /* HAVE_NTGUI */
5275
5276 return pixel;
5277 }
5278
5279 static void
5280 init_color_table ()
5281 {
5282 }
5283 #endif /* COLOR_TABLE_SUPPORT */
5284
5285 \f
5286 /***********************************************************************
5287 Algorithms
5288 ***********************************************************************/
5289
5290 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
5291 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
5292 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
5293
5294 #ifdef HAVE_NTGUI
5295 static void XPutPixel (XImagePtr , int, int, COLORREF);
5296 #endif /* HAVE_NTGUI */
5297
5298 /* Non-zero means draw a cross on images having `:conversion
5299 disabled'. */
5300
5301 int cross_disabled_images;
5302
5303 /* Edge detection matrices for different edge-detection
5304 strategies. */
5305
5306 static int emboss_matrix[9] = {
5307 /* x - 1 x x + 1 */
5308 2, -1, 0, /* y - 1 */
5309 -1, 0, 1, /* y */
5310 0, 1, -2 /* y + 1 */
5311 };
5312
5313 static int laplace_matrix[9] = {
5314 /* x - 1 x x + 1 */
5315 1, 0, 0, /* y - 1 */
5316 0, 0, 0, /* y */
5317 0, 0, -1 /* y + 1 */
5318 };
5319
5320 /* Value is the intensity of the color whose red/green/blue values
5321 are R, G, and B. */
5322
5323 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5324
5325
5326 /* On frame F, return an array of XColor structures describing image
5327 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5328 non-zero means also fill the red/green/blue members of the XColor
5329 structures. Value is a pointer to the array of XColors structures,
5330 allocated with xmalloc; it must be freed by the caller. */
5331
5332 static XColor *
5333 x_to_xcolors (f, img, rgb_p)
5334 struct frame *f;
5335 struct image *img;
5336 int rgb_p;
5337 {
5338 int x, y;
5339 XColor *colors, *p;
5340 XImagePtr_or_DC ximg;
5341 #ifdef HAVE_NTGUI
5342 HDC hdc;
5343 HGDIOBJ prev;
5344 #endif /* HAVE_NTGUI */
5345
5346 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
5347
5348 #ifndef HAVE_NTGUI
5349 /* Get the X image IMG->pixmap. */
5350 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
5351 0, 0, img->width, img->height, ~0, ZPixmap);
5352 #else
5353 /* Load the image into a memory device context. */
5354 hdc = get_frame_dc (f);
5355 ximg = CreateCompatibleDC (hdc);
5356 release_frame_dc (f, hdc);
5357 prev = SelectObject (ximg, img->pixmap);
5358 #endif /* HAVE_NTGUI */
5359
5360 /* Fill the `pixel' members of the XColor array. I wished there
5361 were an easy and portable way to circumvent XGetPixel. */
5362 p = colors;
5363 for (y = 0; y < img->height; ++y)
5364 {
5365 XColor *row = p;
5366
5367 #ifdef HAVE_X_WINDOWS
5368 for (x = 0; x < img->width; ++x, ++p)
5369 p->pixel = XGetPixel (ximg, x, y);
5370 if (rgb_p)
5371 x_query_colors (f, row, img->width);
5372
5373 #else
5374
5375 for (x = 0; x < img->width; ++x, ++p)
5376 {
5377 /* W32_TODO: palette support needed here? */
5378 p->pixel = GET_PIXEL (ximg, x, y);
5379 if (rgb_p)
5380 {
5381 #ifdef MAC_OS
5382 p->red = RED16_FROM_ULONG (p->pixel);
5383 p->green = GREEN16_FROM_ULONG (p->pixel);
5384 p->blue = BLUE16_FROM_ULONG (p->pixel);
5385 #endif /* MAC_OS */
5386 #ifdef HAVE_NTGUI
5387 p->red = 256 * GetRValue (p->pixel);
5388 p->green = 256 * GetGValue (p->pixel);
5389 p->blue = 256 * GetBValue (p->pixel);
5390 #endif /* HAVE_NTGUI */
5391 }
5392 }
5393 #endif /* HAVE_X_WINDOWS */
5394 }
5395
5396 Destroy_Image (ximg, prev);
5397
5398 return colors;
5399 }
5400
5401 #ifdef HAVE_NTGUI
5402
5403 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5404 created with CreateDIBSection, with the pointer to the bit values
5405 stored in ximg->data. */
5406
5407 static void
5408 XPutPixel (ximg, x, y, color)
5409 XImagePtr ximg;
5410 int x, y;
5411 COLORREF color;
5412 {
5413 int width = ximg->info.bmiHeader.biWidth;
5414 int height = ximg->info.bmiHeader.biHeight;
5415 unsigned char * pixel;
5416
5417 /* True color images. */
5418 if (ximg->info.bmiHeader.biBitCount == 24)
5419 {
5420 int rowbytes = width * 3;
5421 /* Ensure scanlines are aligned on 4 byte boundaries. */
5422 if (rowbytes % 4)
5423 rowbytes += 4 - (rowbytes % 4);
5424
5425 pixel = ximg->data + y * rowbytes + x * 3;
5426 /* Windows bitmaps are in BGR order. */
5427 *pixel = GetBValue (color);
5428 *(pixel + 1) = GetGValue (color);
5429 *(pixel + 2) = GetRValue (color);
5430 }
5431 /* Monochrome images. */
5432 else if (ximg->info.bmiHeader.biBitCount == 1)
5433 {
5434 int rowbytes = width / 8;
5435 /* Ensure scanlines are aligned on 4 byte boundaries. */
5436 if (rowbytes % 4)
5437 rowbytes += 4 - (rowbytes % 4);
5438 pixel = ximg->data + y * rowbytes + x / 8;
5439 /* Filter out palette info. */
5440 if (color & 0x00ffffff)
5441 *pixel = *pixel | (1 << x % 8);
5442 else
5443 *pixel = *pixel & ~(1 << x % 8);
5444 }
5445 else
5446 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
5447 }
5448
5449 #endif /* HAVE_NTGUI */
5450
5451 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5452 RGB members are set. F is the frame on which this all happens.
5453 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5454
5455 static void
5456 x_from_xcolors (f, img, colors)
5457 struct frame *f;
5458 struct image *img;
5459 XColor *colors;
5460 {
5461 int x, y;
5462 XImagePtr oimg;
5463 Pixmap pixmap;
5464 XColor *p;
5465
5466 init_color_table ();
5467
5468 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5469 &oimg, &pixmap);
5470 p = colors;
5471 for (y = 0; y < img->height; ++y)
5472 for (x = 0; x < img->width; ++x, ++p)
5473 {
5474 unsigned long pixel;
5475 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
5476 XPutPixel (oimg, x, y, pixel);
5477 }
5478
5479 xfree (colors);
5480 x_clear_image_1 (f, img, 1, 0, 1);
5481
5482 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5483 x_destroy_x_image (oimg);
5484 img->pixmap = pixmap;
5485 #ifdef COLOR_TABLE_SUPPORT
5486 img->colors = colors_in_color_table (&img->ncolors);
5487 free_color_table ();
5488 #endif /* COLOR_TABLE_SUPPORT */
5489 }
5490
5491
5492 /* On frame F, perform edge-detection on image IMG.
5493
5494 MATRIX is a nine-element array specifying the transformation
5495 matrix. See emboss_matrix for an example.
5496
5497 COLOR_ADJUST is a color adjustment added to each pixel of the
5498 outgoing image. */
5499
5500 static void
5501 x_detect_edges (f, img, matrix, color_adjust)
5502 struct frame *f;
5503 struct image *img;
5504 int matrix[9], color_adjust;
5505 {
5506 XColor *colors = x_to_xcolors (f, img, 1);
5507 XColor *new, *p;
5508 int x, y, i, sum;
5509
5510 for (i = sum = 0; i < 9; ++i)
5511 sum += eabs (matrix[i]);
5512
5513 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5514
5515 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5516
5517 for (y = 0; y < img->height; ++y)
5518 {
5519 p = COLOR (new, 0, y);
5520 p->red = p->green = p->blue = 0xffff/2;
5521 p = COLOR (new, img->width - 1, y);
5522 p->red = p->green = p->blue = 0xffff/2;
5523 }
5524
5525 for (x = 1; x < img->width - 1; ++x)
5526 {
5527 p = COLOR (new, x, 0);
5528 p->red = p->green = p->blue = 0xffff/2;
5529 p = COLOR (new, x, img->height - 1);
5530 p->red = p->green = p->blue = 0xffff/2;
5531 }
5532
5533 for (y = 1; y < img->height - 1; ++y)
5534 {
5535 p = COLOR (new, 1, y);
5536
5537 for (x = 1; x < img->width - 1; ++x, ++p)
5538 {
5539 int r, g, b, y1, x1;
5540
5541 r = g = b = i = 0;
5542 for (y1 = y - 1; y1 < y + 2; ++y1)
5543 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
5544 if (matrix[i])
5545 {
5546 XColor *t = COLOR (colors, x1, y1);
5547 r += matrix[i] * t->red;
5548 g += matrix[i] * t->green;
5549 b += matrix[i] * t->blue;
5550 }
5551
5552 r = (r / sum + color_adjust) & 0xffff;
5553 g = (g / sum + color_adjust) & 0xffff;
5554 b = (b / sum + color_adjust) & 0xffff;
5555 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
5556 }
5557 }
5558
5559 xfree (colors);
5560 x_from_xcolors (f, img, new);
5561
5562 #undef COLOR
5563 }
5564
5565
5566 /* Perform the pre-defined `emboss' edge-detection on image IMG
5567 on frame F. */
5568
5569 static void
5570 x_emboss (f, img)
5571 struct frame *f;
5572 struct image *img;
5573 {
5574 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
5575 }
5576
5577
5578 /* Transform image IMG which is used on frame F with a Laplace
5579 edge-detection algorithm. The result is an image that can be used
5580 to draw disabled buttons, for example. */
5581
5582 static void
5583 x_laplace (f, img)
5584 struct frame *f;
5585 struct image *img;
5586 {
5587 x_detect_edges (f, img, laplace_matrix, 45000);
5588 }
5589
5590
5591 /* Perform edge-detection on image IMG on frame F, with specified
5592 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5593
5594 MATRIX must be either
5595
5596 - a list of at least 9 numbers in row-major form
5597 - a vector of at least 9 numbers
5598
5599 COLOR_ADJUST nil means use a default; otherwise it must be a
5600 number. */
5601
5602 static void
5603 x_edge_detection (f, img, matrix, color_adjust)
5604 struct frame *f;
5605 struct image *img;
5606 Lisp_Object matrix, color_adjust;
5607 {
5608 int i = 0;
5609 int trans[9];
5610
5611 if (CONSP (matrix))
5612 {
5613 for (i = 0;
5614 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5615 ++i, matrix = XCDR (matrix))
5616 trans[i] = XFLOATINT (XCAR (matrix));
5617 }
5618 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5619 {
5620 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5621 trans[i] = XFLOATINT (AREF (matrix, i));
5622 }
5623
5624 if (NILP (color_adjust))
5625 color_adjust = make_number (0xffff / 2);
5626
5627 if (i == 9 && NUMBERP (color_adjust))
5628 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5629 }
5630
5631
5632 /* Transform image IMG on frame F so that it looks disabled. */
5633
5634 static void
5635 x_disable_image (f, img)
5636 struct frame *f;
5637 struct image *img;
5638 {
5639 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5640 #ifdef HAVE_NTGUI
5641 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5642 #else
5643 int n_planes = dpyinfo->n_planes;
5644 #endif /* HAVE_NTGUI */
5645
5646 if (n_planes >= 2)
5647 {
5648 /* Color (or grayscale). Convert to gray, and equalize. Just
5649 drawing such images with a stipple can look very odd, so
5650 we're using this method instead. */
5651 XColor *colors = x_to_xcolors (f, img, 1);
5652 XColor *p, *end;
5653 const int h = 15000;
5654 const int l = 30000;
5655
5656 for (p = colors, end = colors + img->width * img->height;
5657 p < end;
5658 ++p)
5659 {
5660 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5661 int i2 = (0xffff - h - l) * i / 0xffff + l;
5662 p->red = p->green = p->blue = i2;
5663 }
5664
5665 x_from_xcolors (f, img, colors);
5666 }
5667
5668 /* Draw a cross over the disabled image, if we must or if we
5669 should. */
5670 if (n_planes < 2 || cross_disabled_images)
5671 {
5672 #ifndef HAVE_NTGUI
5673 Display *dpy = FRAME_X_DISPLAY (f);
5674 GC gc;
5675
5676 #ifdef MAC_OS
5677 #define MaskForeground(f) PIX_MASK_DRAW
5678 #else
5679 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5680 #endif
5681
5682 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
5683 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5684 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5685 img->width - 1, img->height - 1);
5686 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5687 img->width - 1, 0);
5688 XFreeGC (dpy, gc);
5689
5690 if (img->mask)
5691 {
5692 gc = XCreateGC (dpy, img->mask, 0, NULL);
5693 XSetForeground (dpy, gc, MaskForeground (f));
5694 XDrawLine (dpy, img->mask, gc, 0, 0,
5695 img->width - 1, img->height - 1);
5696 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5697 img->width - 1, 0);
5698 XFreeGC (dpy, gc);
5699 }
5700 #else
5701 HDC hdc, bmpdc;
5702 HGDIOBJ prev;
5703
5704 hdc = get_frame_dc (f);
5705 bmpdc = CreateCompatibleDC (hdc);
5706 release_frame_dc (f, hdc);
5707
5708 prev = SelectObject (bmpdc, img->pixmap);
5709
5710 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5711 MoveToEx (bmpdc, 0, 0, NULL);
5712 LineTo (bmpdc, img->width - 1, img->height - 1);
5713 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5714 LineTo (bmpdc, img->width - 1, 0);
5715
5716 if (img->mask)
5717 {
5718 SelectObject (bmpdc, img->mask);
5719 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5720 MoveToEx (bmpdc, 0, 0, NULL);
5721 LineTo (bmpdc, img->width - 1, img->height - 1);
5722 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5723 LineTo (bmpdc, img->width - 1, 0);
5724 }
5725 SelectObject (bmpdc, prev);
5726 DeleteDC (bmpdc);
5727 #endif /* HAVE_NTGUI */
5728 }
5729 }
5730
5731
5732 /* Build a mask for image IMG which is used on frame F. FILE is the
5733 name of an image file, for error messages. HOW determines how to
5734 determine the background color of IMG. If it is a list '(R G B)',
5735 with R, G, and B being integers >= 0, take that as the color of the
5736 background. Otherwise, determine the background color of IMG
5737 heuristically. Value is non-zero if successful. */
5738
5739 static int
5740 x_build_heuristic_mask (f, img, how)
5741 struct frame *f;
5742 struct image *img;
5743 Lisp_Object how;
5744 {
5745 XImagePtr_or_DC ximg;
5746 #ifndef HAVE_NTGUI
5747 XImagePtr mask_img;
5748 #else
5749 HDC frame_dc;
5750 HGDIOBJ prev;
5751 char *mask_img;
5752 int row_width;
5753 #endif /* HAVE_NTGUI */
5754 int x, y, rc, use_img_background;
5755 unsigned long bg = 0;
5756
5757 if (img->mask)
5758 {
5759 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5760 img->mask = NO_PIXMAP;
5761 img->background_transparent_valid = 0;
5762 }
5763
5764 #ifndef HAVE_NTGUI
5765 /* Create an image and pixmap serving as mask. */
5766 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5767 &mask_img, &img->mask);
5768 if (!rc)
5769 return 0;
5770
5771 /* Get the X image of IMG->pixmap. */
5772 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5773 img->width, img->height,
5774 ~0, ZPixmap);
5775 #else
5776 /* Create the bit array serving as mask. */
5777 row_width = (img->width + 7) / 8;
5778 mask_img = xmalloc (row_width * img->height);
5779 bzero (mask_img, row_width * img->height);
5780
5781 /* Create a memory device context for IMG->pixmap. */
5782 frame_dc = get_frame_dc (f);
5783 ximg = CreateCompatibleDC (frame_dc);
5784 release_frame_dc (f, frame_dc);
5785 prev = SelectObject (ximg, img->pixmap);
5786 #endif /* HAVE_NTGUI */
5787
5788 /* Determine the background color of ximg. If HOW is `(R G B)'
5789 take that as color. Otherwise, use the image's background color. */
5790 use_img_background = 1;
5791
5792 if (CONSP (how))
5793 {
5794 int rgb[3], i;
5795
5796 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5797 {
5798 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5799 how = XCDR (how);
5800 }
5801
5802 if (i == 3 && NILP (how))
5803 {
5804 char color_name[30];
5805 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5806 bg = (
5807 #ifdef HAVE_NTGUI
5808 0x00ffffff & /* Filter out palette info. */
5809 #endif /* HAVE_NTGUI */
5810 x_alloc_image_color (f, img, build_string (color_name), 0));
5811 use_img_background = 0;
5812 }
5813 }
5814
5815 if (use_img_background)
5816 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5817
5818 /* Set all bits in mask_img to 1 whose color in ximg is different
5819 from the background color bg. */
5820 #ifndef HAVE_NTGUI
5821 for (y = 0; y < img->height; ++y)
5822 for (x = 0; x < img->width; ++x)
5823 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5824 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5825
5826 /* Fill in the background_transparent field while we have the mask handy. */
5827 image_background_transparent (img, f, mask_img);
5828
5829 /* Put mask_img into img->mask. */
5830 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5831 x_destroy_x_image (mask_img);
5832
5833 #else
5834 for (y = 0; y < img->height; ++y)
5835 for (x = 0; x < img->width; ++x)
5836 {
5837 COLORREF p = GetPixel (ximg, x, y);
5838 if (p != bg)
5839 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5840 }
5841
5842 /* Create the mask image. */
5843 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5844 mask_img);
5845 /* Fill in the background_transparent field while we have the mask handy. */
5846 SelectObject (ximg, img->mask);
5847 image_background_transparent (img, f, ximg);
5848
5849 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5850 xfree (mask_img);
5851 #endif /* HAVE_NTGUI */
5852
5853 Destroy_Image (ximg, prev);
5854
5855 return 1;
5856 }
5857
5858 \f
5859 /***********************************************************************
5860 PBM (mono, gray, color)
5861 ***********************************************************************/
5862
5863 static int pbm_image_p P_ ((Lisp_Object object));
5864 static int pbm_load P_ ((struct frame *f, struct image *img));
5865 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5866
5867 /* The symbol `pbm' identifying images of this type. */
5868
5869 Lisp_Object Qpbm;
5870
5871 /* Indices of image specification fields in gs_format, below. */
5872
5873 enum pbm_keyword_index
5874 {
5875 PBM_TYPE,
5876 PBM_FILE,
5877 PBM_DATA,
5878 PBM_ASCENT,
5879 PBM_MARGIN,
5880 PBM_RELIEF,
5881 PBM_ALGORITHM,
5882 PBM_HEURISTIC_MASK,
5883 PBM_MASK,
5884 PBM_FOREGROUND,
5885 PBM_BACKGROUND,
5886 PBM_LAST
5887 };
5888
5889 /* Vector of image_keyword structures describing the format
5890 of valid user-defined image specifications. */
5891
5892 static struct image_keyword pbm_format[PBM_LAST] =
5893 {
5894 {":type", IMAGE_SYMBOL_VALUE, 1},
5895 {":file", IMAGE_STRING_VALUE, 0},
5896 {":data", IMAGE_STRING_VALUE, 0},
5897 {":ascent", IMAGE_ASCENT_VALUE, 0},
5898 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5899 {":relief", IMAGE_INTEGER_VALUE, 0},
5900 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5901 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5902 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5903 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5904 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5905 };
5906
5907 /* Structure describing the image type `pbm'. */
5908
5909 static struct image_type pbm_type =
5910 {
5911 &Qpbm,
5912 pbm_image_p,
5913 pbm_load,
5914 x_clear_image,
5915 NULL
5916 };
5917
5918
5919 /* Return non-zero if OBJECT is a valid PBM image specification. */
5920
5921 static int
5922 pbm_image_p (object)
5923 Lisp_Object object;
5924 {
5925 struct image_keyword fmt[PBM_LAST];
5926
5927 bcopy (pbm_format, fmt, sizeof fmt);
5928
5929 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5930 return 0;
5931
5932 /* Must specify either :data or :file. */
5933 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5934 }
5935
5936
5937 /* Scan a decimal number from *S and return it. Advance *S while
5938 reading the number. END is the end of the string. Value is -1 at
5939 end of input. */
5940
5941 static int
5942 pbm_scan_number (s, end)
5943 unsigned char **s, *end;
5944 {
5945 int c = 0, val = -1;
5946
5947 while (*s < end)
5948 {
5949 /* Skip white-space. */
5950 while (*s < end && (c = *(*s)++, isspace (c)))
5951 ;
5952
5953 if (c == '#')
5954 {
5955 /* Skip comment to end of line. */
5956 while (*s < end && (c = *(*s)++, c != '\n'))
5957 ;
5958 }
5959 else if (isdigit (c))
5960 {
5961 /* Read decimal number. */
5962 val = c - '0';
5963 while (*s < end && (c = *(*s)++, isdigit (c)))
5964 val = 10 * val + c - '0';
5965 break;
5966 }
5967 else
5968 break;
5969 }
5970
5971 return val;
5972 }
5973
5974
5975 #ifdef HAVE_NTGUI
5976 #if 0 /* Unused. ++kfs */
5977
5978 /* Read FILE into memory. Value is a pointer to a buffer allocated
5979 with xmalloc holding FILE's contents. Value is null if an error
5980 occurred. *SIZE is set to the size of the file. */
5981
5982 static char *
5983 pbm_read_file (file, size)
5984 Lisp_Object file;
5985 int *size;
5986 {
5987 FILE *fp = NULL;
5988 char *buf = NULL;
5989 struct stat st;
5990
5991 if (stat (SDATA (file), &st) == 0
5992 && (fp = fopen (SDATA (file), "rb")) != NULL
5993 && (buf = (char *) xmalloc (st.st_size),
5994 fread (buf, 1, st.st_size, fp) == st.st_size))
5995 {
5996 *size = st.st_size;
5997 fclose (fp);
5998 }
5999 else
6000 {
6001 if (fp)
6002 fclose (fp);
6003 if (buf)
6004 {
6005 xfree (buf);
6006 buf = NULL;
6007 }
6008 }
6009
6010 return buf;
6011 }
6012 #endif
6013 #endif /* HAVE_NTGUI */
6014
6015 /* Load PBM image IMG for use on frame F. */
6016
6017 static int
6018 pbm_load (f, img)
6019 struct frame *f;
6020 struct image *img;
6021 {
6022 int raw_p, x, y;
6023 int width, height, max_color_idx = 0;
6024 XImagePtr ximg;
6025 Lisp_Object file, specified_file;
6026 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
6027 struct gcpro gcpro1;
6028 unsigned char *contents = NULL;
6029 unsigned char *end, *p;
6030 int size;
6031
6032 specified_file = image_spec_value (img->spec, QCfile, NULL);
6033 file = Qnil;
6034 GCPRO1 (file);
6035
6036 if (STRINGP (specified_file))
6037 {
6038 file = x_find_image_file (specified_file);
6039 if (!STRINGP (file))
6040 {
6041 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6042 UNGCPRO;
6043 return 0;
6044 }
6045
6046 contents = slurp_file (SDATA (file), &size);
6047 if (contents == NULL)
6048 {
6049 image_error ("Error reading `%s'", file, Qnil);
6050 UNGCPRO;
6051 return 0;
6052 }
6053
6054 p = contents;
6055 end = contents + size;
6056 }
6057 else
6058 {
6059 Lisp_Object data;
6060 data = image_spec_value (img->spec, QCdata, NULL);
6061 p = SDATA (data);
6062 end = p + SBYTES (data);
6063 }
6064
6065 /* Check magic number. */
6066 if (end - p < 2 || *p++ != 'P')
6067 {
6068 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6069 error:
6070 xfree (contents);
6071 UNGCPRO;
6072 return 0;
6073 }
6074
6075 switch (*p++)
6076 {
6077 case '1':
6078 raw_p = 0, type = PBM_MONO;
6079 break;
6080
6081 case '2':
6082 raw_p = 0, type = PBM_GRAY;
6083 break;
6084
6085 case '3':
6086 raw_p = 0, type = PBM_COLOR;
6087 break;
6088
6089 case '4':
6090 raw_p = 1, type = PBM_MONO;
6091 break;
6092
6093 case '5':
6094 raw_p = 1, type = PBM_GRAY;
6095 break;
6096
6097 case '6':
6098 raw_p = 1, type = PBM_COLOR;
6099 break;
6100
6101 default:
6102 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6103 goto error;
6104 }
6105
6106 /* Read width, height, maximum color-component. Characters
6107 starting with `#' up to the end of a line are ignored. */
6108 width = pbm_scan_number (&p, end);
6109 height = pbm_scan_number (&p, end);
6110
6111 if (type != PBM_MONO)
6112 {
6113 max_color_idx = pbm_scan_number (&p, end);
6114 if (max_color_idx > 65535 || max_color_idx < 0)
6115 {
6116 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
6117 goto error;
6118 }
6119 }
6120
6121 if (!check_image_size (f, width, height))
6122 {
6123 image_error ("Invalid image size", Qnil, Qnil);
6124 goto error;
6125 }
6126
6127 if (!x_create_x_image_and_pixmap (f, width, height, 0,
6128 &ximg, &img->pixmap))
6129 goto error;
6130
6131 /* Initialize the color hash table. */
6132 init_color_table ();
6133
6134 if (type == PBM_MONO)
6135 {
6136 int c = 0, g;
6137 struct image_keyword fmt[PBM_LAST];
6138 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
6139 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
6140
6141 /* Parse the image specification. */
6142 bcopy (pbm_format, fmt, sizeof fmt);
6143 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
6144
6145 /* Get foreground and background colors, maybe allocate colors. */
6146 if (fmt[PBM_FOREGROUND].count
6147 && STRINGP (fmt[PBM_FOREGROUND].value))
6148 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
6149 if (fmt[PBM_BACKGROUND].count
6150 && STRINGP (fmt[PBM_BACKGROUND].value))
6151 {
6152 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
6153 img->background = bg;
6154 img->background_valid = 1;
6155 }
6156
6157 for (y = 0; y < height; ++y)
6158 for (x = 0; x < width; ++x)
6159 {
6160 if (raw_p)
6161 {
6162 if ((x & 7) == 0)
6163 {
6164 if (p >= end)
6165 {
6166 x_destroy_x_image (ximg);
6167 x_clear_image (f, img);
6168 image_error ("Invalid image size in image `%s'",
6169 img->spec, Qnil);
6170 goto error;
6171 }
6172 c = *p++;
6173 }
6174 g = c & 0x80;
6175 c <<= 1;
6176 }
6177 else
6178 g = pbm_scan_number (&p, end);
6179
6180 XPutPixel (ximg, x, y, g ? fg : bg);
6181 }
6182 }
6183 else
6184 {
6185 int expected_size = height * width;
6186 if (max_color_idx > 255)
6187 expected_size *= 2;
6188 if (type == PBM_COLOR)
6189 expected_size *= 3;
6190
6191 if (raw_p && p + expected_size > end)
6192 {
6193 x_destroy_x_image (ximg);
6194 x_clear_image (f, img);
6195 image_error ("Invalid image size in image `%s'",
6196 img->spec, Qnil);
6197 goto error;
6198 }
6199
6200 for (y = 0; y < height; ++y)
6201 for (x = 0; x < width; ++x)
6202 {
6203 int r, g, b;
6204
6205 if (type == PBM_GRAY && raw_p)
6206 {
6207 r = g = b = *p++;
6208 if (max_color_idx > 255)
6209 r = g = b = r * 256 + *p++;
6210 }
6211 else if (type == PBM_GRAY)
6212 r = g = b = pbm_scan_number (&p, end);
6213 else if (raw_p)
6214 {
6215 r = *p++;
6216 if (max_color_idx > 255)
6217 r = r * 256 + *p++;
6218 g = *p++;
6219 if (max_color_idx > 255)
6220 g = g * 256 + *p++;
6221 b = *p++;
6222 if (max_color_idx > 255)
6223 b = b * 256 + *p++;
6224 }
6225 else
6226 {
6227 r = pbm_scan_number (&p, end);
6228 g = pbm_scan_number (&p, end);
6229 b = pbm_scan_number (&p, end);
6230 }
6231
6232 if (r < 0 || g < 0 || b < 0)
6233 {
6234 x_destroy_x_image (ximg);
6235 image_error ("Invalid pixel value in image `%s'",
6236 img->spec, Qnil);
6237 goto error;
6238 }
6239
6240 /* RGB values are now in the range 0..max_color_idx.
6241 Scale this to the range 0..0xffff supported by X. */
6242 r = (double) r * 65535 / max_color_idx;
6243 g = (double) g * 65535 / max_color_idx;
6244 b = (double) b * 65535 / max_color_idx;
6245 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6246 }
6247 }
6248
6249 #ifdef COLOR_TABLE_SUPPORT
6250 /* Store in IMG->colors the colors allocated for the image, and
6251 free the color table. */
6252 img->colors = colors_in_color_table (&img->ncolors);
6253 free_color_table ();
6254 #endif /* COLOR_TABLE_SUPPORT */
6255
6256 img->width = width;
6257 img->height = height;
6258
6259 /* Maybe fill in the background field while we have ximg handy. */
6260
6261 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6262 /* Casting avoids a GCC warning. */
6263 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6264
6265 /* Put the image into a pixmap. */
6266 x_put_x_image (f, ximg, img->pixmap, width, height);
6267 x_destroy_x_image (ximg);
6268
6269 /* X and W32 versions did it here, MAC version above. ++kfs
6270 img->width = width;
6271 img->height = height; */
6272
6273 UNGCPRO;
6274 xfree (contents);
6275 return 1;
6276 }
6277
6278 \f
6279 /***********************************************************************
6280 PNG
6281 ***********************************************************************/
6282
6283 #if defined (HAVE_PNG) || defined (MAC_OS)
6284
6285 /* Function prototypes. */
6286
6287 static int png_image_p P_ ((Lisp_Object object));
6288 static int png_load P_ ((struct frame *f, struct image *img));
6289
6290 /* The symbol `png' identifying images of this type. */
6291
6292 Lisp_Object Qpng;
6293
6294 /* Indices of image specification fields in png_format, below. */
6295
6296 enum png_keyword_index
6297 {
6298 PNG_TYPE,
6299 PNG_DATA,
6300 PNG_FILE,
6301 PNG_ASCENT,
6302 PNG_MARGIN,
6303 PNG_RELIEF,
6304 PNG_ALGORITHM,
6305 PNG_HEURISTIC_MASK,
6306 PNG_MASK,
6307 PNG_BACKGROUND,
6308 PNG_LAST
6309 };
6310
6311 /* Vector of image_keyword structures describing the format
6312 of valid user-defined image specifications. */
6313
6314 static struct image_keyword png_format[PNG_LAST] =
6315 {
6316 {":type", IMAGE_SYMBOL_VALUE, 1},
6317 {":data", IMAGE_STRING_VALUE, 0},
6318 {":file", IMAGE_STRING_VALUE, 0},
6319 {":ascent", IMAGE_ASCENT_VALUE, 0},
6320 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6321 {":relief", IMAGE_INTEGER_VALUE, 0},
6322 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6323 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6324 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6325 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6326 };
6327
6328 /* Structure describing the image type `png'. */
6329
6330 static struct image_type png_type =
6331 {
6332 &Qpng,
6333 png_image_p,
6334 png_load,
6335 x_clear_image,
6336 NULL
6337 };
6338
6339 /* Return non-zero if OBJECT is a valid PNG image specification. */
6340
6341 static int
6342 png_image_p (object)
6343 Lisp_Object object;
6344 {
6345 struct image_keyword fmt[PNG_LAST];
6346 bcopy (png_format, fmt, sizeof fmt);
6347
6348 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
6349 return 0;
6350
6351 /* Must specify either the :data or :file keyword. */
6352 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6353 }
6354
6355 #endif /* HAVE_PNG || MAC_OS */
6356
6357
6358 #ifdef HAVE_PNG
6359
6360 #if defined HAVE_LIBPNG_PNG_H
6361 # include <libpng/png.h>
6362 #else
6363 # include <png.h>
6364 #endif
6365
6366 #ifdef HAVE_NTGUI
6367 /* PNG library details. */
6368
6369 DEF_IMGLIB_FN (png_get_io_ptr);
6370 DEF_IMGLIB_FN (png_check_sig);
6371 DEF_IMGLIB_FN (png_create_read_struct);
6372 DEF_IMGLIB_FN (png_create_info_struct);
6373 DEF_IMGLIB_FN (png_destroy_read_struct);
6374 DEF_IMGLIB_FN (png_set_read_fn);
6375 DEF_IMGLIB_FN (png_set_sig_bytes);
6376 DEF_IMGLIB_FN (png_read_info);
6377 DEF_IMGLIB_FN (png_get_IHDR);
6378 DEF_IMGLIB_FN (png_get_valid);
6379 DEF_IMGLIB_FN (png_set_strip_16);
6380 DEF_IMGLIB_FN (png_set_expand);
6381 DEF_IMGLIB_FN (png_set_gray_to_rgb);
6382 DEF_IMGLIB_FN (png_set_background);
6383 DEF_IMGLIB_FN (png_get_bKGD);
6384 DEF_IMGLIB_FN (png_read_update_info);
6385 DEF_IMGLIB_FN (png_get_channels);
6386 DEF_IMGLIB_FN (png_get_rowbytes);
6387 DEF_IMGLIB_FN (png_read_image);
6388 DEF_IMGLIB_FN (png_read_end);
6389 DEF_IMGLIB_FN (png_error);
6390
6391 static int
6392 init_png_functions (Lisp_Object libraries)
6393 {
6394 HMODULE library;
6395
6396 /* Try loading libpng under probable names. */
6397 if (!(library = w32_delayed_load (libraries, Qpng)))
6398 return 0;
6399
6400 LOAD_IMGLIB_FN (library, png_get_io_ptr);
6401 LOAD_IMGLIB_FN (library, png_check_sig);
6402 LOAD_IMGLIB_FN (library, png_create_read_struct);
6403 LOAD_IMGLIB_FN (library, png_create_info_struct);
6404 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
6405 LOAD_IMGLIB_FN (library, png_set_read_fn);
6406 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
6407 LOAD_IMGLIB_FN (library, png_read_info);
6408 LOAD_IMGLIB_FN (library, png_get_IHDR);
6409 LOAD_IMGLIB_FN (library, png_get_valid);
6410 LOAD_IMGLIB_FN (library, png_set_strip_16);
6411 LOAD_IMGLIB_FN (library, png_set_expand);
6412 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
6413 LOAD_IMGLIB_FN (library, png_set_background);
6414 LOAD_IMGLIB_FN (library, png_get_bKGD);
6415 LOAD_IMGLIB_FN (library, png_read_update_info);
6416 LOAD_IMGLIB_FN (library, png_get_channels);
6417 LOAD_IMGLIB_FN (library, png_get_rowbytes);
6418 LOAD_IMGLIB_FN (library, png_read_image);
6419 LOAD_IMGLIB_FN (library, png_read_end);
6420 LOAD_IMGLIB_FN (library, png_error);
6421 return 1;
6422 }
6423 #else
6424
6425 #define fn_png_get_io_ptr png_get_io_ptr
6426 #define fn_png_check_sig png_check_sig
6427 #define fn_png_create_read_struct png_create_read_struct
6428 #define fn_png_create_info_struct png_create_info_struct
6429 #define fn_png_destroy_read_struct png_destroy_read_struct
6430 #define fn_png_set_read_fn png_set_read_fn
6431 #define fn_png_set_sig_bytes png_set_sig_bytes
6432 #define fn_png_read_info png_read_info
6433 #define fn_png_get_IHDR png_get_IHDR
6434 #define fn_png_get_valid png_get_valid
6435 #define fn_png_set_strip_16 png_set_strip_16
6436 #define fn_png_set_expand png_set_expand
6437 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6438 #define fn_png_set_background png_set_background
6439 #define fn_png_get_bKGD png_get_bKGD
6440 #define fn_png_read_update_info png_read_update_info
6441 #define fn_png_get_channels png_get_channels
6442 #define fn_png_get_rowbytes png_get_rowbytes
6443 #define fn_png_read_image png_read_image
6444 #define fn_png_read_end png_read_end
6445 #define fn_png_error png_error
6446
6447 #endif /* HAVE_NTGUI */
6448
6449 /* Error and warning handlers installed when the PNG library
6450 is initialized. */
6451
6452 static void
6453 my_png_error (png_ptr, msg)
6454 png_struct *png_ptr;
6455 char *msg;
6456 {
6457 xassert (png_ptr != NULL);
6458 image_error ("PNG error: %s", build_string (msg), Qnil);
6459 longjmp (png_ptr->jmpbuf, 1);
6460 }
6461
6462
6463 static void
6464 my_png_warning (png_ptr, msg)
6465 png_struct *png_ptr;
6466 char *msg;
6467 {
6468 xassert (png_ptr != NULL);
6469 image_error ("PNG warning: %s", build_string (msg), Qnil);
6470 }
6471
6472 /* Memory source for PNG decoding. */
6473
6474 struct png_memory_storage
6475 {
6476 unsigned char *bytes; /* The data */
6477 size_t len; /* How big is it? */
6478 int index; /* Where are we? */
6479 };
6480
6481
6482 /* Function set as reader function when reading PNG image from memory.
6483 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6484 bytes from the input to DATA. */
6485
6486 static void
6487 png_read_from_memory (png_ptr, data, length)
6488 png_structp png_ptr;
6489 png_bytep data;
6490 png_size_t length;
6491 {
6492 struct png_memory_storage *tbr
6493 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
6494
6495 if (length > tbr->len - tbr->index)
6496 fn_png_error (png_ptr, "Read error");
6497
6498 bcopy (tbr->bytes + tbr->index, data, length);
6499 tbr->index = tbr->index + length;
6500 }
6501
6502
6503 /* Function set as reader function when reading PNG image from a file.
6504 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6505 bytes from the input to DATA. */
6506
6507 static void
6508 png_read_from_file (png_ptr, data, length)
6509 png_structp png_ptr;
6510 png_bytep data;
6511 png_size_t length;
6512 {
6513 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
6514
6515 if (fread (data, 1, length, fp) < length)
6516 fn_png_error (png_ptr, "Read error");
6517 }
6518
6519
6520 /* Load PNG image IMG for use on frame F. Value is non-zero if
6521 successful. */
6522
6523 static int
6524 png_load (f, img)
6525 struct frame *f;
6526 struct image *img;
6527 {
6528 Lisp_Object file, specified_file;
6529 Lisp_Object specified_data;
6530 int x, y, i;
6531 XImagePtr ximg, mask_img = NULL;
6532 struct gcpro gcpro1;
6533 png_struct *png_ptr = NULL;
6534 png_info *info_ptr = NULL, *end_info = NULL;
6535 FILE *volatile fp = NULL;
6536 png_byte sig[8];
6537 png_byte * volatile pixels = NULL;
6538 png_byte ** volatile rows = NULL;
6539 png_uint_32 width, height;
6540 int bit_depth, color_type, interlace_type;
6541 png_byte channels;
6542 png_uint_32 row_bytes;
6543 int transparent_p;
6544 struct png_memory_storage tbr; /* Data to be read */
6545
6546 /* Find out what file to load. */
6547 specified_file = image_spec_value (img->spec, QCfile, NULL);
6548 specified_data = image_spec_value (img->spec, QCdata, NULL);
6549 file = Qnil;
6550 GCPRO1 (file);
6551
6552 if (NILP (specified_data))
6553 {
6554 file = x_find_image_file (specified_file);
6555 if (!STRINGP (file))
6556 {
6557 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6558 UNGCPRO;
6559 return 0;
6560 }
6561
6562 /* Open the image file. */
6563 fp = fopen (SDATA (file), "rb");
6564 if (!fp)
6565 {
6566 image_error ("Cannot open image file `%s'", file, Qnil);
6567 UNGCPRO;
6568 return 0;
6569 }
6570
6571 /* Check PNG signature. */
6572 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6573 || !fn_png_check_sig (sig, sizeof sig))
6574 {
6575 image_error ("Not a PNG file: `%s'", file, Qnil);
6576 UNGCPRO;
6577 fclose (fp);
6578 return 0;
6579 }
6580 }
6581 else
6582 {
6583 /* Read from memory. */
6584 tbr.bytes = SDATA (specified_data);
6585 tbr.len = SBYTES (specified_data);
6586 tbr.index = 0;
6587
6588 /* Check PNG signature. */
6589 if (tbr.len < sizeof sig
6590 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6591 {
6592 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6593 UNGCPRO;
6594 return 0;
6595 }
6596
6597 /* Need to skip past the signature. */
6598 tbr.bytes += sizeof (sig);
6599 }
6600
6601 /* Initialize read and info structs for PNG lib. Casting return
6602 value avoids a GCC warning on W32. */
6603 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6604 NULL, my_png_error,
6605 my_png_warning);
6606 if (!png_ptr)
6607 {
6608 if (fp) fclose (fp);
6609 UNGCPRO;
6610 return 0;
6611 }
6612
6613 /* Casting return value avoids a GCC warning on W32. */
6614 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6615 if (!info_ptr)
6616 {
6617 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6618 if (fp) fclose (fp);
6619 UNGCPRO;
6620 return 0;
6621 }
6622
6623 /* Casting return value avoids a GCC warning on W32. */
6624 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6625 if (!end_info)
6626 {
6627 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6628 if (fp) fclose (fp);
6629 UNGCPRO;
6630 return 0;
6631 }
6632
6633 /* Set error jump-back. We come back here when the PNG library
6634 detects an error. */
6635 if (setjmp (png_ptr->jmpbuf))
6636 {
6637 error:
6638 if (png_ptr)
6639 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6640 xfree (pixels);
6641 xfree (rows);
6642 if (fp) fclose (fp);
6643 UNGCPRO;
6644 return 0;
6645 }
6646
6647 /* Read image info. */
6648 if (!NILP (specified_data))
6649 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6650 else
6651 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6652
6653 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6654 fn_png_read_info (png_ptr, info_ptr);
6655 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6656 &interlace_type, NULL, NULL);
6657
6658 if (!check_image_size (f, width, height))
6659 goto error;
6660
6661 /* If image contains simply transparency data, we prefer to
6662 construct a clipping mask. */
6663 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6664 transparent_p = 1;
6665 else
6666 transparent_p = 0;
6667
6668 /* This function is easier to write if we only have to handle
6669 one data format: RGB or RGBA with 8 bits per channel. Let's
6670 transform other formats into that format. */
6671
6672 /* Strip more than 8 bits per channel. */
6673 if (bit_depth == 16)
6674 fn_png_set_strip_16 (png_ptr);
6675
6676 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6677 if available. */
6678 fn_png_set_expand (png_ptr);
6679
6680 /* Convert grayscale images to RGB. */
6681 if (color_type == PNG_COLOR_TYPE_GRAY
6682 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6683 fn_png_set_gray_to_rgb (png_ptr);
6684
6685 /* Handle alpha channel by combining the image with a background
6686 color. Do this only if a real alpha channel is supplied. For
6687 simple transparency, we prefer a clipping mask. */
6688 if (!transparent_p)
6689 {
6690 /* png_color_16 *image_bg; */
6691 Lisp_Object specified_bg
6692 = image_spec_value (img->spec, QCbackground, NULL);
6693 int shift = (bit_depth == 16) ? 0 : 8;
6694
6695 if (STRINGP (specified_bg))
6696 /* The user specified `:background', use that. */
6697 {
6698 /* W32 version incorrectly used COLORREF here!! ++kfs */
6699 XColor color;
6700 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6701 {
6702 png_color_16 user_bg;
6703
6704 bzero (&user_bg, sizeof user_bg);
6705 user_bg.red = color.red >> shift;
6706 user_bg.green = color.green >> shift;
6707 user_bg.blue = color.blue >> shift;
6708
6709 fn_png_set_background (png_ptr, &user_bg,
6710 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6711 }
6712 }
6713 else
6714 {
6715 /* We use the current frame background, ignoring any default
6716 background color set by the image. */
6717 #ifdef HAVE_X_WINDOWS
6718 XColor color;
6719 png_color_16 frame_background;
6720
6721 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6722 x_query_color (f, &color);
6723
6724 bzero (&frame_background, sizeof frame_background);
6725 frame_background.red = color.red >> shift;
6726 frame_background.green = color.green >> shift;
6727 frame_background.blue = color.blue >> shift;
6728 #endif /* HAVE_X_WINDOWS */
6729
6730 #ifdef HAVE_NTGUI
6731 COLORREF color;
6732 png_color_16 frame_background;
6733 color = FRAME_BACKGROUND_PIXEL (f);
6734 #if 0 /* W32 TODO : Colormap support. */
6735 x_query_color (f, &color);
6736 #endif
6737 bzero (&frame_background, sizeof frame_background);
6738 frame_background.red = GetRValue (color);
6739 frame_background.green = GetGValue (color);
6740 frame_background.blue = GetBValue (color);
6741 #endif /* HAVE_NTGUI */
6742
6743 #ifdef MAC_OS
6744 unsigned long color;
6745 png_color_16 frame_background;
6746 color = FRAME_BACKGROUND_PIXEL (f);
6747 #if 0 /* MAC/W32 TODO : Colormap support. */
6748 x_query_color (f, &color);
6749 #endif
6750 bzero (&frame_background, sizeof frame_background);
6751 frame_background.red = RED_FROM_ULONG (color);
6752 frame_background.green = GREEN_FROM_ULONG (color);
6753 frame_background.blue = BLUE_FROM_ULONG (color);
6754 #endif /* MAC_OS */
6755
6756 fn_png_set_background (png_ptr, &frame_background,
6757 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6758 }
6759 }
6760
6761 /* Update info structure. */
6762 fn_png_read_update_info (png_ptr, info_ptr);
6763
6764 /* Get number of channels. Valid values are 1 for grayscale images
6765 and images with a palette, 2 for grayscale images with transparency
6766 information (alpha channel), 3 for RGB images, and 4 for RGB
6767 images with alpha channel, i.e. RGBA. If conversions above were
6768 sufficient we should only have 3 or 4 channels here. */
6769 channels = fn_png_get_channels (png_ptr, info_ptr);
6770 xassert (channels == 3 || channels == 4);
6771
6772 /* Number of bytes needed for one row of the image. */
6773 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6774
6775 /* Allocate memory for the image. */
6776 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6777 rows = (png_byte **) xmalloc (height * sizeof *rows);
6778 for (i = 0; i < height; ++i)
6779 rows[i] = pixels + i * row_bytes;
6780
6781 /* Read the entire image. */
6782 fn_png_read_image (png_ptr, rows);
6783 fn_png_read_end (png_ptr, info_ptr);
6784 if (fp)
6785 {
6786 fclose (fp);
6787 fp = NULL;
6788 }
6789
6790 /* Create the X image and pixmap. */
6791 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6792 &img->pixmap))
6793 goto error;
6794
6795 /* Create an image and pixmap serving as mask if the PNG image
6796 contains an alpha channel. */
6797 if (channels == 4
6798 && !transparent_p
6799 && !x_create_x_image_and_pixmap (f, width, height, 1,
6800 &mask_img, &img->mask))
6801 {
6802 x_destroy_x_image (ximg);
6803 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6804 img->pixmap = NO_PIXMAP;
6805 goto error;
6806 }
6807
6808 /* Fill the X image and mask from PNG data. */
6809 init_color_table ();
6810
6811 for (y = 0; y < height; ++y)
6812 {
6813 png_byte *p = rows[y];
6814
6815 for (x = 0; x < width; ++x)
6816 {
6817 unsigned r, g, b;
6818
6819 r = *p++ << 8;
6820 g = *p++ << 8;
6821 b = *p++ << 8;
6822 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6823 /* An alpha channel, aka mask channel, associates variable
6824 transparency with an image. Where other image formats
6825 support binary transparency---fully transparent or fully
6826 opaque---PNG allows up to 254 levels of partial transparency.
6827 The PNG library implements partial transparency by combining
6828 the image with a specified background color.
6829
6830 I'm not sure how to handle this here nicely: because the
6831 background on which the image is displayed may change, for
6832 real alpha channel support, it would be necessary to create
6833 a new image for each possible background.
6834
6835 What I'm doing now is that a mask is created if we have
6836 boolean transparency information. Otherwise I'm using
6837 the frame's background color to combine the image with. */
6838
6839 if (channels == 4)
6840 {
6841 if (mask_img)
6842 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6843 ++p;
6844 }
6845 }
6846 }
6847
6848 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6849 /* Set IMG's background color from the PNG image, unless the user
6850 overrode it. */
6851 {
6852 png_color_16 *bg;
6853 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6854 {
6855 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6856 img->background_valid = 1;
6857 }
6858 }
6859
6860 #ifdef COLOR_TABLE_SUPPORT
6861 /* Remember colors allocated for this image. */
6862 img->colors = colors_in_color_table (&img->ncolors);
6863 free_color_table ();
6864 #endif /* COLOR_TABLE_SUPPORT */
6865
6866 /* Clean up. */
6867 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6868 xfree (rows);
6869 xfree (pixels);
6870
6871 img->width = width;
6872 img->height = height;
6873
6874 /* Maybe fill in the background field while we have ximg handy.
6875 Casting avoids a GCC warning. */
6876 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6877
6878 /* Put the image into the pixmap, then free the X image and its buffer. */
6879 x_put_x_image (f, ximg, img->pixmap, width, height);
6880 x_destroy_x_image (ximg);
6881
6882 /* Same for the mask. */
6883 if (mask_img)
6884 {
6885 /* Fill in the background_transparent field while we have the
6886 mask handy. Casting avoids a GCC warning. */
6887 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6888
6889 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6890 x_destroy_x_image (mask_img);
6891 }
6892
6893 UNGCPRO;
6894 return 1;
6895 }
6896
6897 #else /* HAVE_PNG */
6898
6899 #ifdef MAC_OS
6900 static int
6901 png_load (f, img)
6902 struct frame *f;
6903 struct image *img;
6904 {
6905 #if USE_MAC_IMAGE_IO
6906 return image_load_image_io (f, img, kUTTypePNG);
6907 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6908 return image_load_quartz2d (f, img, 1);
6909 #else
6910 return image_load_quicktime (f, img, kQTFileTypePNG);
6911 #endif
6912 }
6913 #endif /* MAC_OS */
6914
6915 #endif /* !HAVE_PNG */
6916
6917
6918 \f
6919 /***********************************************************************
6920 JPEG
6921 ***********************************************************************/
6922
6923 #if defined (HAVE_JPEG) || defined (MAC_OS)
6924
6925 static int jpeg_image_p P_ ((Lisp_Object object));
6926 static int jpeg_load P_ ((struct frame *f, struct image *img));
6927
6928 /* The symbol `jpeg' identifying images of this type. */
6929
6930 Lisp_Object Qjpeg;
6931
6932 /* Indices of image specification fields in gs_format, below. */
6933
6934 enum jpeg_keyword_index
6935 {
6936 JPEG_TYPE,
6937 JPEG_DATA,
6938 JPEG_FILE,
6939 JPEG_ASCENT,
6940 JPEG_MARGIN,
6941 JPEG_RELIEF,
6942 JPEG_ALGORITHM,
6943 JPEG_HEURISTIC_MASK,
6944 JPEG_MASK,
6945 JPEG_BACKGROUND,
6946 JPEG_LAST
6947 };
6948
6949 /* Vector of image_keyword structures describing the format
6950 of valid user-defined image specifications. */
6951
6952 static struct image_keyword jpeg_format[JPEG_LAST] =
6953 {
6954 {":type", IMAGE_SYMBOL_VALUE, 1},
6955 {":data", IMAGE_STRING_VALUE, 0},
6956 {":file", IMAGE_STRING_VALUE, 0},
6957 {":ascent", IMAGE_ASCENT_VALUE, 0},
6958 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6959 {":relief", IMAGE_INTEGER_VALUE, 0},
6960 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6961 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6962 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6963 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6964 };
6965
6966 /* Structure describing the image type `jpeg'. */
6967
6968 static struct image_type jpeg_type =
6969 {
6970 &Qjpeg,
6971 jpeg_image_p,
6972 jpeg_load,
6973 x_clear_image,
6974 NULL
6975 };
6976
6977 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6978
6979 static int
6980 jpeg_image_p (object)
6981 Lisp_Object object;
6982 {
6983 struct image_keyword fmt[JPEG_LAST];
6984
6985 bcopy (jpeg_format, fmt, sizeof fmt);
6986
6987 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6988 return 0;
6989
6990 /* Must specify either the :data or :file keyword. */
6991 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6992 }
6993
6994 #endif /* HAVE_JPEG || MAC_OS */
6995
6996 #ifdef HAVE_JPEG
6997
6998 /* Work around a warning about HAVE_STDLIB_H being redefined in
6999 jconfig.h. */
7000 #ifdef HAVE_STDLIB_H
7001 #define HAVE_STDLIB_H_1
7002 #undef HAVE_STDLIB_H
7003 #endif /* HAVE_STLIB_H */
7004
7005 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
7006 /* In older releases of the jpeg library, jpeglib.h will define boolean
7007 differently depending on __WIN32__, so make sure it is defined. */
7008 #define __WIN32__ 1
7009 #endif
7010
7011 #include <jpeglib.h>
7012 #include <jerror.h>
7013 #include <setjmp.h>
7014
7015 #ifdef HAVE_STLIB_H_1
7016 #define HAVE_STDLIB_H 1
7017 #endif
7018
7019 #ifdef HAVE_NTGUI
7020
7021 /* JPEG library details. */
7022 DEF_IMGLIB_FN (jpeg_CreateDecompress);
7023 DEF_IMGLIB_FN (jpeg_start_decompress);
7024 DEF_IMGLIB_FN (jpeg_finish_decompress);
7025 DEF_IMGLIB_FN (jpeg_destroy_decompress);
7026 DEF_IMGLIB_FN (jpeg_read_header);
7027 DEF_IMGLIB_FN (jpeg_read_scanlines);
7028 DEF_IMGLIB_FN (jpeg_std_error);
7029 DEF_IMGLIB_FN (jpeg_resync_to_restart);
7030
7031 static int
7032 init_jpeg_functions (Lisp_Object libraries)
7033 {
7034 HMODULE library;
7035
7036 if (!(library = w32_delayed_load (libraries, Qjpeg)))
7037 return 0;
7038
7039 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
7040 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
7041 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
7042 LOAD_IMGLIB_FN (library, jpeg_read_header);
7043 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
7044 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
7045 LOAD_IMGLIB_FN (library, jpeg_std_error);
7046 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
7047 return 1;
7048 }
7049
7050 /* Wrapper since we can't directly assign the function pointer
7051 to another function pointer that was declared more completely easily. */
7052 static boolean
7053 jpeg_resync_to_restart_wrapper (cinfo, desired)
7054 j_decompress_ptr cinfo;
7055 int desired;
7056 {
7057 return fn_jpeg_resync_to_restart (cinfo, desired);
7058 }
7059
7060 #else
7061
7062 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7063 #define fn_jpeg_start_decompress jpeg_start_decompress
7064 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7065 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7066 #define fn_jpeg_read_header jpeg_read_header
7067 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7068 #define fn_jpeg_std_error jpeg_std_error
7069 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7070
7071 #endif /* HAVE_NTGUI */
7072
7073 struct my_jpeg_error_mgr
7074 {
7075 struct jpeg_error_mgr pub;
7076 jmp_buf setjmp_buffer;
7077 };
7078
7079
7080 static void
7081 my_error_exit (cinfo)
7082 j_common_ptr cinfo;
7083 {
7084 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7085 longjmp (mgr->setjmp_buffer, 1);
7086 }
7087
7088
7089 /* Init source method for JPEG data source manager. Called by
7090 jpeg_read_header() before any data is actually read. See
7091 libjpeg.doc from the JPEG lib distribution. */
7092
7093 static void
7094 our_common_init_source (cinfo)
7095 j_decompress_ptr cinfo;
7096 {
7097 }
7098
7099
7100 /* Method to terminate data source. Called by
7101 jpeg_finish_decompress() after all data has been processed. */
7102
7103 static void
7104 our_common_term_source (cinfo)
7105 j_decompress_ptr cinfo;
7106 {
7107 }
7108
7109
7110 /* Fill input buffer method for JPEG data source manager. Called
7111 whenever more data is needed. We read the whole image in one step,
7112 so this only adds a fake end of input marker at the end. */
7113
7114 static JOCTET our_memory_buffer[2];
7115
7116 static boolean
7117 our_memory_fill_input_buffer (cinfo)
7118 j_decompress_ptr cinfo;
7119 {
7120 /* Insert a fake EOI marker. */
7121 struct jpeg_source_mgr *src = cinfo->src;
7122
7123 our_memory_buffer[0] = (JOCTET) 0xFF;
7124 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
7125
7126 src->next_input_byte = our_memory_buffer;
7127 src->bytes_in_buffer = 2;
7128 return 1;
7129 }
7130
7131
7132 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7133 is the JPEG data source manager. */
7134
7135 static void
7136 our_memory_skip_input_data (cinfo, num_bytes)
7137 j_decompress_ptr cinfo;
7138 long num_bytes;
7139 {
7140 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7141
7142 if (src)
7143 {
7144 if (num_bytes > src->bytes_in_buffer)
7145 ERREXIT (cinfo, JERR_INPUT_EOF);
7146
7147 src->bytes_in_buffer -= num_bytes;
7148 src->next_input_byte += num_bytes;
7149 }
7150 }
7151
7152
7153 /* Set up the JPEG lib for reading an image from DATA which contains
7154 LEN bytes. CINFO is the decompression info structure created for
7155 reading the image. */
7156
7157 static void
7158 jpeg_memory_src (cinfo, data, len)
7159 j_decompress_ptr cinfo;
7160 JOCTET *data;
7161 unsigned int len;
7162 {
7163 struct jpeg_source_mgr *src;
7164
7165 if (cinfo->src == NULL)
7166 {
7167 /* First time for this JPEG object? */
7168 cinfo->src = (struct jpeg_source_mgr *)
7169 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7170 sizeof (struct jpeg_source_mgr));
7171 src = (struct jpeg_source_mgr *) cinfo->src;
7172 src->next_input_byte = data;
7173 }
7174
7175 src = (struct jpeg_source_mgr *) cinfo->src;
7176 src->init_source = our_common_init_source;
7177 src->fill_input_buffer = our_memory_fill_input_buffer;
7178 src->skip_input_data = our_memory_skip_input_data;
7179 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7180 src->term_source = our_common_term_source;
7181 src->bytes_in_buffer = len;
7182 src->next_input_byte = data;
7183 }
7184
7185
7186 struct jpeg_stdio_mgr
7187 {
7188 struct jpeg_source_mgr mgr;
7189 boolean finished;
7190 FILE *file;
7191 JOCTET *buffer;
7192 };
7193
7194
7195 /* Size of buffer to read JPEG from file.
7196 Not too big, as we want to use alloc_small. */
7197 #define JPEG_STDIO_BUFFER_SIZE 8192
7198
7199
7200 /* Fill input buffer method for JPEG data source manager. Called
7201 whenever more data is needed. The data is read from a FILE *. */
7202
7203 static boolean
7204 our_stdio_fill_input_buffer (cinfo)
7205 j_decompress_ptr cinfo;
7206 {
7207 struct jpeg_stdio_mgr *src;
7208
7209 src = (struct jpeg_stdio_mgr *) cinfo->src;
7210 if (!src->finished)
7211 {
7212 size_t bytes;
7213
7214 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
7215 if (bytes > 0)
7216 src->mgr.bytes_in_buffer = bytes;
7217 else
7218 {
7219 WARNMS (cinfo, JWRN_JPEG_EOF);
7220 src->finished = 1;
7221 src->buffer[0] = (JOCTET) 0xFF;
7222 src->buffer[1] = (JOCTET) JPEG_EOI;
7223 src->mgr.bytes_in_buffer = 2;
7224 }
7225 src->mgr.next_input_byte = src->buffer;
7226 }
7227
7228 return 1;
7229 }
7230
7231
7232 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7233 is the JPEG data source manager. */
7234
7235 static void
7236 our_stdio_skip_input_data (cinfo, num_bytes)
7237 j_decompress_ptr cinfo;
7238 long num_bytes;
7239 {
7240 struct jpeg_stdio_mgr *src;
7241 src = (struct jpeg_stdio_mgr *) cinfo->src;
7242
7243 while (num_bytes > 0 && !src->finished)
7244 {
7245 if (num_bytes <= src->mgr.bytes_in_buffer)
7246 {
7247 src->mgr.bytes_in_buffer -= num_bytes;
7248 src->mgr.next_input_byte += num_bytes;
7249 break;
7250 }
7251 else
7252 {
7253 num_bytes -= src->mgr.bytes_in_buffer;
7254 src->mgr.bytes_in_buffer = 0;
7255 src->mgr.next_input_byte = NULL;
7256
7257 our_stdio_fill_input_buffer (cinfo);
7258 }
7259 }
7260 }
7261
7262
7263 /* Set up the JPEG lib for reading an image from a FILE *.
7264 CINFO is the decompression info structure created for
7265 reading the image. */
7266
7267 static void
7268 jpeg_file_src (cinfo, fp)
7269 j_decompress_ptr cinfo;
7270 FILE *fp;
7271 {
7272 struct jpeg_stdio_mgr *src;
7273
7274 if (cinfo->src != NULL)
7275 src = (struct jpeg_stdio_mgr *) cinfo->src;
7276 else
7277 {
7278 /* First time for this JPEG object? */
7279 cinfo->src = (struct jpeg_source_mgr *)
7280 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7281 sizeof (struct jpeg_stdio_mgr));
7282 src = (struct jpeg_stdio_mgr *) cinfo->src;
7283 src->buffer = (JOCTET *)
7284 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7285 JPEG_STDIO_BUFFER_SIZE);
7286 }
7287
7288 src->file = fp;
7289 src->finished = 0;
7290 src->mgr.init_source = our_common_init_source;
7291 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
7292 src->mgr.skip_input_data = our_stdio_skip_input_data;
7293 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7294 src->mgr.term_source = our_common_term_source;
7295 src->mgr.bytes_in_buffer = 0;
7296 src->mgr.next_input_byte = NULL;
7297 }
7298
7299
7300 /* Load image IMG for use on frame F. Patterned after example.c
7301 from the JPEG lib. */
7302
7303 static int
7304 jpeg_load (f, img)
7305 struct frame *f;
7306 struct image *img;
7307 {
7308 struct jpeg_decompress_struct cinfo;
7309 struct my_jpeg_error_mgr mgr;
7310 Lisp_Object file, specified_file;
7311 Lisp_Object specified_data;
7312 FILE * volatile fp = NULL;
7313 JSAMPARRAY buffer;
7314 int row_stride, x, y;
7315 XImagePtr ximg = NULL;
7316 int rc;
7317 unsigned long *colors;
7318 int width, height;
7319 struct gcpro gcpro1;
7320
7321 /* Open the JPEG file. */
7322 specified_file = image_spec_value (img->spec, QCfile, NULL);
7323 specified_data = image_spec_value (img->spec, QCdata, NULL);
7324 file = Qnil;
7325 GCPRO1 (file);
7326
7327 if (NILP (specified_data))
7328 {
7329 file = x_find_image_file (specified_file);
7330 if (!STRINGP (file))
7331 {
7332 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7333 UNGCPRO;
7334 return 0;
7335 }
7336
7337 fp = fopen (SDATA (file), "rb");
7338 if (fp == NULL)
7339 {
7340 image_error ("Cannot open `%s'", file, Qnil);
7341 UNGCPRO;
7342 return 0;
7343 }
7344 }
7345
7346 /* Customize libjpeg's error handling to call my_error_exit when an
7347 error is detected. This function will perform a longjmp.
7348 Casting return value avoids a GCC warning on W32. */
7349 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
7350 mgr.pub.error_exit = my_error_exit;
7351
7352 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7353 {
7354 if (rc == 1)
7355 {
7356 /* Called from my_error_exit. Display a JPEG error. */
7357 char buffer[JMSG_LENGTH_MAX];
7358 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7359 image_error ("Error reading JPEG image `%s': %s", img->spec,
7360 build_string (buffer));
7361 }
7362
7363 /* Close the input file and destroy the JPEG object. */
7364 if (fp)
7365 fclose ((FILE *) fp);
7366 fn_jpeg_destroy_decompress (&cinfo);
7367
7368 /* If we already have an XImage, free that. */
7369 x_destroy_x_image (ximg);
7370
7371 /* Free pixmap and colors. */
7372 x_clear_image (f, img);
7373
7374 UNGCPRO;
7375 return 0;
7376 }
7377
7378 /* Create the JPEG decompression object. Let it read from fp.
7379 Read the JPEG image header. */
7380 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
7381
7382 if (NILP (specified_data))
7383 jpeg_file_src (&cinfo, (FILE *) fp);
7384 else
7385 jpeg_memory_src (&cinfo, SDATA (specified_data),
7386 SBYTES (specified_data));
7387
7388 fn_jpeg_read_header (&cinfo, 1);
7389
7390 /* Customize decompression so that color quantization will be used.
7391 Start decompression. */
7392 cinfo.quantize_colors = 1;
7393 fn_jpeg_start_decompress (&cinfo);
7394 width = img->width = cinfo.output_width;
7395 height = img->height = cinfo.output_height;
7396
7397 if (!check_image_size (f, width, height))
7398 {
7399 image_error ("Invalid image size", Qnil, Qnil);
7400 longjmp (mgr.setjmp_buffer, 2);
7401 }
7402
7403 /* Create X image and pixmap. */
7404 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7405 longjmp (mgr.setjmp_buffer, 2);
7406
7407 /* Allocate colors. When color quantization is used,
7408 cinfo.actual_number_of_colors has been set with the number of
7409 colors generated, and cinfo.colormap is a two-dimensional array
7410 of color indices in the range 0..cinfo.actual_number_of_colors.
7411 No more than 255 colors will be generated. */
7412 {
7413 int i, ir, ig, ib;
7414
7415 if (cinfo.out_color_components > 2)
7416 ir = 0, ig = 1, ib = 2;
7417 else if (cinfo.out_color_components > 1)
7418 ir = 0, ig = 1, ib = 0;
7419 else
7420 ir = 0, ig = 0, ib = 0;
7421
7422 /* Use the color table mechanism because it handles colors that
7423 cannot be allocated nicely. Such colors will be replaced with
7424 a default color, and we don't have to care about which colors
7425 can be freed safely, and which can't. */
7426 init_color_table ();
7427 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
7428 * sizeof *colors);
7429
7430 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
7431 {
7432 /* Multiply RGB values with 255 because X expects RGB values
7433 in the range 0..0xffff. */
7434 int r = cinfo.colormap[ir][i] << 8;
7435 int g = cinfo.colormap[ig][i] << 8;
7436 int b = cinfo.colormap[ib][i] << 8;
7437 colors[i] = lookup_rgb_color (f, r, g, b);
7438 }
7439
7440 #ifdef COLOR_TABLE_SUPPORT
7441 /* Remember those colors actually allocated. */
7442 img->colors = colors_in_color_table (&img->ncolors);
7443 free_color_table ();
7444 #endif /* COLOR_TABLE_SUPPORT */
7445 }
7446
7447 /* Read pixels. */
7448 row_stride = width * cinfo.output_components;
7449 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
7450 row_stride, 1);
7451 for (y = 0; y < height; ++y)
7452 {
7453 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
7454 for (x = 0; x < cinfo.output_width; ++x)
7455 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
7456 }
7457
7458 /* Clean up. */
7459 fn_jpeg_finish_decompress (&cinfo);
7460 fn_jpeg_destroy_decompress (&cinfo);
7461 if (fp)
7462 fclose ((FILE *) fp);
7463
7464 /* Maybe fill in the background field while we have ximg handy. */
7465 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7466 /* Casting avoids a GCC warning. */
7467 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7468
7469 /* Put the image into the pixmap. */
7470 x_put_x_image (f, ximg, img->pixmap, width, height);
7471 x_destroy_x_image (ximg);
7472 UNGCPRO;
7473 return 1;
7474 }
7475
7476 #else /* HAVE_JPEG */
7477
7478 #ifdef MAC_OS
7479 static int
7480 jpeg_load (f, img)
7481 struct frame *f;
7482 struct image *img;
7483 {
7484 #if USE_MAC_IMAGE_IO
7485 return image_load_image_io (f, img, kUTTypeJPEG);
7486 #elif defined (MAC_OSX)
7487 return image_load_quartz2d (f, img, 0);
7488 #else
7489 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7490 #endif
7491 }
7492 #endif /* MAC_OS */
7493
7494 #endif /* !HAVE_JPEG */
7495
7496
7497 \f
7498 /***********************************************************************
7499 TIFF
7500 ***********************************************************************/
7501
7502 #if defined (HAVE_TIFF) || defined (MAC_OS)
7503
7504 static int tiff_image_p P_ ((Lisp_Object object));
7505 static int tiff_load P_ ((struct frame *f, struct image *img));
7506
7507 /* The symbol `tiff' identifying images of this type. */
7508
7509 Lisp_Object Qtiff;
7510
7511 /* Indices of image specification fields in tiff_format, below. */
7512
7513 enum tiff_keyword_index
7514 {
7515 TIFF_TYPE,
7516 TIFF_DATA,
7517 TIFF_FILE,
7518 TIFF_ASCENT,
7519 TIFF_MARGIN,
7520 TIFF_RELIEF,
7521 TIFF_ALGORITHM,
7522 TIFF_HEURISTIC_MASK,
7523 TIFF_MASK,
7524 TIFF_BACKGROUND,
7525 TIFF_LAST
7526 };
7527
7528 /* Vector of image_keyword structures describing the format
7529 of valid user-defined image specifications. */
7530
7531 static struct image_keyword tiff_format[TIFF_LAST] =
7532 {
7533 {":type", IMAGE_SYMBOL_VALUE, 1},
7534 {":data", IMAGE_STRING_VALUE, 0},
7535 {":file", IMAGE_STRING_VALUE, 0},
7536 {":ascent", IMAGE_ASCENT_VALUE, 0},
7537 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7538 {":relief", IMAGE_INTEGER_VALUE, 0},
7539 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7540 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7541 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7542 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7543 };
7544
7545 /* Structure describing the image type `tiff'. */
7546
7547 static struct image_type tiff_type =
7548 {
7549 &Qtiff,
7550 tiff_image_p,
7551 tiff_load,
7552 x_clear_image,
7553 NULL
7554 };
7555
7556 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7557
7558 static int
7559 tiff_image_p (object)
7560 Lisp_Object object;
7561 {
7562 struct image_keyword fmt[TIFF_LAST];
7563 bcopy (tiff_format, fmt, sizeof fmt);
7564
7565 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
7566 return 0;
7567
7568 /* Must specify either the :data or :file keyword. */
7569 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7570 }
7571
7572 #endif /* HAVE_TIFF || MAC_OS */
7573
7574 #ifdef HAVE_TIFF
7575
7576 #include <tiffio.h>
7577
7578 #ifdef HAVE_NTGUI
7579
7580 /* TIFF library details. */
7581 DEF_IMGLIB_FN (TIFFSetErrorHandler);
7582 DEF_IMGLIB_FN (TIFFSetWarningHandler);
7583 DEF_IMGLIB_FN (TIFFOpen);
7584 DEF_IMGLIB_FN (TIFFClientOpen);
7585 DEF_IMGLIB_FN (TIFFGetField);
7586 DEF_IMGLIB_FN (TIFFReadRGBAImage);
7587 DEF_IMGLIB_FN (TIFFClose);
7588
7589 static int
7590 init_tiff_functions (Lisp_Object libraries)
7591 {
7592 HMODULE library;
7593
7594 if (!(library = w32_delayed_load (libraries, Qtiff)))
7595 return 0;
7596
7597 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
7598 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
7599 LOAD_IMGLIB_FN (library, TIFFOpen);
7600 LOAD_IMGLIB_FN (library, TIFFClientOpen);
7601 LOAD_IMGLIB_FN (library, TIFFGetField);
7602 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
7603 LOAD_IMGLIB_FN (library, TIFFClose);
7604 return 1;
7605 }
7606
7607 #else
7608
7609 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7610 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7611 #define fn_TIFFOpen TIFFOpen
7612 #define fn_TIFFClientOpen TIFFClientOpen
7613 #define fn_TIFFGetField TIFFGetField
7614 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7615 #define fn_TIFFClose TIFFClose
7616
7617 #endif /* HAVE_NTGUI */
7618
7619
7620 /* Reading from a memory buffer for TIFF images Based on the PNG
7621 memory source, but we have to provide a lot of extra functions.
7622 Blah.
7623
7624 We really only need to implement read and seek, but I am not
7625 convinced that the TIFF library is smart enough not to destroy
7626 itself if we only hand it the function pointers we need to
7627 override. */
7628
7629 typedef struct
7630 {
7631 unsigned char *bytes;
7632 size_t len;
7633 int index;
7634 }
7635 tiff_memory_source;
7636
7637 static size_t
7638 tiff_read_from_memory (data, buf, size)
7639 thandle_t data;
7640 tdata_t buf;
7641 tsize_t size;
7642 {
7643 tiff_memory_source *src = (tiff_memory_source *) data;
7644
7645 if (size > src->len - src->index)
7646 return (size_t) -1;
7647 bcopy (src->bytes + src->index, buf, size);
7648 src->index += size;
7649 return size;
7650 }
7651
7652 static size_t
7653 tiff_write_from_memory (data, buf, size)
7654 thandle_t data;
7655 tdata_t buf;
7656 tsize_t size;
7657 {
7658 return (size_t) -1;
7659 }
7660
7661 static toff_t
7662 tiff_seek_in_memory (data, off, whence)
7663 thandle_t data;
7664 toff_t off;
7665 int whence;
7666 {
7667 tiff_memory_source *src = (tiff_memory_source *) data;
7668 int idx;
7669
7670 switch (whence)
7671 {
7672 case SEEK_SET: /* Go from beginning of source. */
7673 idx = off;
7674 break;
7675
7676 case SEEK_END: /* Go from end of source. */
7677 idx = src->len + off;
7678 break;
7679
7680 case SEEK_CUR: /* Go from current position. */
7681 idx = src->index + off;
7682 break;
7683
7684 default: /* Invalid `whence'. */
7685 return -1;
7686 }
7687
7688 if (idx > src->len || idx < 0)
7689 return -1;
7690
7691 src->index = idx;
7692 return src->index;
7693 }
7694
7695 static int
7696 tiff_close_memory (data)
7697 thandle_t data;
7698 {
7699 /* NOOP */
7700 return 0;
7701 }
7702
7703 static int
7704 tiff_mmap_memory (data, pbase, psize)
7705 thandle_t data;
7706 tdata_t *pbase;
7707 toff_t *psize;
7708 {
7709 /* It is already _IN_ memory. */
7710 return 0;
7711 }
7712
7713 static void
7714 tiff_unmap_memory (data, base, size)
7715 thandle_t data;
7716 tdata_t base;
7717 toff_t size;
7718 {
7719 /* We don't need to do this. */
7720 }
7721
7722 static toff_t
7723 tiff_size_of_memory (data)
7724 thandle_t data;
7725 {
7726 return ((tiff_memory_source *) data)->len;
7727 }
7728
7729
7730 static void
7731 tiff_error_handler (title, format, ap)
7732 const char *title, *format;
7733 va_list ap;
7734 {
7735 char buf[512];
7736 int len;
7737
7738 len = sprintf (buf, "TIFF error: %s ", title);
7739 vsprintf (buf + len, format, ap);
7740 add_to_log (buf, Qnil, Qnil);
7741 }
7742
7743
7744 static void
7745 tiff_warning_handler (title, format, ap)
7746 const char *title, *format;
7747 va_list ap;
7748 {
7749 char buf[512];
7750 int len;
7751
7752 len = sprintf (buf, "TIFF warning: %s ", title);
7753 vsprintf (buf + len, format, ap);
7754 add_to_log (buf, Qnil, Qnil);
7755 }
7756
7757
7758 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7759 successful. */
7760
7761 static int
7762 tiff_load (f, img)
7763 struct frame *f;
7764 struct image *img;
7765 {
7766 Lisp_Object file, specified_file;
7767 Lisp_Object specified_data;
7768 TIFF *tiff;
7769 int width, height, x, y;
7770 uint32 *buf;
7771 int rc;
7772 XImagePtr ximg;
7773 struct gcpro gcpro1;
7774 tiff_memory_source memsrc;
7775
7776 specified_file = image_spec_value (img->spec, QCfile, NULL);
7777 specified_data = image_spec_value (img->spec, QCdata, NULL);
7778 file = Qnil;
7779 GCPRO1 (file);
7780
7781 fn_TIFFSetErrorHandler (tiff_error_handler);
7782 fn_TIFFSetWarningHandler (tiff_warning_handler);
7783
7784 if (NILP (specified_data))
7785 {
7786 /* Read from a file */
7787 file = x_find_image_file (specified_file);
7788 if (!STRINGP (file))
7789 {
7790 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7791 UNGCPRO;
7792 return 0;
7793 }
7794
7795 /* Try to open the image file. Casting return value avoids a
7796 GCC warning on W32. */
7797 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7798 if (tiff == NULL)
7799 {
7800 image_error ("Cannot open `%s'", file, Qnil);
7801 UNGCPRO;
7802 return 0;
7803 }
7804 }
7805 else
7806 {
7807 /* Memory source! */
7808 memsrc.bytes = SDATA (specified_data);
7809 memsrc.len = SBYTES (specified_data);
7810 memsrc.index = 0;
7811
7812 /* Casting return value avoids a GCC warning on W32. */
7813 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7814 (TIFFReadWriteProc) tiff_read_from_memory,
7815 (TIFFReadWriteProc) tiff_write_from_memory,
7816 tiff_seek_in_memory,
7817 tiff_close_memory,
7818 tiff_size_of_memory,
7819 tiff_mmap_memory,
7820 tiff_unmap_memory);
7821
7822 if (!tiff)
7823 {
7824 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7825 UNGCPRO;
7826 return 0;
7827 }
7828 }
7829
7830 /* Get width and height of the image, and allocate a raster buffer
7831 of width x height 32-bit values. */
7832 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7833 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7834
7835 if (!check_image_size (f, width, height))
7836 {
7837 image_error ("Invalid image size", Qnil, Qnil);
7838 UNGCPRO;
7839 return 0;
7840 }
7841
7842 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7843
7844 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7845 fn_TIFFClose (tiff);
7846 if (!rc)
7847 {
7848 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7849 xfree (buf);
7850 UNGCPRO;
7851 return 0;
7852 }
7853
7854 /* Create the X image and pixmap. */
7855 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7856 {
7857 xfree (buf);
7858 UNGCPRO;
7859 return 0;
7860 }
7861
7862 /* Initialize the color table. */
7863 init_color_table ();
7864
7865 /* Process the pixel raster. Origin is in the lower-left corner. */
7866 for (y = 0; y < height; ++y)
7867 {
7868 uint32 *row = buf + y * width;
7869
7870 for (x = 0; x < width; ++x)
7871 {
7872 uint32 abgr = row[x];
7873 int r = TIFFGetR (abgr) << 8;
7874 int g = TIFFGetG (abgr) << 8;
7875 int b = TIFFGetB (abgr) << 8;
7876 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7877 }
7878 }
7879
7880 #ifdef COLOR_TABLE_SUPPORT
7881 /* Remember the colors allocated for the image. Free the color table. */
7882 img->colors = colors_in_color_table (&img->ncolors);
7883 free_color_table ();
7884 #endif /* COLOR_TABLE_SUPPORT */
7885
7886 img->width = width;
7887 img->height = height;
7888
7889 /* Maybe fill in the background field while we have ximg handy. */
7890 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7891 /* Casting avoids a GCC warning on W32. */
7892 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7893
7894 /* Put the image into the pixmap, then free the X image and its buffer. */
7895 x_put_x_image (f, ximg, img->pixmap, width, height);
7896 x_destroy_x_image (ximg);
7897 xfree (buf);
7898
7899 UNGCPRO;
7900 return 1;
7901 }
7902
7903 #else /* HAVE_TIFF */
7904
7905 #ifdef MAC_OS
7906 static int
7907 tiff_load (f, img)
7908 struct frame *f;
7909 struct image *img;
7910 {
7911 #if USE_MAC_IMAGE_IO
7912 return image_load_image_io (f, img, kUTTypeTIFF);
7913 #else
7914 return image_load_quicktime (f, img, kQTFileTypeTIFF);
7915 #endif
7916 }
7917 #endif /* MAC_OS */
7918
7919 #endif /* !HAVE_TIFF */
7920
7921
7922 \f
7923 /***********************************************************************
7924 GIF
7925 ***********************************************************************/
7926
7927 #if defined (HAVE_GIF) || defined (MAC_OS)
7928
7929 static int gif_image_p P_ ((Lisp_Object object));
7930 static int gif_load P_ ((struct frame *f, struct image *img));
7931 static void gif_clear_image P_ ((struct frame *f, struct image *img));
7932
7933 /* The symbol `gif' identifying images of this type. */
7934
7935 Lisp_Object Qgif;
7936
7937 /* Indices of image specification fields in gif_format, below. */
7938
7939 enum gif_keyword_index
7940 {
7941 GIF_TYPE,
7942 GIF_DATA,
7943 GIF_FILE,
7944 GIF_ASCENT,
7945 GIF_MARGIN,
7946 GIF_RELIEF,
7947 GIF_ALGORITHM,
7948 GIF_HEURISTIC_MASK,
7949 GIF_MASK,
7950 GIF_IMAGE,
7951 GIF_BACKGROUND,
7952 GIF_LAST
7953 };
7954
7955 /* Vector of image_keyword structures describing the format
7956 of valid user-defined image specifications. */
7957
7958 static struct image_keyword gif_format[GIF_LAST] =
7959 {
7960 {":type", IMAGE_SYMBOL_VALUE, 1},
7961 {":data", IMAGE_STRING_VALUE, 0},
7962 {":file", IMAGE_STRING_VALUE, 0},
7963 {":ascent", IMAGE_ASCENT_VALUE, 0},
7964 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7965 {":relief", IMAGE_INTEGER_VALUE, 0},
7966 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7967 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7968 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7969 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7970 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7971 };
7972
7973 /* Structure describing the image type `gif'. */
7974
7975 static struct image_type gif_type =
7976 {
7977 &Qgif,
7978 gif_image_p,
7979 gif_load,
7980 gif_clear_image,
7981 NULL
7982 };
7983
7984 /* Free X resources of GIF image IMG which is used on frame F. */
7985
7986 static void
7987 gif_clear_image (f, img)
7988 struct frame *f;
7989 struct image *img;
7990 {
7991 /* IMG->data.ptr_val may contain extension data. */
7992 img->data.lisp_val = Qnil;
7993 x_clear_image (f, img);
7994 }
7995
7996 /* Return non-zero if OBJECT is a valid GIF image specification. */
7997
7998 static int
7999 gif_image_p (object)
8000 Lisp_Object object;
8001 {
8002 struct image_keyword fmt[GIF_LAST];
8003 bcopy (gif_format, fmt, sizeof fmt);
8004
8005 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8006 return 0;
8007
8008 /* Must specify either the :data or :file keyword. */
8009 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8010 }
8011
8012 #endif /* HAVE_GIF || MAC_OS */
8013
8014 #ifdef HAVE_GIF
8015
8016 #if defined (HAVE_NTGUI) || defined (MAC_OS)
8017 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
8018 Undefine before redefining to avoid a preprocessor warning. */
8019 #ifdef DrawText
8020 #undef DrawText
8021 #endif
8022 /* avoid conflict with QuickdrawText.h */
8023 #define DrawText gif_DrawText
8024 #include <gif_lib.h>
8025 #undef DrawText
8026
8027 #else /* HAVE_NTGUI || MAC_OS */
8028
8029 #include <gif_lib.h>
8030
8031 #endif /* HAVE_NTGUI || MAC_OS */
8032
8033
8034 #ifdef HAVE_NTGUI
8035
8036 /* GIF library details. */
8037 DEF_IMGLIB_FN (DGifCloseFile);
8038 DEF_IMGLIB_FN (DGifSlurp);
8039 DEF_IMGLIB_FN (DGifOpen);
8040 DEF_IMGLIB_FN (DGifOpenFileName);
8041
8042 static int
8043 init_gif_functions (Lisp_Object libraries)
8044 {
8045 HMODULE library;
8046
8047 if (!(library = w32_delayed_load (libraries, Qgif)))
8048 return 0;
8049
8050 LOAD_IMGLIB_FN (library, DGifCloseFile);
8051 LOAD_IMGLIB_FN (library, DGifSlurp);
8052 LOAD_IMGLIB_FN (library, DGifOpen);
8053 LOAD_IMGLIB_FN (library, DGifOpenFileName);
8054 return 1;
8055 }
8056
8057 #else
8058
8059 #define fn_DGifCloseFile DGifCloseFile
8060 #define fn_DGifSlurp DGifSlurp
8061 #define fn_DGifOpen DGifOpen
8062 #define fn_DGifOpenFileName DGifOpenFileName
8063
8064 #endif /* HAVE_NTGUI */
8065
8066 /* Reading a GIF image from memory
8067 Based on the PNG memory stuff to a certain extent. */
8068
8069 typedef struct
8070 {
8071 unsigned char *bytes;
8072 size_t len;
8073 int index;
8074 }
8075 gif_memory_source;
8076
8077 /* Make the current memory source available to gif_read_from_memory.
8078 It's done this way because not all versions of libungif support
8079 a UserData field in the GifFileType structure. */
8080 static gif_memory_source *current_gif_memory_src;
8081
8082 static int
8083 gif_read_from_memory (file, buf, len)
8084 GifFileType *file;
8085 GifByteType *buf;
8086 int len;
8087 {
8088 gif_memory_source *src = current_gif_memory_src;
8089
8090 if (len > src->len - src->index)
8091 return -1;
8092
8093 bcopy (src->bytes + src->index, buf, len);
8094 src->index += len;
8095 return len;
8096 }
8097
8098
8099 /* Load GIF image IMG for use on frame F. Value is non-zero if
8100 successful. */
8101
8102 static int interlace_start[] = {0, 4, 2, 1};
8103 static int interlace_increment[] = {8, 8, 4, 2};
8104
8105 static int
8106 gif_load (f, img)
8107 struct frame *f;
8108 struct image *img;
8109 {
8110 Lisp_Object file, specified_file;
8111 Lisp_Object specified_data;
8112 int rc, width, height, x, y, i;
8113 XImagePtr ximg;
8114 ColorMapObject *gif_color_map;
8115 unsigned long pixel_colors[256];
8116 GifFileType *gif;
8117 struct gcpro gcpro1;
8118 Lisp_Object image;
8119 int ino, image_height, image_width;
8120 gif_memory_source memsrc;
8121 unsigned char *raster;
8122
8123 specified_file = image_spec_value (img->spec, QCfile, NULL);
8124 specified_data = image_spec_value (img->spec, QCdata, NULL);
8125 file = Qnil;
8126 GCPRO1 (file);
8127
8128 if (NILP (specified_data))
8129 {
8130 file = x_find_image_file (specified_file);
8131 if (!STRINGP (file))
8132 {
8133 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8134 UNGCPRO;
8135 return 0;
8136 }
8137
8138 /* Open the GIF file. Casting return value avoids a GCC warning
8139 on W32. */
8140 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
8141 if (gif == NULL)
8142 {
8143 image_error ("Cannot open `%s'", file, Qnil);
8144 UNGCPRO;
8145 return 0;
8146 }
8147 }
8148 else
8149 {
8150 /* Read from memory! */
8151 current_gif_memory_src = &memsrc;
8152 memsrc.bytes = SDATA (specified_data);
8153 memsrc.len = SBYTES (specified_data);
8154 memsrc.index = 0;
8155
8156 /* Casting return value avoids a GCC warning on W32. */
8157 gif = (GifFileType *) fn_DGifOpen (&memsrc, gif_read_from_memory);
8158 if (!gif)
8159 {
8160 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8161 UNGCPRO;
8162 return 0;
8163 }
8164 }
8165
8166 /* Before reading entire contents, check the declared image size. */
8167 if (!check_image_size (f, gif->SWidth, gif->SHeight))
8168 {
8169 image_error ("Invalid image size", Qnil, Qnil);
8170 fn_DGifCloseFile (gif);
8171 UNGCPRO;
8172 return 0;
8173 }
8174
8175 /* Read entire contents. */
8176 rc = fn_DGifSlurp (gif);
8177 if (rc == GIF_ERROR)
8178 {
8179 image_error ("Error reading `%s'", img->spec, Qnil);
8180 fn_DGifCloseFile (gif);
8181 UNGCPRO;
8182 return 0;
8183 }
8184
8185 image = image_spec_value (img->spec, QCindex, NULL);
8186 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8187 if (ino >= gif->ImageCount)
8188 {
8189 image_error ("Invalid image number `%s' in image `%s'",
8190 image, img->spec);
8191 fn_DGifCloseFile (gif);
8192 UNGCPRO;
8193 return 0;
8194 }
8195
8196 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
8197 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
8198 image_height = gif->SavedImages[ino].ImageDesc.Height;
8199 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
8200 image_width = gif->SavedImages[ino].ImageDesc.Width;
8201 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
8202
8203 width = img->width = max (gif->SWidth,
8204 max (gif->Image.Left + gif->Image.Width,
8205 img->corners[RIGHT_CORNER]));
8206 height = img->height = max (gif->SHeight,
8207 max (gif->Image.Top + gif->Image.Height,
8208 img->corners[BOT_CORNER]));
8209
8210 if (!check_image_size (f, width, height))
8211 {
8212 image_error ("Invalid image size", Qnil, Qnil);
8213 fn_DGifCloseFile (gif);
8214 UNGCPRO;
8215 return 0;
8216 }
8217
8218 /* Create the X image and pixmap. */
8219 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8220 {
8221 fn_DGifCloseFile (gif);
8222 UNGCPRO;
8223 return 0;
8224 }
8225
8226 /* Allocate colors. */
8227 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8228 if (!gif_color_map)
8229 gif_color_map = gif->SColorMap;
8230 init_color_table ();
8231 bzero (pixel_colors, sizeof pixel_colors);
8232
8233 if (gif_color_map)
8234 for (i = 0; i < gif_color_map->ColorCount; ++i)
8235 {
8236 int r = gif_color_map->Colors[i].Red << 8;
8237 int g = gif_color_map->Colors[i].Green << 8;
8238 int b = gif_color_map->Colors[i].Blue << 8;
8239 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8240 }
8241
8242 #ifdef COLOR_TABLE_SUPPORT
8243 img->colors = colors_in_color_table (&img->ncolors);
8244 free_color_table ();
8245 #endif /* COLOR_TABLE_SUPPORT */
8246
8247 /* Clear the part of the screen image that are not covered by
8248 the image from the GIF file. Full animated GIF support
8249 requires more than can be done here (see the gif89 spec,
8250 disposal methods). Let's simply assume that the part
8251 not covered by a sub-image is in the frame's background color. */
8252 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
8253 for (x = 0; x < width; ++x)
8254 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8255
8256 for (y = img->corners[BOT_CORNER]; y < height; ++y)
8257 for (x = 0; x < width; ++x)
8258 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8259
8260 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
8261 {
8262 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
8263 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8264 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
8265 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8266 }
8267
8268 /* Read the GIF image into the X image. We use a local variable
8269 `raster' here because RasterBits below is a char *, and invites
8270 problems with bytes >= 0x80. */
8271 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8272
8273 if (gif->SavedImages[ino].ImageDesc.Interlace)
8274 {
8275 int pass;
8276 int row = interlace_start[0];
8277
8278 pass = 0;
8279
8280 for (y = 0; y < image_height; y++)
8281 {
8282 if (row >= image_height)
8283 {
8284 row = interlace_start[++pass];
8285 while (row >= image_height)
8286 row = interlace_start[++pass];
8287 }
8288
8289 for (x = 0; x < image_width; x++)
8290 {
8291 int i = raster[(y * image_width) + x];
8292 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8293 row + img->corners[TOP_CORNER], pixel_colors[i]);
8294 }
8295
8296 row += interlace_increment[pass];
8297 }
8298 }
8299 else
8300 {
8301 for (y = 0; y < image_height; ++y)
8302 for (x = 0; x < image_width; ++x)
8303 {
8304 int i = raster[y * image_width + x];
8305 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8306 y + img->corners[TOP_CORNER], pixel_colors[i]);
8307 }
8308 }
8309
8310 /* Save GIF image extension data for `image-extension-data'.
8311 Format is (count IMAGES FUNCTION "BYTES" ...). */
8312 img->data.lisp_val = Qnil;
8313 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
8314 {
8315 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
8316 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
8317 /* Append (... FUNCTION "BYTES") */
8318 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
8319 Fcons (make_number (ext->Function),
8320 img->data.lisp_val));
8321 img->data.lisp_val = Fnreverse (img->data.lisp_val);
8322 }
8323 if (gif->ImageCount > 1)
8324 img->data.lisp_val = Fcons (Qcount,
8325 Fcons (make_number (gif->ImageCount),
8326 img->data.lisp_val));
8327
8328 fn_DGifCloseFile (gif);
8329
8330 /* Maybe fill in the background field while we have ximg handy. */
8331 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8332 /* Casting avoids a GCC warning. */
8333 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8334
8335 /* Put the image into the pixmap, then free the X image and its buffer. */
8336 x_put_x_image (f, ximg, img->pixmap, width, height);
8337 x_destroy_x_image (ximg);
8338
8339 UNGCPRO;
8340 return 1;
8341 }
8342
8343 #else /* !HAVE_GIF */
8344
8345 #ifdef MAC_OS
8346 static int
8347 gif_load (f, img)
8348 struct frame *f;
8349 struct image *img;
8350 {
8351 #if USE_MAC_IMAGE_IO
8352 return image_load_image_io (f, img, kUTTypeGIF);
8353 #else /* !USE_MAC_IMAGE_IO */
8354 Lisp_Object specified_file, file;
8355 Lisp_Object specified_data;
8356 OSErr err;
8357 Boolean graphic_p, movie_p, prefer_graphic_p;
8358 Handle dh = NULL;
8359 Movie movie = NULL;
8360 Lisp_Object image;
8361 Track track = NULL;
8362 Media media = NULL;
8363 long nsamples;
8364 Rect rect;
8365 Lisp_Object specified_bg;
8366 XColor color;
8367 RGBColor bg_color;
8368 int width, height;
8369 XImagePtr ximg;
8370 TimeScale time_scale;
8371 TimeValue time, duration;
8372 int ino;
8373 CGrafPtr old_port;
8374 GDHandle old_gdh;
8375
8376 specified_file = image_spec_value (img->spec, QCfile, NULL);
8377 specified_data = image_spec_value (img->spec, QCdata, NULL);
8378
8379 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8380 EnterMovies ();
8381
8382 if (NILP (specified_data))
8383 {
8384 /* Read from a file */
8385 FSSpec fss;
8386 short refnum;
8387
8388 err = find_image_fsspec (specified_file, &file, &fss);
8389 if (err != noErr)
8390 {
8391 if (err == fnfErr)
8392 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8393 else
8394 goto open_error;
8395 }
8396
8397 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
8398 &graphic_p, &movie_p, &prefer_graphic_p, 0);
8399 if (err != noErr)
8400 goto open_error;
8401
8402 if (!graphic_p && !movie_p)
8403 goto open_error;
8404 if (prefer_graphic_p)
8405 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
8406 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
8407 if (err != noErr)
8408 goto open_error;
8409 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
8410 CloseMovieFile (refnum);
8411 if (err != noErr)
8412 {
8413 image_error ("Error reading `%s'", file, Qnil);
8414 return 0;
8415 }
8416 }
8417 else
8418 {
8419 /* Memory source! */
8420 Handle dref = NULL;
8421 long file_type_atom[3];
8422
8423 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
8424 if (err != noErr)
8425 {
8426 image_error ("Cannot allocate data handle for `%s'",
8427 img->spec, Qnil);
8428 goto error;
8429 }
8430
8431 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
8432 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
8433 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
8434 err = PtrToHand (&dh, &dref, sizeof (Handle));
8435 if (err == noErr)
8436 /* no file name */
8437 err = PtrAndHand ("\p", dref, 1);
8438 if (err == noErr)
8439 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
8440 if (err != noErr)
8441 {
8442 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
8443 goto error;
8444 }
8445 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8446 &movie_p, &prefer_graphic_p, 0);
8447 if (err != noErr)
8448 goto open_error;
8449
8450 if (!graphic_p && !movie_p)
8451 goto open_error;
8452 if (prefer_graphic_p)
8453 {
8454 int success_p;
8455
8456 DisposeHandle (dref);
8457 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8458 DisposeHandle (dh);
8459 return success_p;
8460 }
8461 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8462 HandleDataHandlerSubType);
8463 DisposeHandle (dref);
8464 if (err != noErr)
8465 goto open_error;
8466 }
8467
8468 image = image_spec_value (img->spec, QCindex, NULL);
8469 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8470 track = GetMovieIndTrack (movie, 1);
8471 media = GetTrackMedia (track);
8472 nsamples = GetMediaSampleCount (media);
8473 if (ino >= nsamples)
8474 {
8475 image_error ("Invalid image number `%s' in image `%s'",
8476 image, img->spec);
8477 goto error;
8478 }
8479 time_scale = GetMediaTimeScale (media);
8480
8481 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8482 if (!STRINGP (specified_bg)
8483 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8484 {
8485 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8486 color.red = RED16_FROM_ULONG (color.pixel);
8487 color.green = GREEN16_FROM_ULONG (color.pixel);
8488 color.blue = BLUE16_FROM_ULONG (color.pixel);
8489 }
8490 GetMovieBox (movie, &rect);
8491 width = img->width = rect.right - rect.left;
8492 height = img->height = rect.bottom - rect.top;
8493 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8494 goto error;
8495
8496 GetGWorld (&old_port, &old_gdh);
8497 SetGWorld (ximg, NULL);
8498 bg_color.red = color.red;
8499 bg_color.green = color.green;
8500 bg_color.blue = color.blue;
8501 RGBBackColor (&bg_color);
8502 SetGWorld (old_port, old_gdh);
8503 SetMovieActive (movie, 1);
8504 SetMovieGWorld (movie, ximg, NULL);
8505 SampleNumToMediaTime (media, ino + 1, &time, &duration);
8506 SetMovieTimeValue (movie, time);
8507 MoviesTask (movie, 0L);
8508 DisposeTrackMedia (media);
8509 DisposeMovieTrack (track);
8510 DisposeMovie (movie);
8511 if (dh)
8512 DisposeHandle (dh);
8513
8514 /* Save GIF image extension data for `image-extension-data'.
8515 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8516 {
8517 Lisp_Object gce = make_uninit_string (4);
8518 int centisec = ((float)duration / time_scale) * 100.0f + 0.5f;
8519
8520 /* Fill the delay time field. */
8521 SSET (gce, 1, centisec & 0xff);
8522 SSET (gce, 2, (centisec >> 8) & 0xff);
8523 /* We don't know about other fields. */
8524 SSET (gce, 0, 0);
8525 SSET (gce, 3, 0);
8526
8527 img->data.lisp_val = list4 (Qcount, make_number (nsamples),
8528 make_number (0xf9), gce);
8529 }
8530
8531 /* Maybe fill in the background field while we have ximg handy. */
8532 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8533 IMAGE_BACKGROUND (img, f, ximg);
8534
8535 /* Put the image into the pixmap. */
8536 x_put_x_image (f, ximg, img->pixmap, width, height);
8537 x_destroy_x_image (ximg);
8538 return 1;
8539
8540 open_error:
8541 image_error ("Cannot open `%s'", file, Qnil);
8542 error:
8543 if (media)
8544 DisposeTrackMedia (media);
8545 if (track)
8546 DisposeMovieTrack (track);
8547 if (movie)
8548 DisposeMovie (movie);
8549 if (dh)
8550 DisposeHandle (dh);
8551 return 0;
8552 #endif /* !USE_MAC_IMAGE_IO */
8553 }
8554 #endif /* MAC_OS */
8555
8556 #endif /* HAVE_GIF */
8557
8558
8559 \f
8560 /***********************************************************************
8561 SVG
8562 ***********************************************************************/
8563
8564 #if defined (HAVE_RSVG)
8565
8566 /* Function prototypes. */
8567
8568 static int svg_image_p P_ ((Lisp_Object object));
8569 static int svg_load P_ ((struct frame *f, struct image *img));
8570
8571 static int svg_load_image P_ ((struct frame *, struct image *,
8572 unsigned char *, unsigned int));
8573
8574 /* The symbol `svg' identifying images of this type. */
8575
8576 Lisp_Object Qsvg;
8577
8578 /* Indices of image specification fields in svg_format, below. */
8579
8580 enum svg_keyword_index
8581 {
8582 SVG_TYPE,
8583 SVG_DATA,
8584 SVG_FILE,
8585 SVG_ASCENT,
8586 SVG_MARGIN,
8587 SVG_RELIEF,
8588 SVG_ALGORITHM,
8589 SVG_HEURISTIC_MASK,
8590 SVG_MASK,
8591 SVG_BACKGROUND,
8592 SVG_LAST
8593 };
8594
8595 /* Vector of image_keyword structures describing the format
8596 of valid user-defined image specifications. */
8597
8598 static struct image_keyword svg_format[SVG_LAST] =
8599 {
8600 {":type", IMAGE_SYMBOL_VALUE, 1},
8601 {":data", IMAGE_STRING_VALUE, 0},
8602 {":file", IMAGE_STRING_VALUE, 0},
8603 {":ascent", IMAGE_ASCENT_VALUE, 0},
8604 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8605 {":relief", IMAGE_INTEGER_VALUE, 0},
8606 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8607 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8608 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8609 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8610 };
8611
8612 /* Structure describing the image type `svg'. Its the same type of
8613 structure defined for all image formats, handled by emacs image
8614 functions. See struct image_type in dispextern.h. */
8615
8616 static struct image_type svg_type =
8617 {
8618 /* An identifier showing that this is an image structure for the SVG format. */
8619 &Qsvg,
8620 /* Handle to a function that can be used to identify a SVG file. */
8621 svg_image_p,
8622 /* Handle to function used to load a SVG file. */
8623 svg_load,
8624 /* Handle to function to free sresources for SVG. */
8625 x_clear_image,
8626 /* An internal field to link to the next image type in a list of
8627 image types, will be filled in when registering the format. */
8628 NULL
8629 };
8630
8631
8632 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8633 this by calling parse_image_spec and supplying the keywords that
8634 identify the SVG format. */
8635
8636 static int
8637 svg_image_p (object)
8638 Lisp_Object object;
8639 {
8640 struct image_keyword fmt[SVG_LAST];
8641 bcopy (svg_format, fmt, sizeof fmt);
8642
8643 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
8644 return 0;
8645
8646 /* Must specify either the :data or :file keyword. */
8647 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
8648 }
8649
8650 #include <librsvg/rsvg.h>
8651
8652 #ifdef HAVE_NTGUI
8653
8654 /* SVG library functions. */
8655 DEF_IMGLIB_FN (rsvg_handle_new);
8656 DEF_IMGLIB_FN (rsvg_handle_set_size_callback);
8657 DEF_IMGLIB_FN (rsvg_handle_write);
8658 DEF_IMGLIB_FN (rsvg_handle_close);
8659 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf);
8660 DEF_IMGLIB_FN (rsvg_handle_free);
8661
8662 DEF_IMGLIB_FN (gdk_pixbuf_get_width);
8663 DEF_IMGLIB_FN (gdk_pixbuf_get_height);
8664 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels);
8665 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride);
8666 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace);
8667 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels);
8668 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha);
8669 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample);
8670
8671 DEF_IMGLIB_FN (g_type_init);
8672 DEF_IMGLIB_FN (g_object_unref);
8673 DEF_IMGLIB_FN (g_error_free);
8674
8675 Lisp_Object Qgdk_pixbuf, Qglib;
8676
8677 static int
8678 init_svg_functions (Lisp_Object libraries)
8679 {
8680 HMODULE library, gdklib, glib;
8681
8682 if (!(glib = w32_delayed_load (libraries, Qglib))
8683 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
8684 || !(library = w32_delayed_load (libraries, Qsvg)))
8685 return 0;
8686
8687 LOAD_IMGLIB_FN (library, rsvg_handle_new);
8688 LOAD_IMGLIB_FN (library, rsvg_handle_set_size_callback);
8689 LOAD_IMGLIB_FN (library, rsvg_handle_write);
8690 LOAD_IMGLIB_FN (library, rsvg_handle_close);
8691 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
8692 LOAD_IMGLIB_FN (library, rsvg_handle_free);
8693
8694 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
8695 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
8696 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
8697 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
8698 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
8699 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
8700 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
8701 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
8702
8703 LOAD_IMGLIB_FN (glib, g_type_init);
8704 LOAD_IMGLIB_FN (glib, g_object_unref);
8705 LOAD_IMGLIB_FN (glib, g_error_free);
8706 return 1;
8707 }
8708
8709 #else
8710 /* The following aliases for library functions allow dynamic loading
8711 to be used on some platforms. */
8712 #define fn_rsvg_handle_new rsvg_handle_new
8713 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8714 #define fn_rsvg_handle_write rsvg_handle_write
8715 #define fn_rsvg_handle_close rsvg_handle_close
8716 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8717 #define fn_rsvg_handle_free rsvg_handle_free
8718
8719 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8720 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8721 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8722 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8723 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8724 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8725 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8726 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8727
8728 #define fn_g_type_init g_type_init
8729 #define fn_g_object_unref g_object_unref
8730 #define fn_g_error_free g_error_free
8731 #endif /* !HAVE_NTGUI */
8732
8733 /* Load SVG image IMG for use on frame F. Value is non-zero if
8734 successful. this function will go into the svg_type structure, and
8735 the prototype thus needs to be compatible with that structure. */
8736
8737 static int
8738 svg_load (f, img)
8739 struct frame *f;
8740 struct image *img;
8741 {
8742 int success_p = 0;
8743 Lisp_Object file_name;
8744
8745 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8746 file_name = image_spec_value (img->spec, QCfile, NULL);
8747 if (STRINGP (file_name))
8748 {
8749 Lisp_Object file;
8750 unsigned char *contents;
8751 int size;
8752 struct gcpro gcpro1;
8753
8754 file = x_find_image_file (file_name);
8755 GCPRO1 (file);
8756 if (!STRINGP (file))
8757 {
8758 image_error ("Cannot find image file `%s'", file_name, Qnil);
8759 UNGCPRO;
8760 return 0;
8761 }
8762
8763 /* Read the entire file into memory. */
8764 contents = slurp_file (SDATA (file), &size);
8765 if (contents == NULL)
8766 {
8767 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
8768 UNGCPRO;
8769 return 0;
8770 }
8771 /* If the file was slurped into memory properly, parse it. */
8772 success_p = svg_load_image (f, img, contents, size);
8773 xfree (contents);
8774 UNGCPRO;
8775 }
8776 /* Else its not a file, its a lisp object. Load the image from a
8777 lisp object rather than a file. */
8778 else
8779 {
8780 Lisp_Object data;
8781
8782 data = image_spec_value (img->spec, QCdata, NULL);
8783 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
8784 }
8785
8786 return success_p;
8787 }
8788
8789 /* svg_load_image is a helper function for svg_load, which does the
8790 actual loading given contents and size, apart from frame and image
8791 structures, passed from svg_load.
8792
8793 Uses librsvg to do most of the image processing.
8794
8795 Returns non-zero when successful. */
8796 static int
8797 svg_load_image (f, img, contents, size)
8798 /* Pointer to emacs frame structure. */
8799 struct frame *f;
8800 /* Pointer to emacs image structure. */
8801 struct image *img;
8802 /* String containing the SVG XML data to be parsed. */
8803 unsigned char *contents;
8804 /* Size of data in bytes. */
8805 unsigned int size;
8806 {
8807 RsvgHandle *rsvg_handle;
8808 GError *error = NULL;
8809 GdkPixbuf *pixbuf;
8810 int width;
8811 int height;
8812 const guint8 *pixels;
8813 int rowstride;
8814 XImagePtr ximg;
8815 Lisp_Object specified_bg;
8816 XColor background;
8817 int x;
8818 int y;
8819
8820 /* g_type_init is a glib function that must be called prior to using
8821 gnome type library functions. */
8822 fn_g_type_init ();
8823 /* Make a handle to a new rsvg object. */
8824 rsvg_handle = fn_rsvg_handle_new ();
8825
8826 /* Parse the contents argument and fill in the rsvg_handle. */
8827 fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
8828 if (error)
8829 goto rsvg_error;
8830
8831 /* The parsing is complete, rsvg_handle is ready to used, close it
8832 for further writes. */
8833 fn_rsvg_handle_close (rsvg_handle, &error);
8834 if (error)
8835 goto rsvg_error;
8836 /* We can now get a valid pixel buffer from the svg file, if all
8837 went ok. */
8838 pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
8839 eassert (pixbuf);
8840
8841 /* Extract some meta data from the svg handle. */
8842 width = fn_gdk_pixbuf_get_width (pixbuf);
8843 height = fn_gdk_pixbuf_get_height (pixbuf);
8844 pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
8845 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
8846
8847 /* Validate the svg meta data. */
8848 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
8849 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
8850 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
8851 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8852
8853 /* Try to create a x pixmap to hold the svg pixmap. */
8854 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8855 {
8856 fn_g_object_unref (pixbuf);
8857 return 0;
8858 }
8859
8860 init_color_table ();
8861
8862 /* Handle alpha channel by combining the image with a background
8863 color. */
8864 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8865 if (STRINGP (specified_bg)
8866 && x_defined_color (f, SDATA (specified_bg), &background, 0))
8867 {
8868 background.red >>= 8;
8869 background.green >>= 8;
8870 background.blue >>= 8;
8871 }
8872 else
8873 {
8874 #ifdef HAVE_X_WINDOWS
8875 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8876 x_query_color (f, &background);
8877
8878 /* SVG pixmaps specify transparency in the last byte, so right
8879 shift 8 bits to get rid of it, since emacs doesn't support
8880 transparency. */
8881 background.red >>= 8;
8882 background.green >>= 8;
8883 background.blue >>= 8;
8884 #elif defined (MAC_OS)
8885 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8886 background.red = RED_FROM_ULONG (background.pixel);
8887 background.green = GREEN_FROM_ULONG (background.pixel);
8888 background.blue = BLUE_FROM_ULONG (background.pixel);
8889 #elif defined (HAVE_NTGUI)
8890 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8891 #if 0 /* W32 TODO : Colormap support. */
8892 x_query_color (f, &background);
8893 #endif
8894
8895 /* SVG pixmaps specify transparency in the last byte, so right
8896 shift 8 bits to get rid of it, since emacs doesn't support
8897 transparency. */
8898 background.red >>= 8;
8899 background.green >>= 8;
8900 background.blue >>= 8;
8901 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8902 #error FIXME
8903 #endif
8904 }
8905
8906 /* This loop handles opacity values, since Emacs assumes
8907 non-transparent images. Each pixel must be "flattened" by
8908 calculating the resulting color, given the transparency of the
8909 pixel, and the image background color. */
8910 for (y = 0; y < height; ++y)
8911 {
8912 for (x = 0; x < width; ++x)
8913 {
8914 unsigned red;
8915 unsigned green;
8916 unsigned blue;
8917 unsigned opacity;
8918
8919 red = *pixels++;
8920 green = *pixels++;
8921 blue = *pixels++;
8922 opacity = *pixels++;
8923
8924 red = ((red * opacity)
8925 + (background.red * ((1 << 8) - opacity)));
8926 green = ((green * opacity)
8927 + (background.green * ((1 << 8) - opacity)));
8928 blue = ((blue * opacity)
8929 + (background.blue * ((1 << 8) - opacity)));
8930
8931 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
8932 }
8933
8934 pixels += rowstride - 4 * width;
8935 }
8936
8937 #ifdef COLOR_TABLE_SUPPORT
8938 /* Remember colors allocated for this image. */
8939 img->colors = colors_in_color_table (&img->ncolors);
8940 free_color_table ();
8941 #endif /* COLOR_TABLE_SUPPORT */
8942
8943 fn_g_object_unref (pixbuf);
8944
8945 img->width = width;
8946 img->height = height;
8947
8948 /* Maybe fill in the background field while we have ximg handy.
8949 Casting avoids a GCC warning. */
8950 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8951
8952 /* Put the image into the pixmap, then free the X image and its
8953 buffer. */
8954 x_put_x_image (f, ximg, img->pixmap, width, height);
8955 x_destroy_x_image (ximg);
8956
8957 return 1;
8958
8959 rsvg_error:
8960 /* FIXME: Use error->message so the user knows what is the actual
8961 problem with the image. */
8962 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
8963 fn_g_error_free (error);
8964 return 0;
8965 }
8966
8967 #endif /* defined (HAVE_RSVG) */
8968
8969
8970
8971 \f
8972 /***********************************************************************
8973 Ghostscript
8974 ***********************************************************************/
8975
8976 #ifdef HAVE_X_WINDOWS
8977 #define HAVE_GHOSTSCRIPT 1
8978 #endif /* HAVE_X_WINDOWS */
8979
8980 /* The symbol `postscript' identifying images of this type. */
8981
8982 Lisp_Object Qpostscript;
8983
8984 #ifdef HAVE_GHOSTSCRIPT
8985
8986 static int gs_image_p P_ ((Lisp_Object object));
8987 static int gs_load P_ ((struct frame *f, struct image *img));
8988 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8989
8990 /* Keyword symbols. */
8991
8992 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8993
8994 /* Indices of image specification fields in gs_format, below. */
8995
8996 enum gs_keyword_index
8997 {
8998 GS_TYPE,
8999 GS_PT_WIDTH,
9000 GS_PT_HEIGHT,
9001 GS_FILE,
9002 GS_LOADER,
9003 GS_BOUNDING_BOX,
9004 GS_ASCENT,
9005 GS_MARGIN,
9006 GS_RELIEF,
9007 GS_ALGORITHM,
9008 GS_HEURISTIC_MASK,
9009 GS_MASK,
9010 GS_BACKGROUND,
9011 GS_LAST
9012 };
9013
9014 /* Vector of image_keyword structures describing the format
9015 of valid user-defined image specifications. */
9016
9017 static struct image_keyword gs_format[GS_LAST] =
9018 {
9019 {":type", IMAGE_SYMBOL_VALUE, 1},
9020 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9021 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9022 {":file", IMAGE_STRING_VALUE, 1},
9023 {":loader", IMAGE_FUNCTION_VALUE, 0},
9024 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9025 {":ascent", IMAGE_ASCENT_VALUE, 0},
9026 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9027 {":relief", IMAGE_INTEGER_VALUE, 0},
9028 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9029 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9030 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9031 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9032 };
9033
9034 /* Structure describing the image type `ghostscript'. */
9035
9036 static struct image_type gs_type =
9037 {
9038 &Qpostscript,
9039 gs_image_p,
9040 gs_load,
9041 gs_clear_image,
9042 NULL
9043 };
9044
9045
9046 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9047
9048 static void
9049 gs_clear_image (f, img)
9050 struct frame *f;
9051 struct image *img;
9052 {
9053 /* IMG->data.ptr_val may contain a recorded colormap. */
9054 xfree (img->data.ptr_val);
9055 x_clear_image (f, img);
9056 }
9057
9058
9059 /* Return non-zero if OBJECT is a valid Ghostscript image
9060 specification. */
9061
9062 static int
9063 gs_image_p (object)
9064 Lisp_Object object;
9065 {
9066 struct image_keyword fmt[GS_LAST];
9067 Lisp_Object tem;
9068 int i;
9069
9070 bcopy (gs_format, fmt, sizeof fmt);
9071
9072 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9073 return 0;
9074
9075 /* Bounding box must be a list or vector containing 4 integers. */
9076 tem = fmt[GS_BOUNDING_BOX].value;
9077 if (CONSP (tem))
9078 {
9079 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9080 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9081 return 0;
9082 if (!NILP (tem))
9083 return 0;
9084 }
9085 else if (VECTORP (tem))
9086 {
9087 if (XVECTOR (tem)->size != 4)
9088 return 0;
9089 for (i = 0; i < 4; ++i)
9090 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9091 return 0;
9092 }
9093 else
9094 return 0;
9095
9096 return 1;
9097 }
9098
9099
9100 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9101 if successful. */
9102
9103 static int
9104 gs_load (f, img)
9105 struct frame *f;
9106 struct image *img;
9107 {
9108 char buffer[100];
9109 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9110 struct gcpro gcpro1, gcpro2;
9111 Lisp_Object frame;
9112 double in_width, in_height;
9113 Lisp_Object pixel_colors = Qnil;
9114
9115 /* Compute pixel size of pixmap needed from the given size in the
9116 image specification. Sizes in the specification are in pt. 1 pt
9117 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9118 info. */
9119 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9120 in_width = XFASTINT (pt_width) / 72.0;
9121 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9122 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9123 in_height = XFASTINT (pt_height) / 72.0;
9124 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9125
9126 if (!check_image_size (f, img->width, img->height))
9127 {
9128 image_error ("Invalid image size", Qnil, Qnil);
9129 return 0;
9130 }
9131
9132 /* Create the pixmap. */
9133 xassert (img->pixmap == NO_PIXMAP);
9134
9135 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9136 BLOCK_INPUT;
9137 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9138 img->width, img->height,
9139 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9140 UNBLOCK_INPUT;
9141
9142 if (!img->pixmap)
9143 {
9144 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9145 return 0;
9146 }
9147
9148 /* Call the loader to fill the pixmap. It returns a process object
9149 if successful. We do not record_unwind_protect here because
9150 other places in redisplay like calling window scroll functions
9151 don't either. Let the Lisp loader use `unwind-protect' instead. */
9152 GCPRO2 (window_and_pixmap_id, pixel_colors);
9153
9154 sprintf (buffer, "%lu %lu",
9155 (unsigned long) FRAME_X_WINDOW (f),
9156 (unsigned long) img->pixmap);
9157 window_and_pixmap_id = build_string (buffer);
9158
9159 sprintf (buffer, "%lu %lu",
9160 FRAME_FOREGROUND_PIXEL (f),
9161 FRAME_BACKGROUND_PIXEL (f));
9162 pixel_colors = build_string (buffer);
9163
9164 XSETFRAME (frame, f);
9165 loader = image_spec_value (img->spec, QCloader, NULL);
9166 if (NILP (loader))
9167 loader = intern ("gs-load-image");
9168
9169 img->data.lisp_val = call6 (loader, frame, img->spec,
9170 make_number (img->width),
9171 make_number (img->height),
9172 window_and_pixmap_id,
9173 pixel_colors);
9174 UNGCPRO;
9175 return PROCESSP (img->data.lisp_val);
9176 }
9177
9178
9179 /* Kill the Ghostscript process that was started to fill PIXMAP on
9180 frame F. Called from XTread_socket when receiving an event
9181 telling Emacs that Ghostscript has finished drawing. */
9182
9183 void
9184 x_kill_gs_process (pixmap, f)
9185 Pixmap pixmap;
9186 struct frame *f;
9187 {
9188 struct image_cache *c = FRAME_IMAGE_CACHE (f);
9189 int class, i;
9190 struct image *img;
9191
9192 /* Find the image containing PIXMAP. */
9193 for (i = 0; i < c->used; ++i)
9194 if (c->images[i]->pixmap == pixmap)
9195 break;
9196
9197 /* Should someone in between have cleared the image cache, for
9198 instance, give up. */
9199 if (i == c->used)
9200 return;
9201
9202 /* Kill the GS process. We should have found PIXMAP in the image
9203 cache and its image should contain a process object. */
9204 img = c->images[i];
9205 xassert (PROCESSP (img->data.lisp_val));
9206 Fkill_process (img->data.lisp_val, Qnil);
9207 img->data.lisp_val = Qnil;
9208
9209 #if defined (HAVE_X_WINDOWS)
9210
9211 /* On displays with a mutable colormap, figure out the colors
9212 allocated for the image by looking at the pixels of an XImage for
9213 img->pixmap. */
9214 class = FRAME_X_VISUAL (f)->class;
9215 if (class != StaticColor && class != StaticGray && class != TrueColor)
9216 {
9217 XImagePtr ximg;
9218
9219 BLOCK_INPUT;
9220
9221 /* Try to get an XImage for img->pixmep. */
9222 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9223 0, 0, img->width, img->height, ~0, ZPixmap);
9224 if (ximg)
9225 {
9226 int x, y;
9227
9228 /* Initialize the color table. */
9229 init_color_table ();
9230
9231 /* For each pixel of the image, look its color up in the
9232 color table. After having done so, the color table will
9233 contain an entry for each color used by the image. */
9234 for (y = 0; y < img->height; ++y)
9235 for (x = 0; x < img->width; ++x)
9236 {
9237 unsigned long pixel = XGetPixel (ximg, x, y);
9238 lookup_pixel_color (f, pixel);
9239 }
9240
9241 /* Record colors in the image. Free color table and XImage. */
9242 #ifdef COLOR_TABLE_SUPPORT
9243 img->colors = colors_in_color_table (&img->ncolors);
9244 free_color_table ();
9245 #endif
9246 XDestroyImage (ximg);
9247
9248 #if 0 /* This doesn't seem to be the case. If we free the colors
9249 here, we get a BadAccess later in x_clear_image when
9250 freeing the colors. */
9251 /* We have allocated colors once, but Ghostscript has also
9252 allocated colors on behalf of us. So, to get the
9253 reference counts right, free them once. */
9254 if (img->ncolors)
9255 x_free_colors (f, img->colors, img->ncolors);
9256 #endif
9257 }
9258 else
9259 image_error ("Cannot get X image of `%s'; colors will not be freed",
9260 img->spec, Qnil);
9261
9262 UNBLOCK_INPUT;
9263 }
9264 #endif /* HAVE_X_WINDOWS */
9265
9266 /* Now that we have the pixmap, compute mask and transform the
9267 image if requested. */
9268 BLOCK_INPUT;
9269 postprocess_image (f, img);
9270 UNBLOCK_INPUT;
9271 }
9272
9273 #endif /* HAVE_GHOSTSCRIPT */
9274
9275 \f
9276 /***********************************************************************
9277 Tests
9278 ***********************************************************************/
9279
9280 #if GLYPH_DEBUG
9281
9282 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
9283 doc: /* Value is non-nil if SPEC is a valid image specification. */)
9284 (spec)
9285 Lisp_Object spec;
9286 {
9287 return valid_image_p (spec) ? Qt : Qnil;
9288 }
9289
9290
9291 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
9292 (spec)
9293 Lisp_Object spec;
9294 {
9295 int id = -1;
9296
9297 if (valid_image_p (spec))
9298 id = lookup_image (SELECTED_FRAME (), spec);
9299
9300 debug_print (spec);
9301 return make_number (id);
9302 }
9303
9304 #endif /* GLYPH_DEBUG != 0 */
9305
9306
9307 /***********************************************************************
9308 Initialization
9309 ***********************************************************************/
9310
9311 #ifdef HAVE_NTGUI
9312 /* Image types that rely on external libraries are loaded dynamically
9313 if the library is available. */
9314 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9315 define_image_type (image_type, init_lib_fn (libraries))
9316 #else
9317 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9318 define_image_type (image_type, 1)
9319 #endif /* HAVE_NTGUI */
9320
9321 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
9322 doc: /* Initialize image library implementing image type TYPE.
9323 Return non-nil if TYPE is a supported image type.
9324
9325 Image types pbm and xbm are prebuilt; other types are loaded here.
9326 Libraries to load are specified in alist LIBRARIES (usually, the value
9327 of `image-library-alist', which see). */)
9328 (type, libraries)
9329 Lisp_Object type, libraries;
9330 {
9331 Lisp_Object tested;
9332
9333 /* Don't try to reload the library. */
9334 tested = Fassq (type, Vimage_type_cache);
9335 if (CONSP (tested))
9336 return XCDR (tested);
9337
9338 #if defined (HAVE_XPM) || defined (MAC_OS)
9339 if (EQ (type, Qxpm))
9340 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
9341 #endif
9342
9343 #if defined (HAVE_JPEG) || defined (MAC_OS)
9344 if (EQ (type, Qjpeg))
9345 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
9346 #endif
9347
9348 #if defined (HAVE_TIFF) || defined (MAC_OS)
9349 if (EQ (type, Qtiff))
9350 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
9351 #endif
9352
9353 #if defined (HAVE_GIF) || defined (MAC_OS)
9354 if (EQ (type, Qgif))
9355 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
9356 #endif
9357
9358 #if defined (HAVE_PNG) || defined (MAC_OS)
9359 if (EQ (type, Qpng))
9360 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
9361 #endif
9362
9363 #if defined (HAVE_RSVG)
9364 if (EQ (type, Qsvg))
9365 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
9366 #endif
9367
9368 #ifdef HAVE_GHOSTSCRIPT
9369 if (EQ (type, Qpostscript))
9370 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
9371 #endif
9372
9373 /* If the type is not recognized, avoid testing it ever again. */
9374 CACHE_IMAGE_TYPE (type, Qnil);
9375 return Qnil;
9376 }
9377
9378 void
9379 syms_of_image ()
9380 {
9381 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
9382
9383 /* Initialize this only once, since that's what we do with Vimage_types
9384 and they are supposed to be in sync. Initializing here gives correct
9385 operation on GNU/Linux of calling dump-emacs after loading some images. */
9386 image_types = NULL;
9387
9388 /* Must be defined now becase we're going to update it below, while
9389 defining the supported image types. */
9390 DEFVAR_LISP ("image-types", &Vimage_types,
9391 doc: /* List of potentially supported image types.
9392 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9393 To check whether it is really supported, use `image-type-available-p'. */);
9394 Vimage_types = Qnil;
9395
9396 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
9397 doc: /* Alist of image types vs external libraries needed to display them.
9398
9399 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9400 representing a supported image type, and the rest are strings giving
9401 alternate filenames for the corresponding external libraries.
9402
9403 Emacs tries to load the libraries in the order they appear on the
9404 list; if none is loaded, the running session of Emacs won't
9405 support the image type. Types 'pbm and 'xbm don't need to be
9406 listed; they are always supported. */);
9407 Vimage_library_alist = Qnil;
9408 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
9409
9410 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
9411 doc: /* Maximum size of images.
9412 Emacs will not load an image into memory if its pixel width or
9413 pixel height exceeds this limit.
9414
9415 If the value is an integer, it directly specifies the maximum
9416 image height and width, measured in pixels. If it is a floating
9417 point number, it specifies the maximum image height and width
9418 as a ratio to the frame height and width. If the value is
9419 non-numeric, there is no explicit limit on the size of images. */);
9420 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
9421
9422 Vimage_type_cache = Qnil;
9423 staticpro (&Vimage_type_cache);
9424
9425 Qpbm = intern ("pbm");
9426 staticpro (&Qpbm);
9427 ADD_IMAGE_TYPE (Qpbm);
9428
9429 Qxbm = intern ("xbm");
9430 staticpro (&Qxbm);
9431 ADD_IMAGE_TYPE (Qxbm);
9432
9433 define_image_type (&xbm_type, 1);
9434 define_image_type (&pbm_type, 1);
9435
9436 Qcount = intern ("count");
9437 staticpro (&Qcount);
9438
9439 QCascent = intern (":ascent");
9440 staticpro (&QCascent);
9441 QCmargin = intern (":margin");
9442 staticpro (&QCmargin);
9443 QCrelief = intern (":relief");
9444 staticpro (&QCrelief);
9445 QCconversion = intern (":conversion");
9446 staticpro (&QCconversion);
9447 QCcolor_symbols = intern (":color-symbols");
9448 staticpro (&QCcolor_symbols);
9449 QCheuristic_mask = intern (":heuristic-mask");
9450 staticpro (&QCheuristic_mask);
9451 QCindex = intern (":index");
9452 staticpro (&QCindex);
9453 QCmatrix = intern (":matrix");
9454 staticpro (&QCmatrix);
9455 QCcolor_adjustment = intern (":color-adjustment");
9456 staticpro (&QCcolor_adjustment);
9457 QCmask = intern (":mask");
9458 staticpro (&QCmask);
9459
9460 Qlaplace = intern ("laplace");
9461 staticpro (&Qlaplace);
9462 Qemboss = intern ("emboss");
9463 staticpro (&Qemboss);
9464 Qedge_detection = intern ("edge-detection");
9465 staticpro (&Qedge_detection);
9466 Qheuristic = intern ("heuristic");
9467 staticpro (&Qheuristic);
9468
9469 Qpostscript = intern ("postscript");
9470 staticpro (&Qpostscript);
9471 #ifdef HAVE_GHOSTSCRIPT
9472 ADD_IMAGE_TYPE (Qpostscript);
9473 QCloader = intern (":loader");
9474 staticpro (&QCloader);
9475 QCbounding_box = intern (":bounding-box");
9476 staticpro (&QCbounding_box);
9477 QCpt_width = intern (":pt-width");
9478 staticpro (&QCpt_width);
9479 QCpt_height = intern (":pt-height");
9480 staticpro (&QCpt_height);
9481 #endif /* HAVE_GHOSTSCRIPT */
9482
9483 #if defined (HAVE_XPM) || defined (MAC_OS)
9484 Qxpm = intern ("xpm");
9485 staticpro (&Qxpm);
9486 ADD_IMAGE_TYPE (Qxpm);
9487 #endif
9488
9489 #if defined (HAVE_JPEG) || defined (MAC_OS)
9490 Qjpeg = intern ("jpeg");
9491 staticpro (&Qjpeg);
9492 ADD_IMAGE_TYPE (Qjpeg);
9493 #endif
9494
9495 #if defined (HAVE_TIFF) || defined (MAC_OS)
9496 Qtiff = intern ("tiff");
9497 staticpro (&Qtiff);
9498 ADD_IMAGE_TYPE (Qtiff);
9499 #endif
9500
9501 #if defined (HAVE_GIF) || defined (MAC_OS)
9502 Qgif = intern ("gif");
9503 staticpro (&Qgif);
9504 ADD_IMAGE_TYPE (Qgif);
9505 #endif
9506
9507 #if defined (HAVE_PNG) || defined (MAC_OS)
9508 Qpng = intern ("png");
9509 staticpro (&Qpng);
9510 ADD_IMAGE_TYPE (Qpng);
9511 #endif
9512
9513 #if defined (HAVE_RSVG)
9514 Qsvg = intern ("svg");
9515 staticpro (&Qsvg);
9516 ADD_IMAGE_TYPE (Qsvg);
9517 #ifdef HAVE_NTGUI
9518 Qgdk_pixbuf = intern ("gdk-pixbuf");
9519 staticpro (&Qgdk_pixbuf);
9520 Qglib = intern ("glib");
9521 staticpro (&Qglib);
9522 #endif /* HAVE_NTGUI */
9523 #endif /* HAVE_RSVG */
9524
9525 defsubr (&Sinit_image_library);
9526 defsubr (&Sclear_image_cache);
9527 defsubr (&Simage_refresh);
9528 defsubr (&Simage_size);
9529 defsubr (&Simage_mask_p);
9530 defsubr (&Simage_extension_data);
9531
9532 #if GLYPH_DEBUG
9533 defsubr (&Simagep);
9534 defsubr (&Slookup_image);
9535 #endif
9536
9537 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
9538 doc: /* Non-nil means always draw a cross over disabled images.
9539 Disabled images are those having a `:conversion disabled' property.
9540 A cross is always drawn on black & white displays. */);
9541 cross_disabled_images = 0;
9542
9543 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
9544 doc: /* List of directories to search for window system bitmap files. */);
9545 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
9546
9547 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
9548 doc: /* Time after which cached images are removed from the cache.
9549 When an image has not been displayed this many seconds, remove it
9550 from the image cache. Value must be an integer or nil with nil
9551 meaning don't clear the cache. */);
9552 Vimage_cache_eviction_delay = make_number (30 * 60);
9553 }
9554
9555 void
9556 init_image ()
9557 {
9558 }
9559
9560 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9561 (do not change this comment) */