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