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