comparison src/macfns.c @ 83066:887bb2eb4a89

Merged in changes from CVS HEAD Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-116 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-117 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-106
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 28 Feb 2004 01:33:17 +0000
parents 6c8849d06ab3
children a1da121426a9
comparison
equal deleted inserted replaced
83065:a871be7b26a5 83066:887bb2eb4a89
52 0x01, 0x02}; 52 0x01, 0x02};
53 53
54 /*#include <commdlg.h> 54 /*#include <commdlg.h>
55 #include <shellapi.h>*/ 55 #include <shellapi.h>*/
56 #include <ctype.h> 56 #include <ctype.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
57 59
58 #include <stdlib.h> 60 #include <stdlib.h>
59 #include <string.h> 61 #include <string.h>
60 #ifndef MAC_OSX 62 #ifndef MAC_OSX
61 #include <alloca.h> 63 #include <alloca.h>
62 #endif 64 #endif
63 65
64 #ifdef MAC_OSX 66 #ifdef MAC_OSX
65 #undef mktime 67 #include <QuickTime/QuickTime.h>
66 #undef DEBUG
67 #undef Z
68 #undef free
69 #undef malloc
70 #undef realloc
71 /* Macros max and min defined in lisp.h conflict with those in
72 precompiled header Carbon.h. */
73 #undef max
74 #undef min
75 #undef init_process
76 #include <Carbon/Carbon.h>
77 #undef Z
78 #define Z (current_buffer->text->z)
79 #undef free
80 #define free unexec_free
81 #undef malloc
82 #define malloc unexec_malloc
83 #undef realloc
84 #define realloc unexec_realloc
85 #undef min
86 #define min(a, b) ((a) < (b) ? (a) : (b))
87 #undef max
88 #define max(a, b) ((a) > (b) ? (a) : (b))
89 #undef init_process
90 #define init_process emacs_init_process
91 #else /* not MAC_OSX */ 68 #else /* not MAC_OSX */
92 #include <Windows.h> 69 #include <Windows.h>
93 #include <Gestalt.h> 70 #include <Gestalt.h>
94 #include <TextUtils.h> 71 #include <TextUtils.h>
95 #endif /* not MAC_OSX */ 72 #endif /* not MAC_OSX */
207 extern struct font_info *x_get_font_info (FRAME_PTR, int); 184 extern struct font_info *x_get_font_info (FRAME_PTR, int);
208 extern struct font_info *x_load_font (struct frame *, char *, int); 185 extern struct font_info *x_load_font (struct frame *, char *, int);
209 extern void x_find_ccl_program (struct font_info *); 186 extern void x_find_ccl_program (struct font_info *);
210 extern struct font_info *x_query_font (struct frame *, char *); 187 extern struct font_info *x_query_font (struct frame *, char *);
211 extern void mac_initialize (); 188 extern void mac_initialize ();
189 extern Pixmap XCreatePixmap (Display *, WindowPtr, unsigned int, unsigned int, unsigned int);
190 extern Pixmap XCreatePixmapFromBitmapData (Display *, WindowPtr, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
191 extern void XFreePixmap (Display *, Pixmap);
192 extern void XSetForeground (Display *, GC, unsigned long);
193 extern void mac_draw_line_to_pixmap (Display *, Pixmap, GC, int, int, int, int);
194
212 195
213 /* compare two strings ignoring case */ 196 /* compare two strings ignoring case */
214 197
215 static int 198 static int
216 stricmp (const char *s, const char *t) 199 stricmp (const char *s, const char *t)
550 for (i = 0; i < dpyinfo->bitmaps_last; i++) 533 for (i = 0; i < dpyinfo->bitmaps_last; i++)
551 if (dpyinfo->bitmaps[i].refcount > 0) 534 if (dpyinfo->bitmaps[i].refcount > 0)
552 xfree (dpyinfo->bitmaps[i].bitmap_data); 535 xfree (dpyinfo->bitmaps[i].bitmap_data);
553 dpyinfo->bitmaps_last = 0; 536 dpyinfo->bitmaps_last = 0;
554 } 537 }
538
539
555 540
556 /* Connect the frame-parameter names for W32 frames 541 /* Mac equivalent of XImage. */
557 to the ways of passing the parameter values to the window system. 542 typedef Pixmap XImagePtr;
558 543 #define ZPixmap 0 /* arbitrary */
559 The name of a parameter, as a Lisp symbol, 544
560 has an `x-frame-parameter' property which is an integer in Lisp 545 static XImagePtr
561 but can be interpreted as an `enum x_frame_parm' in C. */ 546 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
547 Display *display; /* not used */
548 Pixmap pixmap;
549 int x, y; /* not used */
550 unsigned int width, height; /* not used */
551 unsigned long plane_mask; /* not used */
552 int format; /* not used */
553 {
554 #if GLYPH_DEBUG
555 xassert (x == 0 && y == 0);
556 {
557 Rect ri, rp;
558 SetRect (&ri, 0, 0, width, height);
559 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
560 }
561 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
562 #endif
563
564 LockPixels (GetGWorldPixMap (pixmap));
565
566 return pixmap;
567 }
568
569 static void
570 XPutPixel (ximage, x, y, pixel)
571 XImagePtr ximage;
572 int x, y;
573 unsigned long pixel;
574 {
575 RGBColor color;
576
577 SetGWorld (ximage, NULL);
578
579 color.red = RED16_FROM_ULONG (pixel);
580 color.green = GREEN16_FROM_ULONG (pixel);
581 color.blue = BLUE16_FROM_ULONG (pixel);
582 SetCPixel (x, y, &color);
583 }
584
585 static unsigned long
586 XGetPixel (ximage, x, y)
587 XImagePtr ximage;
588 int x, y;
589 {
590 RGBColor color;
591
592 SetGWorld (ximage, NULL);
593
594 GetCPixel (x, y, &color);
595 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
596 }
597
598 static void
599 XDestroyImage (ximg)
600 XImagePtr ximg;
601 {
602 UnlockPixels (GetGWorldPixMap (ximg));
603 }
604
605
606
607 /* Useful functions defined in the section
608 `Image type independent image structures' below. */
609
610 static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
611 unsigned long height));
612
613 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
614 int depth, XImagePtr *ximg,
615 Pixmap *pixmap));
616
617 static void x_destroy_x_image P_ ((XImagePtr ximg));
618
619 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
620 static void x_disable_image P_ ((struct frame *, struct image *));
562 621
563 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 622 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
564 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 623 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
565 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 624 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
566 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object)); 625 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
579 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *, 638 static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
580 Lisp_Object, 639 Lisp_Object,
581 Lisp_Object, 640 Lisp_Object,
582 char *, char *, 641 char *, char *,
583 int)); 642 int));
643 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
644 Lisp_Object));
645 static void init_color_table P_ ((void));
646 static void free_color_table P_ ((void));
647 static unsigned long *colors_in_color_table P_ ((int *n));
648 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
649 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
584 650
585 /* Store the screen positions of frame F into XPTR and YPTR. 651 /* Store the screen positions of frame F into XPTR and YPTR.
586 These are the positions of the containing window manager window, 652 These are the positions of the containing window manager window,
587 not Emacs's own window. */ 653 not Emacs's own window. */
588 654
1380 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" }, 1446 { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
1381 { RGB_TO_ULONG(144, 238, 144), "light green" }, 1447 { RGB_TO_ULONG(144, 238, 144), "light green" },
1382 { RGB_TO_ULONG(144, 238, 144), "LightGreen" } 1448 { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
1383 }; 1449 };
1384 1450
1385 unsigned long 1451 Lisp_Object
1386 mac_color_map_lookup (colorname) 1452 mac_color_map_lookup (colorname)
1387 char *colorname; 1453 char *colorname;
1388 { 1454 {
1389 Lisp_Object ret = Qnil; 1455 Lisp_Object ret = Qnil;
1390 int i; 1456 int i;
1392 BLOCK_INPUT; 1458 BLOCK_INPUT;
1393 1459
1394 for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++) 1460 for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
1395 if (stricmp (colorname, mac_color_map[i].name) == 0) 1461 if (stricmp (colorname, mac_color_map[i].name) == 0)
1396 { 1462 {
1397 ret = mac_color_map[i].color; 1463 ret = make_number (mac_color_map[i].color);
1398 break; 1464 break;
1399 } 1465 }
1400 1466
1401 UNBLOCK_INPUT; 1467 UNBLOCK_INPUT;
1402 1468
1461 colorval |= (value << pos); 1527 colorval |= (value << pos);
1462 pos -= 8; 1528 pos -= 8;
1463 if (i == 2) 1529 if (i == 2)
1464 { 1530 {
1465 UNBLOCK_INPUT; 1531 UNBLOCK_INPUT;
1466 return (colorval); 1532 return make_number (colorval);
1467 } 1533 }
1468 color = end; 1534 color = end;
1469 } 1535 }
1470 } 1536 }
1471 } 1537 }
1514 if (i == 2) 1580 if (i == 2)
1515 { 1581 {
1516 if (*end != '\0') 1582 if (*end != '\0')
1517 break; 1583 break;
1518 UNBLOCK_INPUT; 1584 UNBLOCK_INPUT;
1519 return (colorval); 1585 return make_number (colorval);
1520 } 1586 }
1521 if (*end != '/') 1587 if (*end != '/')
1522 break; 1588 break;
1523 color = end + 1; 1589 color = end + 1;
1524 } 1590 }
1555 if (i == 2) 1621 if (i == 2)
1556 { 1622 {
1557 if (*end != '\0') 1623 if (*end != '\0')
1558 break; 1624 break;
1559 UNBLOCK_INPUT; 1625 UNBLOCK_INPUT;
1560 return (colorval); 1626 return make_number (colorval);
1561 } 1627 }
1562 if (*end != '/') 1628 if (*end != '/')
1563 break; 1629 break;
1564 color = end + 1; 1630 color = end + 1;
1565 } 1631 }
1614 gamma_correct (f, &mac_color_ref); 1680 gamma_correct (f, &mac_color_ref);
1615 XSETINT (tem, mac_color_ref); 1681 XSETINT (tem, mac_color_ref);
1616 } 1682 }
1617 1683
1618 color_def->pixel = mac_color_ref; 1684 color_def->pixel = mac_color_ref;
1619 color_def->red = RED_FROM_ULONG (mac_color_ref); 1685 color_def->red = RED16_FROM_ULONG (mac_color_ref);
1620 color_def->green = GREEN_FROM_ULONG (mac_color_ref); 1686 color_def->green = GREEN16_FROM_ULONG (mac_color_ref);
1621 color_def->blue = BLUE_FROM_ULONG (mac_color_ref); 1687 color_def->blue = BLUE16_FROM_ULONG (mac_color_ref);
1622 1688
1623 return 1; 1689 return 1;
1624 } 1690 }
1625 else 1691 else
1626 { 1692 {
1647 return BLACK_PIX_DEFAULT (f); 1713 return BLACK_PIX_DEFAULT (f);
1648 else if (strcmp (SDATA (arg), "white") == 0) 1714 else if (strcmp (SDATA (arg), "white") == 0)
1649 return WHITE_PIX_DEFAULT (f); 1715 return WHITE_PIX_DEFAULT (f);
1650 1716
1651 #if 0 1717 #if 0
1652 if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes 1718 if (FRAME_MAC_DISPLAY_INFO (f)->n_planes) == 1)
1653 * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
1654 return def; 1719 return def;
1655 #endif 1720 #endif
1656 1721
1657 if (mac_defined_color (f, SDATA (arg), &cdef, 1)) 1722 if (mac_defined_color (f, SDATA (arg), &cdef, 1))
1658 return cdef.pixel; 1723 return cdef.pixel;
1672 void 1737 void
1673 x_set_foreground_color (f, arg, oldval) 1738 x_set_foreground_color (f, arg, oldval)
1674 struct frame *f; 1739 struct frame *f;
1675 Lisp_Object arg, oldval; 1740 Lisp_Object arg, oldval;
1676 { 1741 {
1677 FRAME_FOREGROUND_PIXEL (f) 1742 unsigned long fg, old_fg;
1678 = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); 1743
1744 fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1745 old_fg = FRAME_FOREGROUND_PIXEL (f);
1746 FRAME_FOREGROUND_PIXEL (f) = fg;
1679 1747
1680 if (FRAME_MAC_WINDOW (f) != 0) 1748 if (FRAME_MAC_WINDOW (f) != 0)
1681 { 1749 {
1682 update_face_from_frame_parameter (f, Qforeground_color, arg); 1750 update_face_from_frame_parameter (f, Qforeground_color, arg);
1683 if (FRAME_VISIBLE_P (f)) 1751 if (FRAME_VISIBLE_P (f))
1854 void 1922 void
1855 x_set_cursor_color (f, arg, oldval) 1923 x_set_cursor_color (f, arg, oldval)
1856 struct frame *f; 1924 struct frame *f;
1857 Lisp_Object arg, oldval; 1925 Lisp_Object arg, oldval;
1858 { 1926 {
1859 unsigned long fore_pixel; 1927 unsigned long fore_pixel, pixel;
1860 1928
1861 if (!NILP (Vx_cursor_fore_pixel)) 1929 if (!NILP (Vx_cursor_fore_pixel))
1862 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel, 1930 fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1863 WHITE_PIX_DEFAULT (f)); 1931 WHITE_PIX_DEFAULT (f));
1864 else 1932 else
1865 fore_pixel = FRAME_BACKGROUND_PIXEL (f); 1933 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1866 f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); 1934
1935 pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1867 1936
1868 /* Make sure that the cursor color differs from the background color. */ 1937 /* Make sure that the cursor color differs from the background color. */
1869 if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f)) 1938 if (pixel == FRAME_BACKGROUND_PIXEL (f))
1870 { 1939 {
1871 f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel; 1940 pixel = f->output_data.mac->mouse_pixel;
1872 if (f->output_data.mac->cursor_pixel == fore_pixel) 1941 if (pixel == fore_pixel)
1873 fore_pixel = FRAME_BACKGROUND_PIXEL (f); 1942 fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1874 } 1943 }
1875 FRAME_FOREGROUND_PIXEL (f) = fore_pixel; 1944
1876 1945 f->output_data.mac->cursor_foreground_pixel = fore_pixel;
1877 #if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */ 1946 f->output_data.mac->cursor_pixel = pixel;
1947
1878 if (FRAME_MAC_WINDOW (f) != 0) 1948 if (FRAME_MAC_WINDOW (f) != 0)
1879 { 1949 {
1950 BLOCK_INPUT;
1951 /* Update frame's cursor_gc. */
1952 f->output_data.mac->cursor_gc->foreground = fore_pixel;
1953 f->output_data.mac->cursor_gc->background = pixel;
1954
1955 UNBLOCK_INPUT;
1956
1880 if (FRAME_VISIBLE_P (f)) 1957 if (FRAME_VISIBLE_P (f))
1881 { 1958 {
1882 BLOCK_INPUT; 1959 x_update_cursor (f, 0);
1883 display_and_set_cursor (f, 0); 1960 x_update_cursor (f, 1);
1884 display_and_set_cursor (f, 1);
1885 UNBLOCK_INPUT;
1886 } 1961 }
1887 } 1962 }
1888 #endif
1889 1963
1890 update_face_from_frame_parameter (f, Qcursor_color, arg); 1964 update_face_from_frame_parameter (f, Qcursor_color, arg);
1891 } 1965 }
1892 1966
1893 /* Set the border-color of frame F to pixel value PIX. 1967 /* Set the border-color of frame F to pixel value PIX.
1894 Note that this does not fully take effect if done before 1968 Note that this does not fully take effect if done before
1895 F has a window. */ 1969 F has a window. */
1970
1896 void 1971 void
1897 x_set_border_pixel (f, pix) 1972 x_set_border_pixel (f, pix)
1898 struct frame *f; 1973 struct frame *f;
1899 int pix; 1974 int pix;
1900 { 1975 {
1976
1901 f->output_data.mac->border_pixel = pix; 1977 f->output_data.mac->border_pixel = pix;
1902 1978
1903 if (FRAME_MAC_WINDOW (f) != 0 && f->border_width > 0) 1979 if (FRAME_MAC_WINDOW (f) != 0 && f->border_width > 0)
1904 { 1980 {
1905 if (FRAME_VISIBLE_P (f)) 1981 if (FRAME_VISIBLE_P (f))
1924 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); 2000 pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1925 x_set_border_pixel (f, pix); 2001 x_set_border_pixel (f, pix);
1926 update_face_from_frame_parameter (f, Qborder_color, arg); 2002 update_face_from_frame_parameter (f, Qborder_color, arg);
1927 } 2003 }
1928 2004
2005
1929 void 2006 void
1930 x_set_cursor_type (f, arg, oldval) 2007 x_set_cursor_type (f, arg, oldval)
1931 FRAME_PTR f; 2008 FRAME_PTR f;
1932 Lisp_Object arg, oldval; 2009 Lisp_Object arg, oldval;
1933 { 2010 {
1934 set_frame_cursor_types (f, arg); 2011 set_frame_cursor_types (f, arg);
1935 2012
1936 /* Make sure the cursor gets redrawn. This is overkill, but how 2013 /* Make sure the cursor gets redrawn. */
1937 often do people change cursor types? */ 2014 cursor_type_changed = 1;
1938 update_mode_lines++;
1939 } 2015 }
1940 2016
1941 #if 0 /* MAC_TODO: really no icon for Mac */ 2017 #if 0 /* MAC_TODO: really no icon for Mac */
1942 void 2018 void
1943 x_set_icon_type (f, arg, oldval) 2019 x_set_icon_type (f, arg, oldval)
2595 { 2671 {
2596 XGCValues gc_values; 2672 XGCValues gc_values;
2597 2673
2598 BLOCK_INPUT; 2674 BLOCK_INPUT;
2599 2675
2600 /* Create the GC's of this frame. 2676 /* Create the GCs of this frame.
2601 Note that many default values are used. */ 2677 Note that many default values are used. */
2602 2678
2603 /* Normal video */ 2679 /* Normal video */
2604 gc_values.font = FRAME_FONT (f); 2680 gc_values.font = FRAME_FONT (f);
2605 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f); 2681 gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
2627 2703
2628 /* Reliefs. */ 2704 /* Reliefs. */
2629 f->output_data.mac->white_relief.gc = 0; 2705 f->output_data.mac->white_relief.gc = 0;
2630 f->output_data.mac->black_relief.gc = 0; 2706 f->output_data.mac->black_relief.gc = 0;
2631 2707
2708 #if 0
2709 /* Create the gray border tile used when the pointer is not in
2710 the frame. Since this depends on the frame's pixel values,
2711 this must be done on a per-frame basis. */
2712 f->output_data.x->border_tile
2713 = (XCreatePixmapFromBitmapData
2714 (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
2715 gray_bits, gray_width, gray_height,
2716 f->output_data.x->foreground_pixel,
2717 f->output_data.x->background_pixel,
2718 DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
2719 #endif
2720
2632 UNBLOCK_INPUT; 2721 UNBLOCK_INPUT;
2722 }
2723
2724
2725 /* Free what was was allocated in x_make_gc. */
2726
2727 void
2728 x_free_gcs (f)
2729 struct frame *f;
2730 {
2731 Display *dpy = FRAME_MAC_DISPLAY (f);
2732
2733 BLOCK_INPUT;
2734
2735 if (f->output_data.mac->normal_gc)
2736 {
2737 XFreeGC (dpy, f->output_data.mac->normal_gc);
2738 f->output_data.mac->normal_gc = 0;
2739 }
2740
2741 if (f->output_data.mac->reverse_gc)
2742 {
2743 XFreeGC (dpy, f->output_data.mac->reverse_gc);
2744 f->output_data.mac->reverse_gc = 0;
2745 }
2746
2747 if (f->output_data.mac->cursor_gc)
2748 {
2749 XFreeGC (dpy, f->output_data.mac->cursor_gc);
2750 f->output_data.mac->cursor_gc = 0;
2751 }
2752
2753 #if 0
2754 if (f->output_data.mac->border_tile)
2755 {
2756 XFreePixmap (dpy, f->output_data.mac->border_tile);
2757 f->output_data.mac->border_tile = 0;
2758 }
2759 #endif
2760
2761 if (f->output_data.mac->white_relief.gc)
2762 {
2763 XFreeGC (dpy, f->output_data.mac->white_relief.gc);
2764 f->output_data.mac->white_relief.gc = 0;
2765 }
2766
2767 if (f->output_data.mac->black_relief.gc)
2768 {
2769 XFreeGC (dpy, f->output_data.mac->black_relief.gc);
2770 f->output_data.mac->black_relief.gc = 0;
2771 }
2772
2773 UNBLOCK_INPUT;
2774 }
2775
2776
2777 /* Handler for signals raised during x_create_frame and
2778 x_create_top_frame. FRAME is the frame which is partially
2779 constructed. */
2780
2781 static Lisp_Object
2782 unwind_create_frame (frame)
2783 Lisp_Object frame;
2784 {
2785 struct frame *f = XFRAME (frame);
2786
2787 /* If frame is ``official'', nothing to do. */
2788 if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
2789 {
2790 #if GLYPH_DEBUG
2791 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
2792 #endif
2793
2794 x_free_frame_resources (f);
2795
2796 /* Check that reference counts are indeed correct. */
2797 xassert (dpyinfo->reference_count == dpyinfo_refcount);
2798 xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
2799 return Qt;
2800 }
2801
2802 return Qnil;
2633 } 2803 }
2634 2804
2635 2805
2636 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 2806 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
2637 1, 1, 0, 2807 1, 1, 0,
2734 f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output)); 2904 f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
2735 bzero (f->output_data.mac, sizeof (struct mac_output)); 2905 bzero (f->output_data.mac, sizeof (struct mac_output));
2736 FRAME_FONTSET (f) = -1; 2906 FRAME_FONTSET (f) = -1;
2737 f->output_data.mac->scroll_bar_foreground_pixel = -1; 2907 f->output_data.mac->scroll_bar_foreground_pixel = -1;
2738 f->output_data.mac->scroll_bar_background_pixel = -1; 2908 f->output_data.mac->scroll_bar_background_pixel = -1;
2739 2909 record_unwind_protect (unwind_create_frame, frame);
2740 #if 0
2741 FRAME_FONTSET (f) = -1;
2742 #endif
2743 2910
2744 f->icon_name 2911 f->icon_name
2745 = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING); 2912 = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
2746 if (! STRINGP (f->icon_name)) 2913 if (! STRINGP (f->icon_name))
2747 f->icon_name = Qnil; 2914 f->icon_name = Qnil;
2788 2955
2789 BLOCK_INPUT; 2956 BLOCK_INPUT;
2790 /* First, try whatever font the caller has specified. */ 2957 /* First, try whatever font the caller has specified. */
2791 if (STRINGP (font)) 2958 if (STRINGP (font))
2792 { 2959 {
2793 tem = Fquery_fontset (font, Qnil); 2960 tem = Fquery_fontset (font, Qnil);
2794 if (STRINGP (tem)) 2961 if (STRINGP (tem))
2795 font = x_new_fontset (f, SDATA (tem)); 2962 font = x_new_fontset (f, SDATA (tem));
2796 else 2963 else
2797 font = x_new_font (f, SDATA (font)); 2964 font = x_new_font (f, SDATA (font));
2798 } 2965 }
2966
2799 /* Try out a font which we hope has bold and italic variations. */ 2967 /* Try out a font which we hope has bold and italic variations. */
2800 if (! STRINGP (font)) 2968 if (! STRINGP (font))
2801 font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1"); 2969 font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
2802 /* If those didn't work, look for something which will at least work. */ 2970 /* If those didn't work, look for something which will at least work. */
2803 if (!STRINGP (font)) 2971 if (! STRINGP (font))
2804 font = x_new_font (f, "-*-monaco-*-12-*-mac-roman"); 2972 font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
2805 if (! STRINGP (font)) 2973 if (! STRINGP (font))
2806 font = x_new_font (f, "-*-courier-*-10-*-mac-roman"); 2974 font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
2807 if (! STRINGP (font)) 2975 if (! STRINGP (font))
2808 error ("Cannot find any usable font"); 2976 error ("Cannot find any usable font");
3009 3177
3010 if (mac_defined_color (f, SDATA (color), &foo, 0)) 3178 if (mac_defined_color (f, SDATA (color), &foo, 0))
3011 { 3179 {
3012 Lisp_Object rgb[3]; 3180 Lisp_Object rgb[3];
3013 3181
3014 rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8) 3182 rgb[0] = make_number (foo.red);
3015 | RED_FROM_ULONG (foo.pixel)); 3183 rgb[1] = make_number (foo.green);
3016 rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8) 3184 rgb[2] = make_number (foo.blue);
3017 | GREEN_FROM_ULONG (foo.pixel));
3018 rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
3019 | BLUE_FROM_ULONG (foo.pixel));
3020 return Flist (3, rgb); 3185 return Flist (3, rgb);
3021 } 3186 }
3022 else 3187 else
3023 return Qnil; 3188 return Qnil;
3024 } 3189 }
3028 (display) 3193 (display)
3029 Lisp_Object display; 3194 Lisp_Object display;
3030 { 3195 {
3031 struct mac_display_info *dpyinfo = check_x_display_info (display); 3196 struct mac_display_info *dpyinfo = check_x_display_info (display);
3032 3197
3033 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2) 3198 if (!dpyinfo->color_p)
3034 return Qnil; 3199 return Qnil;
3035 3200
3036 return Qt; 3201 return Qt;
3037 } 3202 }
3038 3203
3046 (display) 3211 (display)
3047 Lisp_Object display; 3212 Lisp_Object display;
3048 { 3213 {
3049 struct mac_display_info *dpyinfo = check_x_display_info (display); 3214 struct mac_display_info *dpyinfo = check_x_display_info (display);
3050 3215
3051 if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1) 3216 if (dpyinfo->n_planes <= 1)
3052 return Qnil; 3217 return Qnil;
3053 3218
3054 return Qt; 3219 return Qt;
3055 } 3220 }
3056 3221
3091 (display) 3256 (display)
3092 Lisp_Object display; 3257 Lisp_Object display;
3093 { 3258 {
3094 struct mac_display_info *dpyinfo = check_x_display_info (display); 3259 struct mac_display_info *dpyinfo = check_x_display_info (display);
3095 3260
3096 return make_number (dpyinfo->n_planes * dpyinfo->n_cbits); 3261 return make_number (dpyinfo->n_planes);
3097 } 3262 }
3098 3263
3099 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, 3264 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
3100 0, 1, 0, 3265 0, 1, 0,
3101 doc: /* Returns the number of color cells of the display DISPLAY. 3266 doc: /* Returns the number of color cells of the display DISPLAY.
3106 Lisp_Object display; 3271 Lisp_Object display;
3107 { 3272 {
3108 struct mac_display_info *dpyinfo = check_x_display_info (display); 3273 struct mac_display_info *dpyinfo = check_x_display_info (display);
3109 3274
3110 /* MAC_TODO: check whether this is right */ 3275 /* MAC_TODO: check whether this is right */
3111 return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits))); 3276 return make_number (dpyinfo->n_planes >= 8 ? 256 : 1 << dpyinfo->n_planes - 1);
3112 } 3277 }
3113 3278
3114 DEFUN ("x-server-max-request-size", Fx_server_max_request_size, 3279 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
3115 Sx_server_max_request_size, 3280 Sx_server_max_request_size,
3116 0, 1, 0, 3281 0, 1, 0,
3444 Lisp_Object display, on; 3609 Lisp_Object display, on;
3445 { 3610 {
3446 return Qnil; 3611 return Qnil;
3447 } 3612 }
3448 3613
3614
3449 3615
3450 /*********************************************************************** 3616 /***********************************************************************
3451 Image types 3617 Image types
3452 ***********************************************************************/ 3618 ***********************************************************************/
3453 3619
3468 3634
3469 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; 3635 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
3470 extern Lisp_Object QCdata, QCtype; 3636 extern Lisp_Object QCdata, QCtype;
3471 Lisp_Object QCascent, QCmargin, QCrelief; 3637 Lisp_Object QCascent, QCmargin, QCrelief;
3472 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; 3638 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
3473 Lisp_Object QCindex; 3639 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
3474 3640
3475 /* Other symbols. */ 3641 /* Other symbols. */
3476 3642
3477 Lisp_Object Qlaplace; 3643 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
3478 3644
3479 /* Time in seconds after which images should be removed from the cache 3645 /* Time in seconds after which images should be removed from the cache
3480 if not displayed. */ 3646 if not displayed. */
3481 3647
3482 Lisp_Object Vimage_cache_eviction_delay; 3648 Lisp_Object Vimage_cache_eviction_delay;
3485 3651
3486 static void define_image_type P_ ((struct image_type *type)); 3652 static void define_image_type P_ ((struct image_type *type));
3487 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol)); 3653 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
3488 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object)); 3654 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
3489 static void x_laplace P_ ((struct frame *, struct image *)); 3655 static void x_laplace P_ ((struct frame *, struct image *));
3656 static void x_emboss P_ ((struct frame *, struct image *));
3490 static int x_build_heuristic_mask P_ ((struct frame *, struct image *, 3657 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
3491 Lisp_Object)); 3658 Lisp_Object));
3492 3659
3493 3660
3494 /* Define a new image type from TYPE. This adds a copy of TYPE to 3661 /* Define a new image type from TYPE. This adds a copy of TYPE to
3538 { 3705 {
3539 int valid_p = 0; 3706 int valid_p = 0;
3540 3707
3541 if (IMAGEP (object)) 3708 if (IMAGEP (object))
3542 { 3709 {
3543 Lisp_Object symbol = Fplist_get (XCDR (object), QCtype); 3710 Lisp_Object tem;
3544 struct image_type *type = lookup_image_type (symbol); 3711
3545 3712 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
3546 if (type) 3713 if (EQ (XCAR (tem), QCtype))
3547 valid_p = type->valid_p (object); 3714 {
3715 tem = XCDR (tem);
3716 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
3717 {
3718 struct image_type *type;
3719 type = lookup_image_type (XCAR (tem));
3720 if (type)
3721 valid_p = type->valid_p (object);
3722 }
3723
3724 break;
3725 }
3548 } 3726 }
3549 3727
3550 return valid_p; 3728 return valid_p;
3551 } 3729 }
3552 3730
3553 3731
3554 /* Log error message with format string FORMAT and argument ARG. 3732 /* Log error message with format string FORMAT and argument ARG.
3555 Signaling an error, e.g. when an image cannot be loaded, is not a 3733 Signaling an error, e.g. when an image cannot be loaded, is not a
3556 good idea because this would interrupt redisplay, and the error 3734 good idea because this would interrupt redisplay, and the error
3557 message display would lead to another redisplay. This function 3735 message display would lead to another redisplay. This function
3558 therefore simply displays a message. */ 3736 therefore simply displays a message. */
3559 3737
3560 static void 3738 static void
3561 image_error (format, arg1, arg2) 3739 image_error (format, arg1, arg2)
3562 char *format; 3740 char *format;
3563 Lisp_Object arg1, arg2; 3741 Lisp_Object arg1, arg2;
3573 3751
3574 enum image_value_type 3752 enum image_value_type
3575 { 3753 {
3576 IMAGE_DONT_CHECK_VALUE_TYPE, 3754 IMAGE_DONT_CHECK_VALUE_TYPE,
3577 IMAGE_STRING_VALUE, 3755 IMAGE_STRING_VALUE,
3756 IMAGE_STRING_OR_NIL_VALUE,
3578 IMAGE_SYMBOL_VALUE, 3757 IMAGE_SYMBOL_VALUE,
3579 IMAGE_POSITIVE_INTEGER_VALUE, 3758 IMAGE_POSITIVE_INTEGER_VALUE,
3580 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 3759 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
3581 IMAGE_NON_NEGATIVE_INTEGER_VALUE, 3760 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
3582 IMAGE_ASCENT_VALUE, 3761 IMAGE_ASCENT_VALUE,
3652 for (i = 0; i < nkeywords; ++i) 3831 for (i = 0; i < nkeywords; ++i)
3653 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0) 3832 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
3654 break; 3833 break;
3655 3834
3656 if (i == nkeywords) 3835 if (i == nkeywords)
3657 continue; 3836 continue;
3658 3837
3659 /* Record that we recognized the keyword. If a keywords 3838 /* Record that we recognized the keyword. If a keywords
3660 was found more than once, it's an error. */ 3839 was found more than once, it's an error. */
3661 keywords[i].value = value; 3840 keywords[i].value = value;
3662 ++keywords[i].count; 3841 ++keywords[i].count;
3667 /* Check type of value against allowed type. */ 3846 /* Check type of value against allowed type. */
3668 switch (keywords[i].type) 3847 switch (keywords[i].type)
3669 { 3848 {
3670 case IMAGE_STRING_VALUE: 3849 case IMAGE_STRING_VALUE:
3671 if (!STRINGP (value)) 3850 if (!STRINGP (value))
3851 return 0;
3852 break;
3853
3854 case IMAGE_STRING_OR_NIL_VALUE:
3855 if (!STRINGP (value) && !NILP (value))
3672 return 0; 3856 return 0;
3673 break; 3857 break;
3674 3858
3675 case IMAGE_SYMBOL_VALUE: 3859 case IMAGE_SYMBOL_VALUE:
3676 if (!SYMBOLP (value)) 3860 if (!SYMBOLP (value))
3689 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value)) 3873 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
3690 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0) 3874 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
3691 break; 3875 break;
3692 return 0; 3876 return 0;
3693 3877
3694 case IMAGE_ASCENT_VALUE: 3878 case IMAGE_ASCENT_VALUE:
3695 if (SYMBOLP (value) && EQ (value, Qcenter)) 3879 if (SYMBOLP (value) && EQ (value, Qcenter))
3696 break; 3880 break;
3697 else if (INTEGERP (value) 3881 else if (INTEGERP (value)
3698 && XINT (value) >= 0 3882 && XINT (value) >= 0
3699 && XINT (value) <= 100) 3883 && XINT (value) <= 100)
3777 if (found) 3961 if (found)
3778 *found = 0; 3962 *found = 0;
3779 return Qnil; 3963 return Qnil;
3780 } 3964 }
3781 3965
3966
3967 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
3968 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
3969 PIXELS non-nil means return the size in pixels, otherwise return the
3970 size in canonical character units.
3971 FRAME is the frame on which the image will be displayed. FRAME nil
3972 or omitted means use the selected frame. */)
3973 (spec, pixels, frame)
3974 Lisp_Object spec, pixels, frame;
3975 {
3976 Lisp_Object size;
3977
3978 size = Qnil;
3979 if (valid_image_p (spec))
3980 {
3981 struct frame *f = check_x_frame (frame);
3982 int id = lookup_image (f, spec);
3983 struct image *img = IMAGE_FROM_ID (f, id);
3984 int width = img->width + 2 * img->hmargin;
3985 int height = img->height + 2 * img->vmargin;
3986
3987 if (NILP (pixels))
3988 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
3989 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
3990 else
3991 size = Fcons (make_number (width), make_number (height));
3992 }
3993 else
3994 error ("Invalid image specification");
3995
3996 return size;
3997 }
3998
3999
4000 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
4001 doc: /* Return t if image SPEC has a mask bitmap.
4002 FRAME is the frame on which the image will be displayed. FRAME nil
4003 or omitted means use the selected frame. */)
4004 (spec, frame)
4005 Lisp_Object spec, frame;
4006 {
4007 Lisp_Object mask;
4008
4009 mask = Qnil;
4010 if (valid_image_p (spec))
4011 {
4012 struct frame *f = check_x_frame (frame);
4013 int id = lookup_image (f, spec);
4014 struct image *img = IMAGE_FROM_ID (f, id);
4015 if (img->mask)
4016 mask = Qt;
4017 }
4018 else
4019 error ("Invalid image specification");
4020
4021 return mask;
4022 }
3782 4023
3783 4024
3784 4025
3785 /*********************************************************************** 4026 /***********************************************************************
3786 Image type independent image structures 4027 Image type independent image structures
3874 int ascent; 4115 int ascent;
3875 4116
3876 if (img->ascent == CENTERED_IMAGE_ASCENT) 4117 if (img->ascent == CENTERED_IMAGE_ASCENT)
3877 { 4118 {
3878 if (face->font) 4119 if (face->font)
3879 ascent = height / 2 - (FONT_DESCENT(face->font) 4120 /* This expression is arranged so that if the image can't be
3880 - FONT_BASE(face->font)) / 2; 4121 exactly centered, it will be moved slightly up. This is
4122 because a typical font is `top-heavy' (due to the presence
4123 uppercase letters), so the image placement should err towards
4124 being top-heavy too. It also just generally looks better. */
4125 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
3881 else 4126 else
3882 ascent = height / 2; 4127 ascent = height / 2;
3883 } 4128 }
3884 else 4129 else
3885 ascent = height * img->ascent / 100.0; 4130 ascent = height * img->ascent / 100.0;
3886 4131
3887 return ascent; 4132 return ascent;
3888 } 4133 }
3889 4134
4135
4136 /* Image background colors. */
4137
4138 static unsigned long
4139 four_corners_best (ximg, width, height)
4140 XImagePtr ximg;
4141 unsigned long width, height;
4142 {
4143 unsigned long corners[4], best;
4144 int i, best_count;
4145
4146 /* Get the colors at the corners of ximg. */
4147 corners[0] = XGetPixel (ximg, 0, 0);
4148 corners[1] = XGetPixel (ximg, width - 1, 0);
4149 corners[2] = XGetPixel (ximg, width - 1, height - 1);
4150 corners[3] = XGetPixel (ximg, 0, height - 1);
4151
4152 /* Choose the most frequently found color as background. */
4153 for (i = best_count = 0; i < 4; ++i)
4154 {
4155 int j, n;
4156
4157 for (j = n = 0; j < 4; ++j)
4158 if (corners[i] == corners[j])
4159 ++n;
4160
4161 if (n > best_count)
4162 best = corners[i], best_count = n;
4163 }
4164
4165 return best;
4166 }
4167
4168 /* Return the `background' field of IMG. If IMG doesn't have one yet,
4169 it is guessed heuristically. If non-zero, XIMG is an existing XImage
4170 object to use for the heuristic. */
4171
4172 unsigned long
4173 image_background (img, f, ximg)
4174 struct image *img;
4175 struct frame *f;
4176 XImagePtr ximg;
4177 {
4178 if (! img->background_valid)
4179 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4180 {
4181 int free_ximg = !ximg;
4182
4183 if (! ximg)
4184 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4185 0, 0, img->width, img->height, ~0, ZPixmap);
4186
4187 img->background = four_corners_best (ximg, img->width, img->height);
4188
4189 if (free_ximg)
4190 XDestroyImage (ximg);
4191
4192 img->background_valid = 1;
4193 }
4194
4195 return img->background;
4196 }
4197
4198 /* Return the `background_transparent' field of IMG. If IMG doesn't
4199 have one yet, it is guessed heuristically. If non-zero, MASK is an
4200 existing XImage object to use for the heuristic. */
4201
4202 int
4203 image_background_transparent (img, f, mask)
4204 struct image *img;
4205 struct frame *f;
4206 XImagePtr mask;
4207 {
4208 if (! img->background_transparent_valid)
4209 /* IMG doesn't have a background yet, try to guess a reasonable value. */
4210 {
4211 if (img->mask)
4212 {
4213 int free_mask = !mask;
4214
4215 if (! mask)
4216 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
4217 0, 0, img->width, img->height, ~0, ZPixmap);
4218
4219 img->background_transparent
4220 = four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN (f);
4221
4222 if (free_mask)
4223 XDestroyImage (mask);
4224 }
4225 else
4226 img->background_transparent = 0;
4227
4228 img->background_transparent_valid = 1;
4229 }
4230
4231 return img->background_transparent;
4232 }
3890 4233
3891 4234
3892 /*********************************************************************** 4235 /***********************************************************************
3893 Helper functions for X image types 4236 Helper functions for X image types
3894 ***********************************************************************/ 4237 ***********************************************************************/
3895 4238
4239 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
4240 int, int));
3896 static void x_clear_image P_ ((struct frame *f, struct image *img)); 4241 static void x_clear_image P_ ((struct frame *f, struct image *img));
3897 static unsigned long x_alloc_image_color P_ ((struct frame *f, 4242 static unsigned long x_alloc_image_color P_ ((struct frame *f,
3898 struct image *img, 4243 struct image *img,
3899 Lisp_Object color_name, 4244 Lisp_Object color_name,
3900 unsigned long dflt)); 4245 unsigned long dflt));
3901 4246
4247
4248 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
4249 free the pixmap if any. MASK_P non-zero means clear the mask
4250 pixmap if any. COLORS_P non-zero means free colors allocated for
4251 the image, if any. */
4252
4253 static void
4254 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
4255 struct frame *f;
4256 struct image *img;
4257 int pixmap_p, mask_p, colors_p;
4258 {
4259 if (pixmap_p && img->pixmap)
4260 {
4261 XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
4262 img->pixmap = NULL;
4263 img->background_valid = 0;
4264 }
4265
4266 if (mask_p && img->mask)
4267 {
4268 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
4269 img->mask = NULL;
4270 img->background_transparent_valid = 0;
4271 }
4272
4273 if (colors_p && img->ncolors)
4274 {
4275 #if 0 /* TODO: color table support. */
4276 x_free_colors (f, img->colors, img->ncolors);
4277 #endif
4278 xfree (img->colors);
4279 img->colors = NULL;
4280 img->ncolors = 0;
4281 }
4282 }
4283
3902 /* Free X resources of image IMG which is used on frame F. */ 4284 /* Free X resources of image IMG which is used on frame F. */
3903 4285
3904 static void 4286 static void
3905 x_clear_image (f, img) 4287 x_clear_image (f, img)
3906 struct frame *f; 4288 struct frame *f;
3907 struct image *img; 4289 struct image *img;
3908 { 4290 {
3909 #if 0 /* MAC_TODO: W32 image support */ 4291 BLOCK_INPUT;
3910 4292 x_clear_image_1 (f, img, 1, 1, 1);
3911 if (img->pixmap) 4293 UNBLOCK_INPUT;
3912 {
3913 BLOCK_INPUT;
3914 XFreePixmap (NULL, img->pixmap);
3915 img->pixmap = 0;
3916 UNBLOCK_INPUT;
3917 }
3918
3919 if (img->ncolors)
3920 {
3921 int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
3922
3923 /* If display has an immutable color map, freeing colors is not
3924 necessary and some servers don't allow it. So don't do it. */
3925 if (class != StaticColor
3926 && class != StaticGray
3927 && class != TrueColor)
3928 {
3929 Colormap cmap;
3930 BLOCK_INPUT;
3931 cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
3932 XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
3933 img->ncolors, 0);
3934 UNBLOCK_INPUT;
3935 }
3936
3937 xfree (img->colors);
3938 img->colors = NULL;
3939 img->ncolors = 0;
3940 }
3941 #endif /* MAC_TODO */
3942 } 4294 }
3943 4295
3944 4296
3945 /* Allocate color COLOR_NAME for image IMG on frame F. If color 4297 /* Allocate color COLOR_NAME for image IMG on frame F. If color
3946 cannot be allocated, use DFLT. Add a newly allocated color to 4298 cannot be allocated, use DFLT. Add a newly allocated color to
3952 struct frame *f; 4304 struct frame *f;
3953 struct image *img; 4305 struct image *img;
3954 Lisp_Object color_name; 4306 Lisp_Object color_name;
3955 unsigned long dflt; 4307 unsigned long dflt;
3956 { 4308 {
3957 #if 0 /* MAC_TODO: allocing colors. */
3958 XColor color; 4309 XColor color;
3959 unsigned long result; 4310 unsigned long result;
3960 4311
3961 xassert (STRINGP (color_name)); 4312 xassert (STRINGP (color_name));
3962 4313
3963 if (w32_defined_color (f, SDATA (color_name), &color, 1)) 4314 if (mac_defined_color (f, SDATA (color_name), &color, 1))
3964 { 4315 {
3965 /* This isn't called frequently so we get away with simply 4316 /* This isn't called frequently so we get away with simply
3966 reallocating the color vector to the needed size, here. */ 4317 reallocating the color vector to the needed size, here. */
3967 ++img->ncolors; 4318 ++img->ncolors;
3968 img->colors = 4319 img->colors =
3971 img->colors[img->ncolors - 1] = color.pixel; 4322 img->colors[img->ncolors - 1] = color.pixel;
3972 result = color.pixel; 4323 result = color.pixel;
3973 } 4324 }
3974 else 4325 else
3975 result = dflt; 4326 result = dflt;
4327
3976 return result; 4328 return result;
3977 #endif /* MAC_TODO */
3978 return 0;
3979 } 4329 }
3980 4330
3981 4331
3982 4332
3983 /*********************************************************************** 4333 /***********************************************************************
3984 Image Cache 4334 Image Cache
3985 ***********************************************************************/ 4335 ***********************************************************************/
3986 4336
3987 static void cache_image P_ ((struct frame *f, struct image *img)); 4337 static void cache_image P_ ((struct frame *f, struct image *img));
4338 static void postprocess_image P_ ((struct frame *, struct image *));
3988 4339
3989 4340
3990 /* Return a new, initialized image cache that is allocated from the 4341 /* Return a new, initialized image cache that is allocated from the
3991 heap. Call free_image_cache to free an image cache. */ 4342 heap. Call free_image_cache to free an image cache. */
3992 4343
4047 4398
4048 if (c && INTEGERP (Vimage_cache_eviction_delay)) 4399 if (c && INTEGERP (Vimage_cache_eviction_delay))
4049 { 4400 {
4050 EMACS_TIME t; 4401 EMACS_TIME t;
4051 unsigned long old; 4402 unsigned long old;
4052 int i, any_freed_p = 0; 4403 int i, nfreed;
4053 4404
4054 EMACS_GET_TIME (t); 4405 EMACS_GET_TIME (t);
4055 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay); 4406 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
4056 4407
4057 for (i = 0; i < c->used; ++i) 4408 /* Block input so that we won't be interrupted by a SIGIO
4409 while being in an inconsistent state. */
4410 BLOCK_INPUT;
4411
4412 for (i = nfreed = 0; i < c->used; ++i)
4058 { 4413 {
4059 struct image *img = c->images[i]; 4414 struct image *img = c->images[i];
4060 if (img != NULL 4415 if (img != NULL
4061 && (force_p 4416 && (force_p || img->timestamp < old))
4062 || (img->timestamp > old)))
4063 { 4417 {
4064 free_image (f, img); 4418 free_image (f, img);
4065 any_freed_p = 1; 4419 ++nfreed;
4066 } 4420 }
4067 } 4421 }
4068 4422
4069 /* We may be clearing the image cache because, for example, 4423 /* We may be clearing the image cache because, for example,
4070 Emacs was iconified for a longer period of time. In that 4424 Emacs was iconified for a longer period of time. In that
4071 case, current matrices may still contain references to 4425 case, current matrices may still contain references to
4072 images freed above. So, clear these matrices. */ 4426 images freed above. So, clear these matrices. */
4073 if (any_freed_p) 4427 if (nfreed)
4074 { 4428 {
4075 clear_current_matrices (f); 4429 Lisp_Object tail, frame;
4430
4431 FOR_EACH_FRAME (tail, frame)
4432 {
4433 struct frame *f = XFRAME (frame);
4434 if (FRAME_MAC_P (f)
4435 && FRAME_X_IMAGE_CACHE (f) == c)
4436 clear_current_matrices (f);
4437 }
4438
4076 ++windows_or_buffers_changed; 4439 ++windows_or_buffers_changed;
4077 } 4440 }
4441
4442 UNBLOCK_INPUT;
4078 } 4443 }
4079 } 4444 }
4080 4445
4081 4446
4082 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache, 4447 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
4083 0, 1, 0, 4448 0, 1, 0,
4084 doc: /* Clear the image cache of FRAME. 4449 doc: /* Clear the image cache of FRAME.
4085 FRAME nil or omitted means use the selected frame. 4450 FRAME nil or omitted means use the selected frame.
4086 FRAME t means clear the image caches of all frames. */) 4451 FRAME t means clear the image caches of all frames. */)
4087 (frame) 4452 (frame)
4088 Lisp_Object frame; 4453 Lisp_Object frame;
4089 { 4454 {
4090 if (EQ (frame, Qt)) 4455 if (EQ (frame, Qt))
4091 { 4456 {
4092 Lisp_Object tail; 4457 Lisp_Object tail;
4097 } 4462 }
4098 else 4463 else
4099 clear_image_cache (check_x_frame (frame), 1); 4464 clear_image_cache (check_x_frame (frame), 1);
4100 4465
4101 return Qnil; 4466 return Qnil;
4467 }
4468
4469
4470 /* Compute masks and transform image IMG on frame F, as specified
4471 by the image's specification, */
4472
4473 static void
4474 postprocess_image (f, img)
4475 struct frame *f;
4476 struct image *img;
4477 {
4478 /* Manipulation of the image's mask. */
4479 if (img->pixmap)
4480 {
4481 Lisp_Object conversion, spec;
4482 Lisp_Object mask;
4483
4484 spec = img->spec;
4485
4486 /* `:heuristic-mask t'
4487 `:mask heuristic'
4488 means build a mask heuristically.
4489 `:heuristic-mask (R G B)'
4490 `:mask (heuristic (R G B))'
4491 means build a mask from color (R G B) in the
4492 image.
4493 `:mask nil'
4494 means remove a mask, if any. */
4495
4496 mask = image_spec_value (spec, QCheuristic_mask, NULL);
4497 if (!NILP (mask))
4498 x_build_heuristic_mask (f, img, mask);
4499 else
4500 {
4501 int found_p;
4502
4503 mask = image_spec_value (spec, QCmask, &found_p);
4504
4505 if (EQ (mask, Qheuristic))
4506 x_build_heuristic_mask (f, img, Qt);
4507 else if (CONSP (mask)
4508 && EQ (XCAR (mask), Qheuristic))
4509 {
4510 if (CONSP (XCDR (mask)))
4511 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
4512 else
4513 x_build_heuristic_mask (f, img, XCDR (mask));
4514 }
4515 else if (NILP (mask) && found_p && img->mask)
4516 {
4517 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
4518 img->mask = NULL;
4519 }
4520 }
4521
4522
4523 /* Should we apply an image transformation algorithm? */
4524 conversion = image_spec_value (spec, QCconversion, NULL);
4525 if (EQ (conversion, Qdisabled))
4526 x_disable_image (f, img);
4527 else if (EQ (conversion, Qlaplace))
4528 x_laplace (f, img);
4529 else if (EQ (conversion, Qemboss))
4530 x_emboss (f, img);
4531 else if (CONSP (conversion)
4532 && EQ (XCAR (conversion), Qedge_detection))
4533 {
4534 Lisp_Object tem;
4535 tem = XCDR (conversion);
4536 if (CONSP (tem))
4537 x_edge_detection (f, img,
4538 Fplist_get (tem, QCmatrix),
4539 Fplist_get (tem, QCcolor_adjustment));
4540 }
4541 }
4102 } 4542 }
4103 4543
4104 4544
4105 /* Return the id of image with Lisp specification SPEC on frame F. 4545 /* Return the id of image with Lisp specification SPEC on frame F.
4106 SPEC must be a valid Lisp image specification (see valid_image_p). */ 4546 SPEC must be a valid Lisp image specification (see valid_image_p). */
4133 break; 4573 break;
4134 4574
4135 /* If not found, create a new image and cache it. */ 4575 /* If not found, create a new image and cache it. */
4136 if (img == NULL) 4576 if (img == NULL)
4137 { 4577 {
4578 extern Lisp_Object Qpostscript;
4579
4138 BLOCK_INPUT; 4580 BLOCK_INPUT;
4139 img = make_image (spec, hash); 4581 img = make_image (spec, hash);
4140 cache_image (f, img); 4582 cache_image (f, img);
4141 img->load_failed_p = img->type->load (f, img) == 0; 4583 img->load_failed_p = img->type->load (f, img) == 0;
4142 xassert (!interrupt_input_blocked);
4143 4584
4144 /* If we can't load the image, and we don't have a width and 4585 /* If we can't load the image, and we don't have a width and
4145 height, use some arbitrary width and height so that we can 4586 height, use some arbitrary width and height so that we can
4146 draw a rectangle for it. */ 4587 draw a rectangle for it. */
4147 if (img->load_failed_p) 4588 if (img->load_failed_p)
4156 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT); 4597 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
4157 } 4598 }
4158 else 4599 else
4159 { 4600 {
4160 /* Handle image type independent image attributes 4601 /* Handle image type independent image attributes
4161 `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */ 4602 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
4162 Lisp_Object ascent, margin, relief; 4603 `:background COLOR'. */
4604 Lisp_Object ascent, margin, relief, bg;
4163 4605
4164 ascent = image_spec_value (spec, QCascent, NULL); 4606 ascent = image_spec_value (spec, QCascent, NULL);
4165 if (INTEGERP (ascent)) 4607 if (INTEGERP (ascent))
4166 img->ascent = XFASTINT (ascent); 4608 img->ascent = XFASTINT (ascent);
4167 else if (EQ (ascent, Qcenter)) 4609 else if (EQ (ascent, Qcenter))
4168 img->ascent = CENTERED_IMAGE_ASCENT; 4610 img->ascent = CENTERED_IMAGE_ASCENT;
4169 4611
4170 margin = image_spec_value (spec, QCmargin, NULL); 4612 margin = image_spec_value (spec, QCmargin, NULL);
4171 if (INTEGERP (margin) && XINT (margin) >= 0) 4613 if (INTEGERP (margin) && XINT (margin) >= 0)
4172 img->vmargin = img->hmargin = XFASTINT (margin); 4614 img->vmargin = img->hmargin = XFASTINT (margin);
4173 else if (CONSP (margin) && INTEGERP (XCAR (margin)) 4615 else if (CONSP (margin) && INTEGERP (XCAR (margin))
4184 { 4626 {
4185 img->relief = XINT (relief); 4627 img->relief = XINT (relief);
4186 img->hmargin += abs (img->relief); 4628 img->hmargin += abs (img->relief);
4187 img->vmargin += abs (img->relief); 4629 img->vmargin += abs (img->relief);
4188 } 4630 }
4631
4632 if (! img->background_valid)
4633 {
4634 bg = image_spec_value (img->spec, QCbackground, NULL);
4635 if (!NILP (bg))
4636 {
4637 img->background
4638 = x_alloc_image_color (f, img, bg,
4639 FRAME_BACKGROUND_PIXEL (f));
4640 img->background_valid = 1;
4641 }
4642 }
4643
4644 /* Do image transformations and compute masks, unless we
4645 don't have the image yet. */
4646 if (!EQ (*img->type->type, Qpostscript))
4647 postprocess_image (f, img);
4189 } 4648 }
4649
4650 UNBLOCK_INPUT;
4190 } 4651 }
4191 4652
4192 /* We're using IMG, so set its timestamp to `now'. */ 4653 /* We're using IMG, so set its timestamp to `now'. */
4193 EMACS_GET_TIME (now); 4654 EMACS_GET_TIME (now);
4194 img->timestamp = EMACS_SECS (now); 4655 img->timestamp = EMACS_SECS (now);
4264 4725
4265 /*********************************************************************** 4726 /***********************************************************************
4266 Mac support code 4727 Mac support code
4267 ***********************************************************************/ 4728 ***********************************************************************/
4268 4729
4269 #if 0 /* MAC_TODO: Mac specific image code. */
4270
4271 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int, 4730 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
4272 XImage **, Pixmap *)); 4731 XImagePtr *, Pixmap *));
4273 static void x_destroy_x_image P_ ((XImage *)); 4732 static void x_destroy_x_image P_ ((XImagePtr));
4274 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int)); 4733 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
4275 4734
4276 4735
4277 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
4278 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
4279 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
4280 via xmalloc. Print error messages via image_error if an error
4281 occurs. Value is non-zero if successful. */
4282
4283 static int
4284 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap) 4736 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
4285 struct frame *f; 4737 struct frame *f;
4286 int width, height, depth; 4738 int width, height, depth;
4287 XImage **ximg; 4739 XImagePtr *ximg;
4288 Pixmap *pixmap; 4740 Pixmap *pixmap;
4289 { 4741 {
4290 #if 0 /* MAC_TODO: Image support for Mac */ 4742 Display *display = FRAME_MAC_DISPLAY (f);
4291 Display *display = FRAME_W32_DISPLAY (f); 4743 Window window = FRAME_MAC_WINDOW (f);
4292 Screen *screen = FRAME_X_SCREEN (f);
4293 Window window = FRAME_W32_WINDOW (f);
4294 4744
4295 xassert (interrupt_input_blocked); 4745 xassert (interrupt_input_blocked);
4296
4297 if (depth <= 0)
4298 depth = DefaultDepthOfScreen (screen);
4299 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
4300 depth, ZPixmap, 0, NULL, width, height,
4301 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
4302 if (*ximg == NULL)
4303 {
4304 image_error ("Unable to allocate X image", Qnil, Qnil);
4305 return 0;
4306 }
4307
4308 /* Allocate image raster. */
4309 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
4310 4746
4311 /* Allocate a pixmap of the same size. */ 4747 /* Allocate a pixmap of the same size. */
4312 *pixmap = XCreatePixmap (display, window, width, height, depth); 4748 *pixmap = XCreatePixmap (display, window, width, height, depth);
4313 if (*pixmap == 0) 4749 if (*pixmap == 0)
4314 { 4750 {
4315 x_destroy_x_image (*ximg); 4751 x_destroy_x_image (*ximg);
4316 *ximg = NULL; 4752 *ximg = NULL;
4317 image_error ("Unable to create X pixmap", Qnil, Qnil); 4753 image_error ("Unable to create X pixmap", Qnil, Qnil);
4318 return 0; 4754 return 0;
4319 } 4755 }
4320 #endif /* MAC_TODO */ 4756
4757 LockPixels (GetGWorldPixMap (*pixmap));
4758 *ximg = *pixmap;
4321 return 1; 4759 return 1;
4322 } 4760 }
4323
4324
4325 /* Destroy XImage XIMG. Free XIMG->data. */
4326 4761
4327 static void 4762 static void
4328 x_destroy_x_image (ximg) 4763 x_destroy_x_image (ximg)
4329 XImage *ximg; 4764 XImagePtr ximg;
4330 { 4765 {
4331 xassert (interrupt_input_blocked); 4766 xassert (interrupt_input_blocked);
4332 if (ximg) 4767 if (ximg)
4333 { 4768 XDestroyImage (ximg);
4334 xfree (ximg->data); 4769 }
4335 ximg->data = NULL;
4336 XDestroyImage (ximg);
4337 }
4338 }
4339
4340
4341 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
4342 are width and height of both the image and pixmap. */
4343 4770
4344 static void 4771 static void
4345 x_put_x_image (f, ximg, pixmap, width, height) 4772 x_put_x_image (f, ximg, pixmap, width, height)
4346 struct frame *f; 4773 struct frame *f;
4347 XImage *ximg; 4774 XImagePtr ximg;
4348 Pixmap pixmap; 4775 Pixmap pixmap;
4349 { 4776 {
4350 GC gc; 4777 xassert (ximg == pixmap);
4351 4778 }
4352 xassert (interrupt_input_blocked); 4779
4353 gc = XCreateGC (NULL, pixmap, 0, NULL);
4354 XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
4355 XFreeGC (NULL, gc);
4356 }
4357
4358 #endif /* MAC_TODO */
4359 4780
4360 4781
4361 /*********************************************************************** 4782 /***********************************************************************
4362 Searching files 4783 File Handling
4363 ***********************************************************************/ 4784 ***********************************************************************/
4364 4785
4365 static Lisp_Object x_find_image_file P_ ((Lisp_Object)); 4786 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
4787 static char *slurp_file P_ ((char *, int *));
4788
4366 4789
4367 /* Find image file FILE. Look in data-directory, then 4790 /* Find image file FILE. Look in data-directory, then
4368 x-bitmap-file-path. Value is the full name of the file found, or 4791 x-bitmap-file-path. Value is the full name of the file found, or
4369 nil if not found. */ 4792 nil if not found. */
4370 4793
4381 GCPRO2 (file_found, search_path); 4804 GCPRO2 (file_found, search_path);
4382 4805
4383 /* Try to find FILE in data-directory, then x-bitmap-file-path. */ 4806 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
4384 fd = openp (search_path, file, Qnil, &file_found, Qnil); 4807 fd = openp (search_path, file, Qnil, &file_found, Qnil);
4385 4808
4386 if (fd < 0) 4809 if (fd == -1)
4387 file_found = Qnil; 4810 file_found = Qnil;
4388 else 4811 else
4389 close (fd); 4812 close (fd);
4390 4813
4391 UNGCPRO; 4814 UNGCPRO;
4392 return file_found; 4815 return file_found;
4393 } 4816 }
4817
4818
4819 /* Read FILE into memory. Value is a pointer to a buffer allocated
4820 with xmalloc holding FILE's contents. Value is null if an error
4821 occurred. *SIZE is set to the size of the file. */
4822
4823 static char *
4824 slurp_file (file, size)
4825 char *file;
4826 int *size;
4827 {
4828 FILE *fp = NULL;
4829 char *buf = NULL;
4830 struct stat st;
4831
4832 if (stat (file, &st) == 0
4833 && (fp = fopen (file, "r")) != NULL
4834 && (buf = (char *) xmalloc (st.st_size),
4835 fread (buf, 1, st.st_size, fp) == st.st_size))
4836 {
4837 *size = st.st_size;
4838 fclose (fp);
4839 }
4840 else
4841 {
4842 if (fp)
4843 fclose (fp);
4844 if (buf)
4845 {
4846 xfree (buf);
4847 buf = NULL;
4848 }
4849 }
4850
4851 return buf;
4852 }
4853
4854
4855
4856 /***********************************************************************
4857 Image Load Functions
4858 ***********************************************************************/
4859
4860 static int image_load_quicktime P_ ((struct frame *, struct image *img,
4861 OSType));
4862 #ifdef MAC_OSX
4863 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
4864 #endif
4865
4866
4867 static OSErr
4868 find_image_fsspec (specified_file, file, fss)
4869 Lisp_Object specified_file, *file;
4870 FSSpec *fss;
4871 {
4872 #if TARGET_API_MAC_CARBON
4873 FSRef fsr;
4874 #else
4875 Str255 mac_pathname;
4876 #endif
4877 OSErr err;
4878
4879 *file = x_find_image_file (specified_file);
4880 if (!STRINGP (*file))
4881 return fnfErr; /* file or directory not found;
4882 incomplete pathname */
4883 /* Try to open the image file. */
4884 #if TARGET_API_MAC_CARBON
4885 err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
4886 if (err == noErr)
4887 err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
4888 #else
4889 if (posix_to_mac_pathname (SDATA (*file), mac_pathname, MAXPATHLEN+1) == 0)
4890 return fnfErr;
4891 c2pstr (mac_pathname);
4892 err = FSMakeFSSpec (0, 0, mac_pathname, fss);
4893 #endif
4894 return err;
4895 }
4896
4897
4898 static int
4899 image_load_qt_1 (f, img, type, fss, dh)
4900 struct frame *f;
4901 struct image *img;
4902 OSType type;
4903 FSSpec *fss;
4904 Handle dh;
4905 {
4906 OSErr err;
4907 GraphicsImportComponent gi;
4908 Rect rect;
4909 int width, height;
4910 short draw_all_pixels;
4911 Lisp_Object specified_bg;
4912 XColor color;
4913 XImagePtr ximg;
4914 RGBColor bg_color;
4915
4916 err = OpenADefaultComponent (GraphicsImporterComponentType,
4917 type, &gi);
4918 if (err != noErr)
4919 {
4920 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
4921 return 0;
4922 }
4923 if (dh == NULL)
4924 {
4925 /* read from file system spec */
4926 err = GraphicsImportSetDataFile (gi, fss);
4927 if (err != noErr)
4928 {
4929 image_error ("Cannot set fsspec to graphics importer for '%s'",
4930 img->spec, Qnil);
4931 goto error;
4932 }
4933 }
4934 else
4935 {
4936 /* read from data handle */
4937 err = GraphicsImportSetDataHandle (gi, dh);
4938 if (err != noErr)
4939 {
4940 image_error ("Cannot set data handle to graphics importer for `%s'",
4941 img->spec, Qnil);
4942 goto error;
4943 }
4944 }
4945 err = GraphicsImportGetNaturalBounds (gi, &rect);
4946 if (err != noErr)
4947 {
4948 image_error ("Error reading `%s'", img->spec, Qnil);
4949 goto error;
4950 }
4951 width = img->width = rect.right - rect.left;
4952 height = img->height = rect.bottom - rect.top;
4953 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
4954 #if 0
4955 /* Don't check the error code here. It may have an undocumented
4956 value -32766. */
4957 if (err != noErr)
4958 {
4959 image_error ("Error reading `%s'", img->spec, Qnil);
4960 goto error;
4961 }
4962 #endif
4963 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
4964 {
4965 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
4966 if (!STRINGP (specified_bg) ||
4967 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
4968 {
4969 color.pixel = FRAME_BACKGROUND_PIXEL (f);
4970 color.red = RED16_FROM_ULONG (color.pixel);
4971 color.green = GREEN16_FROM_ULONG (color.pixel);
4972 color.blue = BLUE16_FROM_ULONG (color.pixel);
4973 }
4974 }
4975
4976 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
4977 goto error;
4978 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
4979 {
4980 SetGWorld (ximg, NULL);
4981 bg_color.red = color.red;
4982 bg_color.green = color.green;
4983 bg_color.blue = color.blue;
4984 RGBBackColor (&bg_color);
4985 #if TARGET_API_MAC_CARBON
4986 GetPortBounds (ximg, &rect);
4987 EraseRect (&rect);
4988 #else
4989 EraseRect (&(ximg->portRect));
4990 #endif
4991 }
4992 GraphicsImportSetGWorld (gi, ximg, NULL);
4993 GraphicsImportDraw (gi);
4994 CloseComponent (gi);
4995
4996 /* Maybe fill in the background field while we have ximg handy. */
4997 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4998 IMAGE_BACKGROUND (img, f, ximg);
4999
5000 /* Put the image into the pixmap. */
5001 x_put_x_image (f, ximg, img->pixmap, width, height);
5002 x_destroy_x_image (ximg);
5003 return 1;
5004
5005 error:
5006 CloseComponent (gi);
5007 return 0;
5008 }
5009
5010
5011 /* Load an image using the QuickTime Graphics Importer.
5012 Note: The alpha channel does not work for PNG images. */
5013 static int
5014 image_load_quicktime (f, img, type)
5015 struct frame *f;
5016 struct image *img;
5017 OSType type;
5018 {
5019 Lisp_Object specified_file;
5020 Lisp_Object specified_data;
5021 OSErr err;
5022
5023 specified_file = image_spec_value (img->spec, QCfile, NULL);
5024 specified_data = image_spec_value (img->spec, QCdata, NULL);
5025
5026 if (NILP (specified_data))
5027 {
5028 /* Read from a file */
5029 Lisp_Object file;
5030 FSSpec fss;
5031
5032 err = find_image_fsspec (specified_file, &file, &fss);
5033 if (err != noErr)
5034 {
5035 if (err == fnfErr)
5036 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5037 else
5038 image_error ("Cannot open `%s'", file, Qnil);
5039 return 0;
5040 }
5041 return image_load_qt_1 (f, img, type, &fss, NULL);
5042 }
5043 else
5044 {
5045 /* Memory source! */
5046 int success_p;
5047 Handle dh;
5048
5049 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
5050 if (err != noErr)
5051 {
5052 image_error ("Cannot allocate data handle for `%s'",
5053 img->spec, Qnil);
5054 return 0;
5055 }
5056 success_p = image_load_qt_1 (f, img, type, NULL, dh);
5057 DisposeHandle (dh);
5058 return success_p;
5059 }
5060 }
5061
5062
5063 #ifdef MAC_OSX
5064 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
5065 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
5066 So don't use this function directly but determine at runtime
5067 whether it exists. */
5068 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
5069 (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
5070 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
5071
5072
5073 static void
5074 init_image_func_pointer ()
5075 {
5076 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
5077 {
5078 MyCGImageCreateWithPNGDataProvider
5079 = (CGImageCreateWithPNGDataProviderProcType)
5080 NSAddressOfSymbol (NSLookupAndBindSymbol
5081 ("_CGImageCreateWithPNGDataProvider"));
5082 }
5083 else
5084 MyCGImageCreateWithPNGDataProvider = NULL;
5085 }
5086
5087
5088 static int
5089 image_load_quartz2d (f, img, png_p)
5090 struct frame *f;
5091 struct image *img;
5092 int png_p;
5093 {
5094 Lisp_Object file, specified_file;
5095 Lisp_Object specified_data, specified_bg;
5096 struct gcpro gcpro1;
5097 CGDataProviderRef source;
5098 CGImageRef image;
5099 int width, height;
5100 XColor color;
5101 XImagePtr ximg = NULL;
5102 CGContextRef context;
5103 CGRect rectangle;
5104
5105 /* Open the file. */
5106 specified_file = image_spec_value (img->spec, QCfile, NULL);
5107 specified_data = image_spec_value (img->spec, QCdata, NULL);
5108
5109 file = Qnil;
5110 GCPRO1 (file);
5111
5112 if (NILP (specified_data))
5113 {
5114 CFStringRef path;
5115 CFURLRef url;
5116
5117 file = x_find_image_file (specified_file);
5118 if (!STRINGP (file))
5119 {
5120 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5121 UNGCPRO;
5122 return 0;
5123 }
5124 path = CFStringCreateWithCString (NULL, SDATA (file),
5125 kCFStringEncodingUTF8);
5126 url = CFURLCreateWithFileSystemPath (NULL, path,
5127 kCFURLPOSIXPathStyle, 0);
5128 CFRelease (path);
5129 source = CGDataProviderCreateWithURL (url);
5130 CFRelease (url);
5131 }
5132 else
5133 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
5134 SBYTES (specified_data), NULL);
5135
5136 if (png_p)
5137 image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
5138 kCGRenderingIntentDefault);
5139 else
5140 image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
5141 kCGRenderingIntentDefault);
5142
5143 CGDataProviderRelease (source);
5144 if (image == NULL)
5145 {
5146 UNGCPRO;
5147 image_error ("Error reading image `%s'", img->spec, Qnil);
5148 return 0;
5149 }
5150
5151 if (png_p)
5152 {
5153 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
5154 if (!STRINGP (specified_bg) ||
5155 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
5156 {
5157 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5158 color.red = RED16_FROM_ULONG (color.pixel);
5159 color.green = GREEN16_FROM_ULONG (color.pixel);
5160 color.blue = BLUE16_FROM_ULONG (color.pixel);
5161 }
5162 }
5163 width = img->width = CGImageGetWidth (image);
5164 height = img->height = CGImageGetHeight (image);
5165 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
5166 {
5167 CGImageRelease (image);
5168 UNGCPRO;
5169 return 0;
5170 }
5171 rectangle = CGRectMake (0, 0, width, height);
5172 QDBeginCGContext (ximg, &context);
5173 if (png_p)
5174 {
5175 CGContextSetRGBFillColor (context, color.red / 65535.0,
5176 color.green / 65535.0,
5177 color.blue / 65535.0, 1.0);
5178 CGContextFillRect (context, rectangle);
5179 }
5180 CGContextDrawImage (context, rectangle, image);
5181 QDEndCGContext (ximg, &context);
5182 CGImageRelease (image);
5183
5184 /* Maybe fill in the background field while we have ximg handy. */
5185 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5186 IMAGE_BACKGROUND (img, f, ximg);
5187
5188 /* Put the image into the pixmap. */
5189 x_put_x_image (f, ximg, img->pixmap, width, height);
5190 x_destroy_x_image (ximg);
5191 UNGCPRO;
5192 return 1;
5193 }
5194 #endif
5195
4394 5196
4395 5197
4396 /*********************************************************************** 5198 /***********************************************************************
4397 XBM images 5199 XBM images
4398 ***********************************************************************/ 5200 ***********************************************************************/
4399 5201
5202 static int xbm_scan P_ ((char **, char *, char *, int *));
4400 static int xbm_load P_ ((struct frame *f, struct image *img)); 5203 static int xbm_load P_ ((struct frame *f, struct image *img));
4401 static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img, 5204 static int xbm_load_image P_ ((struct frame *f, struct image *img,
4402 Lisp_Object file)); 5205 char *, char *));
4403 static int xbm_image_p P_ ((Lisp_Object object)); 5206 static int xbm_image_p P_ ((Lisp_Object object));
4404 static int xbm_read_bitmap_file_data P_ ((char *, int *, int *, 5207 static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
4405 unsigned char **)); 5208 unsigned char **));
5209 static int xbm_file_p P_ ((Lisp_Object));
4406 5210
4407 5211
4408 /* Indices of image specification fields in xbm_format, below. */ 5212 /* Indices of image specification fields in xbm_format, below. */
4409 5213
4410 enum xbm_keyword_index 5214 enum xbm_keyword_index
4419 XBM_ASCENT, 5223 XBM_ASCENT,
4420 XBM_MARGIN, 5224 XBM_MARGIN,
4421 XBM_RELIEF, 5225 XBM_RELIEF,
4422 XBM_ALGORITHM, 5226 XBM_ALGORITHM,
4423 XBM_HEURISTIC_MASK, 5227 XBM_HEURISTIC_MASK,
5228 XBM_MASK,
4424 XBM_LAST 5229 XBM_LAST
4425 }; 5230 };
4426 5231
4427 /* Vector of image_keyword structures describing the format 5232 /* Vector of image_keyword structures describing the format
4428 of valid XBM image specifications. */ 5233 of valid XBM image specifications. */
4432 {":type", IMAGE_SYMBOL_VALUE, 1}, 5237 {":type", IMAGE_SYMBOL_VALUE, 1},
4433 {":file", IMAGE_STRING_VALUE, 0}, 5238 {":file", IMAGE_STRING_VALUE, 0},
4434 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 5239 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
4435 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 5240 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
4436 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 5241 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4437 {":foreground", IMAGE_STRING_VALUE, 0}, 5242 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
4438 {":background", IMAGE_STRING_VALUE, 0}, 5243 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
4439 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 5244 {":ascent", IMAGE_ASCENT_VALUE, 0},
4440 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 5245 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
4441 {":relief", IMAGE_INTEGER_VALUE, 0}, 5246 {":relief", IMAGE_INTEGER_VALUE, 0},
4442 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 5247 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4443 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 5248 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5249 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
4444 }; 5250 };
4445 5251
4446 /* Structure describing the image type XBM. */ 5252 /* Structure describing the image type XBM. */
4447 5253
4448 static struct image_type xbm_type = 5254 static struct image_type xbm_type =
4481 2. a bool-vector of size >= WIDTH * HEIGHT 5287 2. a bool-vector of size >= WIDTH * HEIGHT
4482 5288
4483 3. a vector of strings or bool-vectors, one for each line of the 5289 3. a vector of strings or bool-vectors, one for each line of the
4484 bitmap. 5290 bitmap.
4485 5291
5292 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
5293 may not be specified in this case because they are defined in the
5294 XBM file.
5295
4486 Both the file and data forms may contain the additional entries 5296 Both the file and data forms may contain the additional entries
4487 `:background COLOR' and `:foreground COLOR'. If not present, 5297 `:background COLOR' and `:foreground COLOR'. If not present,
4488 foreground and background of the frame on which the image is 5298 foreground and background of the frame on which the image is
4489 displayed, is used. */ 5299 displayed is used. */
4490 5300
4491 static int 5301 static int
4492 xbm_image_p (object) 5302 xbm_image_p (object)
4493 Lisp_Object object; 5303 Lisp_Object object;
4494 { 5304 {
4501 xassert (EQ (kw[XBM_TYPE].value, Qxbm)); 5311 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
4502 5312
4503 if (kw[XBM_FILE].count) 5313 if (kw[XBM_FILE].count)
4504 { 5314 {
4505 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count) 5315 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
5316 return 0;
5317 }
5318 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
5319 {
5320 /* In-memory XBM file. */
5321 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
4506 return 0; 5322 return 0;
4507 } 5323 }
4508 else 5324 else
4509 { 5325 {
4510 Lisp_Object data; 5326 Lisp_Object data;
4564 } 5380 }
4565 else 5381 else
4566 return 0; 5382 return 0;
4567 } 5383 }
4568 5384
4569 /* Baseline must be a value between 0 and 100 (a percentage). */
4570 if (kw[XBM_ASCENT].count
4571 && XFASTINT (kw[XBM_ASCENT].value) > 100)
4572 return 0;
4573
4574 return 1; 5385 return 1;
4575 } 5386 }
4576 5387
4577 5388
4578 /* Scan a bitmap file. FP is the stream to read from. Value is 5389 /* Scan a bitmap file. FP is the stream to read from. Value is
4580 single-character token, or 0 at end of file. If scanning an 5391 single-character token, or 0 at end of file. If scanning an
4581 identifier, store the lexeme of the identifier in SVAL. If 5392 identifier, store the lexeme of the identifier in SVAL. If
4582 scanning a number, store its value in *IVAL. */ 5393 scanning a number, store its value in *IVAL. */
4583 5394
4584 static int 5395 static int
4585 xbm_scan (fp, sval, ival) 5396 xbm_scan (s, end, sval, ival)
4586 FILE *fp; 5397 char **s, *end;
4587 char *sval; 5398 char *sval;
4588 int *ival; 5399 int *ival;
4589 { 5400 {
4590 int c; 5401 int c;
4591 5402
5403 loop:
5404
4592 /* Skip white space. */ 5405 /* Skip white space. */
4593 while ((c = fgetc (fp)) != EOF && isspace (c)) 5406 while (*s < end && (c = *(*s)++, isspace (c)))
4594 ; 5407 ;
4595 5408
4596 if (c == EOF) 5409 if (*s >= end)
4597 c = 0; 5410 c = 0;
4598 else if (isdigit (c)) 5411 else if (isdigit (c))
4599 { 5412 {
4600 int value = 0, digit; 5413 int value = 0, digit;
4601 5414
4602 if (c == '0') 5415 if (c == '0' && *s < end)
4603 { 5416 {
4604 c = fgetc (fp); 5417 c = *(*s)++;
4605 if (c == 'x' || c == 'X') 5418 if (c == 'x' || c == 'X')
4606 { 5419 {
4607 while ((c = fgetc (fp)) != EOF) 5420 while (*s < end)
4608 { 5421 {
5422 c = *(*s)++;
4609 if (isdigit (c)) 5423 if (isdigit (c))
4610 digit = c - '0'; 5424 digit = c - '0';
4611 else if (c >= 'a' && c <= 'f') 5425 else if (c >= 'a' && c <= 'f')
4612 digit = c - 'a' + 10; 5426 digit = c - 'a' + 10;
4613 else if (c >= 'A' && c <= 'F') 5427 else if (c >= 'A' && c <= 'F')
4618 } 5432 }
4619 } 5433 }
4620 else if (isdigit (c)) 5434 else if (isdigit (c))
4621 { 5435 {
4622 value = c - '0'; 5436 value = c - '0';
4623 while ((c = fgetc (fp)) != EOF 5437 while (*s < end
4624 && isdigit (c)) 5438 && (c = *(*s)++, isdigit (c)))
4625 value = 8 * value + c - '0'; 5439 value = 8 * value + c - '0';
4626 } 5440 }
4627 } 5441 }
4628 else 5442 else
4629 { 5443 {
4630 value = c - '0'; 5444 value = c - '0';
4631 while ((c = fgetc (fp)) != EOF 5445 while (*s < end
4632 && isdigit (c)) 5446 && (c = *(*s)++, isdigit (c)))
4633 value = 10 * value + c - '0'; 5447 value = 10 * value + c - '0';
4634 } 5448 }
4635 5449
4636 if (c != EOF) 5450 if (*s < end)
4637 ungetc (c, fp); 5451 *s = *s - 1;
4638 *ival = value; 5452 *ival = value;
4639 c = XBM_TK_NUMBER; 5453 c = XBM_TK_NUMBER;
4640 } 5454 }
4641 else if (isalpha (c) || c == '_') 5455 else if (isalpha (c) || c == '_')
4642 { 5456 {
4643 *sval++ = c; 5457 *sval++ = c;
4644 while ((c = fgetc (fp)) != EOF 5458 while (*s < end
4645 && (isalnum (c) || c == '_')) 5459 && (c = *(*s)++, (isalnum (c) || c == '_')))
4646 *sval++ = c; 5460 *sval++ = c;
4647 *sval = 0; 5461 *sval = 0;
4648 if (c != EOF) 5462 if (*s < end)
4649 ungetc (c, fp); 5463 *s = *s - 1;
4650 c = XBM_TK_IDENT; 5464 c = XBM_TK_IDENT;
4651 } 5465 }
5466 else if (c == '/' && **s == '*')
5467 {
5468 /* C-style comment. */
5469 ++*s;
5470 while (**s && (**s != '*' || *(*s + 1) != '/'))
5471 ++*s;
5472 if (**s)
5473 {
5474 *s += 2;
5475 goto loop;
5476 }
5477 }
4652 5478
4653 return c; 5479 return c;
4654 } 5480 }
4655 5481
4656 5482
4657 /* Replacement for XReadBitmapFileData which isn't available under old 5483 /* Replacement for XReadBitmapFileData which isn't available under old
4658 X versions. FILE is the name of the bitmap file to read. Set 5484 X versions. CONTENTS is a pointer to a buffer to parse; END is the
4659 *WIDTH and *HEIGHT to the width and height of the image. Return in 5485 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
4660 *DATA the bitmap data allocated with xmalloc. Value is non-zero if 5486 the image. Return in *DATA the bitmap data allocated with xmalloc.
4661 successful. */ 5487 Value is non-zero if successful. DATA null means just test if
5488 CONTENTS looks like an in-memory XBM file. */
4662 5489
4663 static int 5490 static int
4664 xbm_read_bitmap_file_data (file, width, height, data) 5491 xbm_read_bitmap_data (contents, end, width, height, data)
4665 char *file; 5492 char *contents, *end;
4666 int *width, *height; 5493 int *width, *height;
4667 unsigned char **data; 5494 unsigned char **data;
4668 { 5495 {
4669 FILE *fp; 5496 char *s = contents;
4670 char buffer[BUFSIZ]; 5497 char buffer[BUFSIZ];
4671 int padding_p = 0; 5498 int padding_p = 0;
4672 int v10 = 0; 5499 int v10 = 0;
4673 int bytes_per_line, i, nbytes; 5500 int bytes_per_line, i, nbytes;
4674 unsigned char *p; 5501 unsigned char *p;
4675 int value; 5502 int value;
4676 int LA1; 5503 int LA1;
4677 5504
4678 #define match() \ 5505 #define match() \
4679 LA1 = xbm_scan (fp, buffer, &value) 5506 LA1 = xbm_scan (&s, end, buffer, &value)
4680 5507
4681 #define expect(TOKEN) \ 5508 #define expect(TOKEN) \
4682 if (LA1 != (TOKEN)) \ 5509 if (LA1 != (TOKEN)) \
4683 goto failure; \ 5510 goto failure; \
4684 else \ 5511 else \
4688 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \ 5515 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
4689 match (); \ 5516 match (); \
4690 else \ 5517 else \
4691 goto failure 5518 goto failure
4692 5519
4693 fp = fopen (file, "r");
4694 if (fp == NULL)
4695 return 0;
4696
4697 *width = *height = -1; 5520 *width = *height = -1;
4698 *data = NULL; 5521 if (data)
4699 LA1 = xbm_scan (fp, buffer, &value); 5522 *data = NULL;
5523 LA1 = xbm_scan (&s, end, buffer, &value);
4700 5524
4701 /* Parse defines for width, height and hot-spots. */ 5525 /* Parse defines for width, height and hot-spots. */
4702 while (LA1 == '#') 5526 while (LA1 == '#')
4703 { 5527 {
4704 match (); 5528 match ();
4717 expect (XBM_TK_NUMBER); 5541 expect (XBM_TK_NUMBER);
4718 } 5542 }
4719 5543
4720 if (*width < 0 || *height < 0) 5544 if (*width < 0 || *height < 0)
4721 goto failure; 5545 goto failure;
5546 else if (data == NULL)
5547 goto success;
4722 5548
4723 /* Parse bits. Must start with `static'. */ 5549 /* Parse bits. Must start with `static'. */
4724 expect_ident ("static"); 5550 expect_ident ("static");
4725 if (LA1 == XBM_TK_IDENT) 5551 if (LA1 == XBM_TK_IDENT)
4726 { 5552 {
4754 nbytes = bytes_per_line * *height; 5580 nbytes = bytes_per_line * *height;
4755 p = *data = (char *) xmalloc (nbytes); 5581 p = *data = (char *) xmalloc (nbytes);
4756 5582
4757 if (v10) 5583 if (v10)
4758 { 5584 {
4759
4760 for (i = 0; i < nbytes; i += 2) 5585 for (i = 0; i < nbytes; i += 2)
4761 { 5586 {
4762 int val = value; 5587 int val = value;
4763 expect (XBM_TK_NUMBER); 5588 expect (XBM_TK_NUMBER);
4764 5589
4786 else 5611 else
4787 goto failure; 5612 goto failure;
4788 } 5613 }
4789 } 5614 }
4790 5615
4791 fclose (fp); 5616 success:
4792 return 1; 5617 return 1;
4793 5618
4794 failure: 5619 failure:
4795 5620
4796 fclose (fp); 5621 if (data && *data)
4797 if (*data)
4798 { 5622 {
4799 xfree (*data); 5623 xfree (*data);
4800 *data = NULL; 5624 *data = NULL;
4801 } 5625 }
4802 return 0; 5626 return 0;
4805 #undef expect 5629 #undef expect
4806 #undef expect_ident 5630 #undef expect_ident
4807 } 5631 }
4808 5632
4809 5633
4810 /* Load XBM image IMG which will be displayed on frame F from file 5634 /* Load XBM image IMG which will be displayed on frame F from buffer
4811 SPECIFIED_FILE. Value is non-zero if successful. */ 5635 CONTENTS. END is the end of the buffer. Value is non-zero if
5636 successful. */
4812 5637
4813 static int 5638 static int
4814 xbm_load_image_from_file (f, img, specified_file) 5639 xbm_load_image (f, img, contents, end)
4815 struct frame *f; 5640 struct frame *f;
4816 struct image *img; 5641 struct image *img;
4817 Lisp_Object specified_file; 5642 char *contents, *end;
4818 { 5643 {
4819 int rc; 5644 int rc;
4820 unsigned char *data; 5645 unsigned char *data;
4821 int success_p = 0; 5646 int success_p = 0;
4822 Lisp_Object file; 5647
4823 struct gcpro gcpro1; 5648 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
4824
4825 xassert (STRINGP (specified_file));
4826 file = Qnil;
4827 GCPRO1 (file);
4828
4829 file = x_find_image_file (specified_file);
4830 if (!STRINGP (file))
4831 {
4832 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4833 UNGCPRO;
4834 return 0;
4835 }
4836
4837 rc = xbm_read_bitmap_file_data (SDATA (file), &img->width,
4838 &img->height, &data);
4839 if (rc) 5649 if (rc)
4840 { 5650 {
4841 int depth = one_mac_display_info.n_cbits; 5651 int depth = one_mac_display_info.n_planes;
4842 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); 5652 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
4843 unsigned long background = FRAME_BACKGROUND_PIXEL (f); 5653 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
4844 Lisp_Object value; 5654 Lisp_Object value;
4845 5655
4846 xassert (img->width > 0 && img->height > 0); 5656 xassert (img->width > 0 && img->height > 0);
4847 5657
4848 /* Get foreground and background colors, maybe allocate colors. */ 5658 /* Get foreground and background colors, maybe allocate colors. */
4849 value = image_spec_value (img->spec, QCforeground, NULL); 5659 value = image_spec_value (img->spec, QCforeground, NULL);
4850 if (!NILP (value)) 5660 if (!NILP (value))
4851 foreground = x_alloc_image_color (f, img, value, foreground); 5661 foreground = x_alloc_image_color (f, img, value, foreground);
4852
4853 value = image_spec_value (img->spec, QCbackground, NULL); 5662 value = image_spec_value (img->spec, QCbackground, NULL);
4854 if (!NILP (value)) 5663 if (!NILP (value))
4855 background = x_alloc_image_color (f, img, value, background); 5664 {
4856 5665 background = x_alloc_image_color (f, img, value, background);
4857 #if 0 /* MAC_TODO : Port image display to Mac */ 5666 img->background = background;
4858 BLOCK_INPUT; 5667 img->background_valid = 1;
5668 }
5669
4859 img->pixmap 5670 img->pixmap
4860 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f), 5671 = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
4861 FRAME_W32_WINDOW (f), 5672 FRAME_MAC_WINDOW (f),
4862 data, 5673 data,
4863 img->width, img->height, 5674 img->width, img->height,
4864 foreground, background, 5675 foreground, background,
4865 depth); 5676 depth);
4866 xfree (data); 5677 xfree (data);
4867 5678
4868 if (img->pixmap == 0) 5679 if (img->pixmap == 0)
4869 { 5680 {
4870 x_clear_image (f, img); 5681 x_clear_image (f, img);
4871 image_error ("Unable to create X pixmap for `%s'", file, Qnil); 5682 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
4872 } 5683 }
4873 else 5684 else
4874 success_p = 1; 5685 success_p = 1;
4875
4876 UNBLOCK_INPUT;
4877 #endif /* MAC_TODO */
4878 } 5686 }
4879 else 5687 else
4880 image_error ("Error loading XBM image `%s'", img->spec, Qnil); 5688 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
4881 5689
4882 UNGCPRO;
4883 return success_p; 5690 return success_p;
5691 }
5692
5693
5694 /* Value is non-zero if DATA looks like an in-memory XBM file. */
5695
5696 static int
5697 xbm_file_p (data)
5698 Lisp_Object data;
5699 {
5700 int w, h;
5701 return (STRINGP (data)
5702 && xbm_read_bitmap_data (SDATA (data),
5703 (SDATA (data)
5704 + SBYTES (data)),
5705 &w, &h, NULL));
4884 } 5706 }
4885 5707
4886 5708
4887 /* Fill image IMG which is used on frame F with pixmap data. Value is 5709 /* Fill image IMG which is used on frame F with pixmap data. Value is
4888 non-zero if successful. */ 5710 non-zero if successful. */
4898 xassert (xbm_image_p (img->spec)); 5720 xassert (xbm_image_p (img->spec));
4899 5721
4900 /* If IMG->spec specifies a file name, create a non-file spec from it. */ 5722 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4901 file_name = image_spec_value (img->spec, QCfile, NULL); 5723 file_name = image_spec_value (img->spec, QCfile, NULL);
4902 if (STRINGP (file_name)) 5724 if (STRINGP (file_name))
4903 success_p = xbm_load_image_from_file (f, img, file_name); 5725 {
5726 Lisp_Object file;
5727 char *contents;
5728 int size;
5729 struct gcpro gcpro1;
5730
5731 file = x_find_image_file (file_name);
5732 GCPRO1 (file);
5733 if (!STRINGP (file))
5734 {
5735 image_error ("Cannot find image file `%s'", file_name, Qnil);
5736 UNGCPRO;
5737 return 0;
5738 }
5739
5740 contents = slurp_file (SDATA (file), &size);
5741 if (contents == NULL)
5742 {
5743 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
5744 UNGCPRO;
5745 return 0;
5746 }
5747
5748 success_p = xbm_load_image (f, img, contents, contents + size);
5749 UNGCPRO;
5750 }
4904 else 5751 else
4905 { 5752 {
4906 struct image_keyword fmt[XBM_LAST]; 5753 struct image_keyword fmt[XBM_LAST];
4907 Lisp_Object data; 5754 Lisp_Object data;
4908 int depth; 5755 int depth;
4909 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); 5756 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
4910 unsigned long background = FRAME_BACKGROUND_PIXEL (f); 5757 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
4911 char *bits; 5758 char *bits;
4912 int parsed_p; 5759 int parsed_p;
4913 5760 int in_memory_file_p = 0;
4914 /* Parse the list specification. */ 5761
5762 /* See if data looks like an in-memory XBM file. */
5763 data = image_spec_value (img->spec, QCdata, NULL);
5764 in_memory_file_p = xbm_file_p (data);
5765
5766 /* Parse the image specification. */
4915 bcopy (xbm_format, fmt, sizeof fmt); 5767 bcopy (xbm_format, fmt, sizeof fmt);
4916 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm); 5768 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
4917 xassert (parsed_p); 5769 xassert (parsed_p);
4918 5770
4919 /* Get specified width, and height. */ 5771 /* Get specified width, and height. */
4920 img->width = XFASTINT (fmt[XBM_WIDTH].value); 5772 if (!in_memory_file_p)
4921 img->height = XFASTINT (fmt[XBM_HEIGHT].value); 5773 {
4922 xassert (img->width > 0 && img->height > 0); 5774 img->width = XFASTINT (fmt[XBM_WIDTH].value);
4923 5775 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
4924 BLOCK_INPUT; 5776 xassert (img->width > 0 && img->height > 0);
4925 5777 }
4926 if (fmt[XBM_ASCENT].count)
4927 img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
4928 5778
4929 /* Get foreground and background colors, maybe allocate colors. */ 5779 /* Get foreground and background colors, maybe allocate colors. */
4930 if (fmt[XBM_FOREGROUND].count) 5780 if (fmt[XBM_FOREGROUND].count
5781 && STRINGP (fmt[XBM_FOREGROUND].value))
4931 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value, 5782 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
4932 foreground); 5783 foreground);
4933 if (fmt[XBM_BACKGROUND].count) 5784 if (fmt[XBM_BACKGROUND].count
5785 && STRINGP (fmt[XBM_BACKGROUND].value))
4934 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value, 5786 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
4935 background); 5787 background);
4936 5788
4937 /* Set bits to the bitmap image data. */ 5789 if (in_memory_file_p)
4938 data = fmt[XBM_DATA].value; 5790 success_p = xbm_load_image (f, img, SDATA (data),
4939 if (VECTORP (data)) 5791 (SDATA (data)
5792 + SBYTES (data)));
5793 else
4940 { 5794 {
4941 int i; 5795 if (VECTORP (data))
4942 char *p;
4943 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
4944
4945 p = bits = (char *) alloca (nbytes * img->height);
4946 for (i = 0; i < img->height; ++i, p += nbytes)
4947 { 5796 {
4948 Lisp_Object line = XVECTOR (data)->contents[i]; 5797 int i;
4949 if (STRINGP (line)) 5798 char *p;
4950 bcopy (SDATA (line), p, nbytes); 5799 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
4951 else 5800
4952 bcopy (XBOOL_VECTOR (line)->data, p, nbytes); 5801 p = bits = (char *) alloca (nbytes * img->height);
5802 for (i = 0; i < img->height; ++i, p += nbytes)
5803 {
5804 Lisp_Object line = XVECTOR (data)->contents[i];
5805 if (STRINGP (line))
5806 bcopy (SDATA (line), p, nbytes);
5807 else
5808 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
5809 }
5810 }
5811 else if (STRINGP (data))
5812 bits = SDATA (data);
5813 else
5814 bits = XBOOL_VECTOR (data)->data;
5815
5816 /* Create the pixmap. */
5817 depth = one_mac_display_info.n_planes;
5818 img->pixmap
5819 = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
5820 FRAME_MAC_WINDOW (f),
5821 bits,
5822 img->width, img->height,
5823 foreground, background,
5824 depth);
5825 if (img->pixmap)
5826 success_p = 1;
5827 else
5828 {
5829 image_error ("Unable to create pixmap for XBM image `%s'",
5830 img->spec, Qnil);
5831 x_clear_image (f, img);
4953 } 5832 }
4954 } 5833 }
4955 else if (STRINGP (data))
4956 bits = SDATA (data);
4957 else
4958 bits = XBOOL_VECTOR (data)->data;
4959
4960 #if 0 /* MAC_TODO : port Mac display code */
4961 /* Create the pixmap. */
4962 depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
4963 img->pixmap
4964 = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
4965 FRAME_W32_WINDOW (f),
4966 bits,
4967 img->width, img->height,
4968 foreground, background,
4969 depth);
4970 #endif /* MAC_TODO */
4971
4972 if (img->pixmap)
4973 success_p = 1;
4974 else
4975 {
4976 image_error ("Unable to create pixmap for XBM image `%s'",
4977 img->spec, Qnil);
4978 x_clear_image (f, img);
4979 }
4980
4981 UNBLOCK_INPUT;
4982 } 5834 }
4983 5835
4984 return success_p; 5836 return success_p;
4985 } 5837 }
4986 5838
5012 XPM_ASCENT, 5864 XPM_ASCENT,
5013 XPM_MARGIN, 5865 XPM_MARGIN,
5014 XPM_RELIEF, 5866 XPM_RELIEF,
5015 XPM_ALGORITHM, 5867 XPM_ALGORITHM,
5016 XPM_HEURISTIC_MASK, 5868 XPM_HEURISTIC_MASK,
5869 XPM_MASK,
5017 XPM_COLOR_SYMBOLS, 5870 XPM_COLOR_SYMBOLS,
5871 XPM_BACKGROUND,
5018 XPM_LAST 5872 XPM_LAST
5019 }; 5873 };
5020 5874
5021 /* Vector of image_keyword structures describing the format 5875 /* Vector of image_keyword structures describing the format
5022 of valid XPM image specifications. */ 5876 of valid XPM image specifications. */
5024 static struct image_keyword xpm_format[XPM_LAST] = 5878 static struct image_keyword xpm_format[XPM_LAST] =
5025 { 5879 {
5026 {":type", IMAGE_SYMBOL_VALUE, 1}, 5880 {":type", IMAGE_SYMBOL_VALUE, 1},
5027 {":file", IMAGE_STRING_VALUE, 0}, 5881 {":file", IMAGE_STRING_VALUE, 0},
5028 {":data", IMAGE_STRING_VALUE, 0}, 5882 {":data", IMAGE_STRING_VALUE, 0},
5029 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 5883 {":ascent", IMAGE_ASCENT_VALUE, 0},
5030 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 5884 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5031 {":relief", IMAGE_INTEGER_VALUE, 0}, 5885 {":relief", IMAGE_INTEGER_VALUE, 0},
5032 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 5886 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5033 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 5887 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5034 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 5888 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5889 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5890 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5035 }; 5891 };
5036 5892
5037 /* Structure describing the image type XBM. */ 5893 /* Structure describing the image type XBM. */
5038 5894
5039 static struct image_type xpm_type = 5895 static struct image_type xpm_type =
5080 /* Either `:file' or `:data' must be present. */ 5936 /* Either `:file' or `:data' must be present. */
5081 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1 5937 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
5082 /* Either no `:color-symbols' or it's a list of conses 5938 /* Either no `:color-symbols' or it's a list of conses
5083 whose car and cdr are strings. */ 5939 whose car and cdr are strings. */
5084 && (fmt[XPM_COLOR_SYMBOLS].count == 0 5940 && (fmt[XPM_COLOR_SYMBOLS].count == 0
5085 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)) 5941 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
5086 && (fmt[XPM_ASCENT].count == 0
5087 || XFASTINT (fmt[XPM_ASCENT].value) < 100));
5088 } 5942 }
5089 5943
5090 5944
5091 /* Load image IMG which will be displayed on frame F. Value is 5945 /* Load image IMG which will be displayed on frame F. Value is
5092 non-zero if successful. */ 5946 non-zero if successful. */
5094 static int 5948 static int
5095 xpm_load (f, img) 5949 xpm_load (f, img)
5096 struct frame *f; 5950 struct frame *f;
5097 struct image *img; 5951 struct image *img;
5098 { 5952 {
5099 int rc, i; 5953 int rc;
5100 XpmAttributes attrs; 5954 XpmAttributes attrs;
5101 Lisp_Object specified_file, color_symbols; 5955 Lisp_Object specified_file, color_symbols;
5102 5956
5103 /* Configure the XPM lib. Use the visual of frame F. Allocate 5957 /* Configure the XPM lib. Use the visual of frame F. Allocate
5104 close colors. Return colors allocated. */ 5958 close colors. Return colors allocated. */
5109 attrs.valuemask |= XpmColormap; 5963 attrs.valuemask |= XpmColormap;
5110 attrs.valuemask |= XpmReturnAllocPixels; 5964 attrs.valuemask |= XpmReturnAllocPixels;
5111 #ifdef XpmAllocCloseColors 5965 #ifdef XpmAllocCloseColors
5112 attrs.alloc_close_colors = 1; 5966 attrs.alloc_close_colors = 1;
5113 attrs.valuemask |= XpmAllocCloseColors; 5967 attrs.valuemask |= XpmAllocCloseColors;
5114 #else 5968 #else /* not XpmAllocCloseColors */
5115 attrs.closeness = 600; 5969 attrs.closeness = 600;
5116 attrs.valuemask |= XpmCloseness; 5970 attrs.valuemask |= XpmCloseness;
5117 #endif 5971 #endif /* not XpmAllocCloseColors */
5118 5972
5119 /* If image specification contains symbolic color definitions, add 5973 /* If image specification contains symbolic color definitions, add
5120 these to `attrs'. */ 5974 these to `attrs'. */
5121 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL); 5975 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
5122 if (CONSP (color_symbols)) 5976 if (CONSP (color_symbols))
5152 } 6006 }
5153 } 6007 }
5154 6008
5155 /* Create a pixmap for the image, either from a file, or from a 6009 /* Create a pixmap for the image, either from a file, or from a
5156 string buffer containing data in the same format as an XPM file. */ 6010 string buffer containing data in the same format as an XPM file. */
5157 BLOCK_INPUT; 6011
5158 specified_file = image_spec_value (img->spec, QCfile, NULL); 6012 specified_file = image_spec_value (img->spec, QCfile, NULL);
5159 if (STRINGP (specified_file)) 6013 if (STRINGP (specified_file))
5160 { 6014 {
5161 Lisp_Object file = x_find_image_file (specified_file); 6015 Lisp_Object file = x_find_image_file (specified_file);
5162 if (!STRINGP (file)) 6016 if (!STRINGP (file))
5163 { 6017 {
5164 image_error ("Cannot find image file `%s'", specified_file, Qnil); 6018 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5165 UNBLOCK_INPUT;
5166 return 0; 6019 return 0;
5167 } 6020 }
5168 6021
5169 rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f), 6022 rc = XpmReadFileToPixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5170 SDATA (file), &img->pixmap, &img->mask, 6023 SDATA (file), &img->pixmap, &img->mask,
5171 &attrs); 6024 &attrs);
5172 } 6025 }
5173 else 6026 else
5174 { 6027 {
5175 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL); 6028 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
5176 rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f), 6029 rc = XpmCreatePixmapFromBuffer (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5177 SDATA (buffer), 6030 SDATA (buffer),
5178 &img->pixmap, &img->mask, 6031 &img->pixmap, &img->mask,
5179 &attrs); 6032 &attrs);
5180 } 6033 }
5181 UNBLOCK_INPUT;
5182 6034
5183 if (rc == XpmSuccess) 6035 if (rc == XpmSuccess)
5184 { 6036 {
5185 /* Remember allocated colors. */ 6037 int i;
6038
5186 img->ncolors = attrs.nalloc_pixels; 6039 img->ncolors = attrs.nalloc_pixels;
5187 img->colors = (unsigned long *) xmalloc (img->ncolors 6040 img->colors = (unsigned long *) xmalloc (img->ncolors
5188 * sizeof *img->colors); 6041 * sizeof *img->colors);
5189 for (i = 0; i < attrs.nalloc_pixels; ++i) 6042 for (i = 0; i < attrs.nalloc_pixels; ++i)
5190 img->colors[i] = attrs.alloc_pixels[i]; 6043 img->colors[i] = attrs.alloc_pixels[i];
5192 img->width = attrs.width; 6045 img->width = attrs.width;
5193 img->height = attrs.height; 6046 img->height = attrs.height;
5194 xassert (img->width > 0 && img->height > 0); 6047 xassert (img->width > 0 && img->height > 0);
5195 6048
5196 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */ 6049 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
5197 BLOCK_INPUT;
5198 XpmFreeAttributes (&attrs); 6050 XpmFreeAttributes (&attrs);
5199 UNBLOCK_INPUT;
5200 } 6051 }
5201 else 6052 else
5202 { 6053 {
5203 switch (rc) 6054 switch (rc)
5204 { 6055 {
5259 struct ct_color **ct_table; 6110 struct ct_color **ct_table;
5260 6111
5261 /* Number of entries in the color table. */ 6112 /* Number of entries in the color table. */
5262 6113
5263 int ct_colors_allocated; 6114 int ct_colors_allocated;
5264
5265 /* Function prototypes. */
5266
5267 static void init_color_table P_ ((void));
5268 static void free_color_table P_ ((void));
5269 static unsigned long *colors_in_color_table P_ ((int *n));
5270 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
5271 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
5272
5273 6115
5274 /* Initialize the color table. */ 6116 /* Initialize the color table. */
5275 6117
5276 static void 6118 static void
5277 init_color_table () 6119 init_color_table ()
5420 } 6262 }
5421 6263
5422 return colors; 6264 return colors;
5423 } 6265 }
5424 6266
6267 #else
6268 static unsigned long
6269 lookup_rgb_color (f, r, g, b)
6270 struct frame *f;
6271 int r, g, b;
6272 {
6273 unsigned long pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
6274
6275 gamma_correct (f, &pixel);
6276 return pixel;
6277 }
5425 #endif /* MAC_TODO */ 6278 #endif /* MAC_TODO */
5426 6279
5427 6280
5428 /*********************************************************************** 6281 /***********************************************************************
5429 Algorithms 6282 Algorithms
5430 ***********************************************************************/ 6283 ***********************************************************************/
5431 6284
5432 #if 0 /* MAC_TODO : Mac versions of low level algorithms */ 6285 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
5433 static void x_laplace_write_row P_ ((struct frame *, long *, 6286 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
5434 int, XImage *, int)); 6287 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
5435 static void x_laplace_read_row P_ ((struct frame *, Colormap, 6288
5436 XColor *, int, XImage *, int)); 6289 /* Non-zero means draw a cross on images having `:conversion
5437 6290 disabled'. */
5438 6291
5439 /* Fill COLORS with RGB colors from row Y of image XIMG. F is the 6292 int cross_disabled_images;
5440 frame we operate on, CMAP is the color-map in effect, and WIDTH is 6293
5441 the width of one row in the image. */ 6294 /* Edge detection matrices for different edge-detection
6295 strategies. */
6296
6297 static int emboss_matrix[9] = {
6298 /* x - 1 x x + 1 */
6299 2, -1, 0, /* y - 1 */
6300 -1, 0, 1, /* y */
6301 0, 1, -2 /* y + 1 */
6302 };
6303
6304 static int laplace_matrix[9] = {
6305 /* x - 1 x x + 1 */
6306 1, 0, 0, /* y - 1 */
6307 0, 0, 0, /* y */
6308 0, 0, -1 /* y + 1 */
6309 };
6310
6311 /* Value is the intensity of the color whose red/green/blue values
6312 are R, G, and B. */
6313
6314 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
6315
6316
6317 /* On frame F, return an array of XColor structures describing image
6318 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
6319 non-zero means also fill the red/green/blue members of the XColor
6320 structures. Value is a pointer to the array of XColors structures,
6321 allocated with xmalloc; it must be freed by the caller. */
6322
6323 static XColor *
6324 x_to_xcolors (f, img, rgb_p)
6325 struct frame *f;
6326 struct image *img;
6327 int rgb_p;
6328 {
6329 int x, y;
6330 XColor *colors, *p;
6331 XImagePtr ximg;
6332
6333 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
6334
6335 /* Get the X image IMG->pixmap. */
6336 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
6337 0, 0, img->width, img->height, ~0, ZPixmap);
6338
6339 /* Fill the `pixel' members of the XColor array. I wished there
6340 were an easy and portable way to circumvent XGetPixel. */
6341 p = colors;
6342 for (y = 0; y < img->height; ++y)
6343 {
6344 XColor *row = p;
6345
6346 for (x = 0; x < img->width; ++x, ++p)
6347 {
6348 p->pixel = XGetPixel (ximg, x, y);
6349
6350 if (rgb_p)
6351 {
6352 p->red = RED16_FROM_ULONG (p->pixel);
6353 p->green = GREEN16_FROM_ULONG (p->pixel);
6354 p->blue = BLUE16_FROM_ULONG (p->pixel);
6355 }
6356 }
6357 }
6358
6359 XDestroyImage (ximg);
6360 return colors;
6361 }
6362
6363
6364 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
6365 RGB members are set. F is the frame on which this all happens.
6366 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5442 6367
5443 static void 6368 static void
5444 x_laplace_read_row (f, cmap, colors, width, ximg, y) 6369 x_from_xcolors (f, img, colors)
5445 struct frame *f; 6370 struct frame *f;
5446 Colormap cmap; 6371 struct image *img;
5447 XColor *colors; 6372 XColor *colors;
5448 int width; 6373 {
5449 XImage *ximg; 6374 int x, y;
5450 int y; 6375 XImagePtr oimg;
5451 { 6376 Pixmap pixmap;
5452 int x; 6377 XColor *p;
5453 6378
5454 for (x = 0; x < width; ++x) 6379 #if 0 /* TODO: color tables. */
5455 colors[x].pixel = XGetPixel (ximg, x, y); 6380 init_color_table ();
5456 6381 #endif
5457 XQueryColors (NULL, cmap, colors, width); 6382
5458 } 6383 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5459 6384 &oimg, &pixmap);
5460 6385 p = colors;
5461 /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs 6386 for (y = 0; y < img->height; ++y)
5462 containing the pixel colors to write. F is the frame we are 6387 for (x = 0; x < img->width; ++x, ++p)
5463 working on. */ 6388 {
6389 unsigned long pixel;
6390 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
6391 XPutPixel (oimg, x, y, pixel);
6392 }
6393
6394 xfree (colors);
6395 x_clear_image_1 (f, img, 1, 0, 1);
6396
6397 x_put_x_image (f, oimg, pixmap, img->width, img->height);
6398 x_destroy_x_image (oimg);
6399 img->pixmap = pixmap;
6400 #if 0 /* TODO: color tables. */
6401 img->colors = colors_in_color_table (&img->ncolors);
6402 free_color_table ();
6403 #endif
6404 }
6405
6406
6407 /* On frame F, perform edge-detection on image IMG.
6408
6409 MATRIX is a nine-element array specifying the transformation
6410 matrix. See emboss_matrix for an example.
6411
6412 COLOR_ADJUST is a color adjustment added to each pixel of the
6413 outgoing image. */
5464 6414
5465 static void 6415 static void
5466 x_laplace_write_row (f, pixels, width, ximg, y) 6416 x_detect_edges (f, img, matrix, color_adjust)
5467 struct frame *f; 6417 struct frame *f;
5468 long *pixels; 6418 struct image *img;
5469 int width; 6419 int matrix[9], color_adjust;
5470 XImage *ximg; 6420 {
5471 int y; 6421 XColor *colors = x_to_xcolors (f, img, 1);
5472 { 6422 XColor *new, *p;
5473 int x; 6423 int x, y, i, sum;
5474 6424
5475 for (x = 0; x < width; ++x) 6425 for (i = sum = 0; i < 9; ++i)
5476 XPutPixel (ximg, x, y, pixels[x]); 6426 sum += abs (matrix[i]);
5477 } 6427
5478 #endif /* MAC_TODO */ 6428 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5479 6429
5480 /* Transform image IMG which is used on frame F with a Laplace 6430 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5481 edge-detection algorithm. The result is an image that can be used 6431
5482 to draw disabled buttons, for example. */ 6432 for (y = 0; y < img->height; ++y)
6433 {
6434 p = COLOR (new, 0, y);
6435 p->red = p->green = p->blue = 0xffff/2;
6436 p = COLOR (new, img->width - 1, y);
6437 p->red = p->green = p->blue = 0xffff/2;
6438 }
6439
6440 for (x = 1; x < img->width - 1; ++x)
6441 {
6442 p = COLOR (new, x, 0);
6443 p->red = p->green = p->blue = 0xffff/2;
6444 p = COLOR (new, x, img->height - 1);
6445 p->red = p->green = p->blue = 0xffff/2;
6446 }
6447
6448 for (y = 1; y < img->height - 1; ++y)
6449 {
6450 p = COLOR (new, 1, y);
6451
6452 for (x = 1; x < img->width - 1; ++x, ++p)
6453 {
6454 int r, g, b, y1, x1;
6455
6456 r = g = b = i = 0;
6457 for (y1 = y - 1; y1 < y + 2; ++y1)
6458 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
6459 if (matrix[i])
6460 {
6461 XColor *t = COLOR (colors, x1, y1);
6462 r += matrix[i] * t->red;
6463 g += matrix[i] * t->green;
6464 b += matrix[i] * t->blue;
6465 }
6466
6467 r = (r / sum + color_adjust) & 0xffff;
6468 g = (g / sum + color_adjust) & 0xffff;
6469 b = (b / sum + color_adjust) & 0xffff;
6470 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
6471 }
6472 }
6473
6474 xfree (colors);
6475 x_from_xcolors (f, img, new);
6476
6477 #undef COLOR
6478 }
6479
6480
6481 /* Perform the pre-defined `emboss' edge-detection on image IMG
6482 on frame F. */
6483
6484 static void
6485 x_emboss (f, img)
6486 struct frame *f;
6487 struct image *img;
6488 {
6489 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
6490 }
6491
6492
6493 /* Perform the pre-defined `laplace' edge-detection on image IMG
6494 on frame F. */
5483 6495
5484 static void 6496 static void
5485 x_laplace (f, img) 6497 x_laplace (f, img)
5486 struct frame *f; 6498 struct frame *f;
5487 struct image *img; 6499 struct image *img;
5488 { 6500 {
5489 #if 0 /* MAC_TODO : Mac version */ 6501 x_detect_edges (f, img, laplace_matrix, 45000);
5490 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f)); 6502 }
5491 XImage *ximg, *oimg; 6503
5492 XColor *in[3]; 6504
5493 long *out; 6505 /* Perform edge-detection on image IMG on frame F, with specified
5494 Pixmap pixmap; 6506 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5495 int x, y, i; 6507
5496 long pixel; 6508 MATRIX must be either
5497 int in_y, out_y, rc; 6509
5498 int mv2 = 45000; 6510 - a list of at least 9 numbers in row-major form
5499 6511 - a vector of at least 9 numbers
5500 BLOCK_INPUT; 6512
5501 6513 COLOR_ADJUST nil means use a default; otherwise it must be a
5502 /* Get the X image IMG->pixmap. */ 6514 number. */
5503 ximg = XGetImage (NULL, img->pixmap, 6515
5504 0, 0, img->width, img->height, ~0, ZPixmap); 6516 static void
5505 6517 x_edge_detection (f, img, matrix, color_adjust)
5506 /* Allocate 3 input rows, and one output row of colors. */ 6518 struct frame *f;
5507 for (i = 0; i < 3; ++i) 6519 struct image *img;
5508 in[i] = (XColor *) alloca (img->width * sizeof (XColor)); 6520 Lisp_Object matrix, color_adjust;
5509 out = (long *) alloca (img->width * sizeof (long)); 6521 {
5510 6522 int i = 0;
5511 /* Create an X image for output. */ 6523 int trans[9];
5512 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0, 6524
5513 &oimg, &pixmap); 6525 if (CONSP (matrix))
5514 6526 {
5515 /* Fill first two rows. */ 6527 for (i = 0;
5516 x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0); 6528 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5517 x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1); 6529 ++i, matrix = XCDR (matrix))
5518 in_y = 2; 6530 trans[i] = XFLOATINT (XCAR (matrix));
5519 6531 }
5520 /* Write first row, all zeros. */ 6532 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5521 init_color_table (); 6533 {
5522 pixel = lookup_rgb_color (f, 0, 0, 0); 6534 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5523 for (x = 0; x < img->width; ++x) 6535 trans[i] = XFLOATINT (AREF (matrix, i));
5524 out[x] = pixel; 6536 }
5525 x_laplace_write_row (f, out, img->width, oimg, 0); 6537
5526 out_y = 1; 6538 if (NILP (color_adjust))
5527 6539 color_adjust = make_number (0xffff / 2);
5528 for (y = 2; y < img->height; ++y) 6540
5529 { 6541 if (i == 9 && NUMBERP (color_adjust))
5530 int rowa = y % 3; 6542 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5531 int rowb = (y + 2) % 3; 6543 }
5532 6544
5533 x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++); 6545
5534 6546 /* Transform image IMG on frame F so that it looks disabled. */
5535 for (x = 0; x < img->width - 2; ++x) 6547
6548 static void
6549 x_disable_image (f, img)
6550 struct frame *f;
6551 struct image *img;
6552 {
6553 struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6554
6555 if (dpyinfo->n_planes >= 2)
6556 {
6557 /* Color (or grayscale). Convert to gray, and equalize. Just
6558 drawing such images with a stipple can look very odd, so
6559 we're using this method instead. */
6560 XColor *colors = x_to_xcolors (f, img, 1);
6561 XColor *p, *end;
6562 const int h = 15000;
6563 const int l = 30000;
6564
6565 for (p = colors, end = colors + img->width * img->height;
6566 p < end;
6567 ++p)
5536 { 6568 {
5537 int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red; 6569 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5538 int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green; 6570 int i2 = (0xffff - h - l) * i / 0xffff + l;
5539 int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue; 6571 p->red = p->green = p->blue = i2;
5540
5541 out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
5542 b & 0xffff);
5543 } 6572 }
5544 6573
5545 x_laplace_write_row (f, out, img->width, oimg, out_y++); 6574 x_from_xcolors (f, img, colors);
5546 } 6575 }
5547 6576
5548 /* Write last line, all zeros. */ 6577 /* Draw a cross over the disabled image, if we must or if we
5549 for (x = 0; x < img->width; ++x) 6578 should. */
5550 out[x] = pixel; 6579 if (dpyinfo->n_planes < 2 || cross_disabled_images)
5551 x_laplace_write_row (f, out, img->width, oimg, out_y); 6580 {
5552 6581 Display *dpy = FRAME_MAC_DISPLAY (f);
5553 /* Free the input image, and free resources of IMG. */ 6582 GC gc;
5554 XDestroyImage (ximg); 6583
5555 x_clear_image (f, img); 6584 gc = XCreateGC (dpy, NULL /*img->pixmap*/, 0, NULL);
5556 6585 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5557 /* Put the output image into pixmap, and destroy it. */ 6586 mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, 0,
5558 x_put_x_image (f, oimg, pixmap, img->width, img->height); 6587 img->width - 1, img->height - 1);
5559 x_destroy_x_image (oimg); 6588 mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, img->height - 1,
5560 6589 img->width - 1, 0);
5561 /* Remember new pixmap and colors in IMG. */ 6590 XFreeGC (dpy, gc);
5562 img->pixmap = pixmap; 6591
5563 img->colors = colors_in_color_table (&img->ncolors); 6592 if (img->mask)
5564 free_color_table (); 6593 {
5565 6594 gc = XCreateGC (dpy, NULL /*img->mask*/, 0, NULL);
5566 UNBLOCK_INPUT; 6595 XSetForeground (dpy, gc, PIX_MASK_DRAW (f));
5567 #endif /* MAC_TODO */ 6596 mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, 0,
5568 } 6597 img->width - 1, img->height - 1);
5569 6598 mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, img->height - 1,
5570 6599 img->width - 1, 0);
5571 /* Build a mask for image IMG which is used on frame F. FILE is the 6600 XFreeGC (dpy, gc);
5572 name of an image file, for error messages. HOW determines how to 6601 }
5573 determine the background color of IMG. If it is a list '(R G B)', 6602 }
6603 }
6604
6605
6606 /* Build a mask for image IMG which is used on frame F. FILE is the
6607 name of an image file, for error messages. HOW determines how to
6608 determine the background color of IMG. If it is a list '(R G B)',
5574 with R, G, and B being integers >= 0, take that as the color of the 6609 with R, G, and B being integers >= 0, take that as the color of the
5575 background. Otherwise, determine the background color of IMG 6610 background. Otherwise, determine the background color of IMG
5576 heuristically. Value is non-zero if successful. */ 6611 heuristically. Value is non-zero if successful. */
5577 6612
5578 static int 6613 static int
5579 x_build_heuristic_mask (f, img, how) 6614 x_build_heuristic_mask (f, img, how)
5580 struct frame *f; 6615 struct frame *f;
5581 struct image *img; 6616 struct image *img;
5582 Lisp_Object how; 6617 Lisp_Object how;
5583 { 6618 {
5584 #if 0 /* MAC_TODO : Mac version */ 6619 Display *dpy = FRAME_X_DISPLAY (f);
5585 Display *dpy = FRAME_W32_DISPLAY (f); 6620 XImagePtr ximg, mask_img;
5586 XImage *ximg, *mask_img; 6621 int x, y, rc, use_img_background;
5587 int x, y, rc, look_at_corners_p; 6622 unsigned long bg = 0;
5588 unsigned long bg; 6623
5589 6624 if (img->mask)
5590 BLOCK_INPUT; 6625 {
6626 XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
6627 img->mask = 0;
6628 img->background_transparent_valid = 0;
6629 }
5591 6630
5592 /* Create an image and pixmap serving as mask. */ 6631 /* Create an image and pixmap serving as mask. */
5593 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, 6632 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5594 &mask_img, &img->mask); 6633 &mask_img, &img->mask);
5595 if (!rc) 6634 if (!rc)
5596 { 6635 return 0;
5597 UNBLOCK_INPUT;
5598 return 0;
5599 }
5600 6636
5601 /* Get the X image of IMG->pixmap. */ 6637 /* Get the X image of IMG->pixmap. */
5602 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height, 6638 ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
5603 ~0, ZPixmap); 6639 ~0, ZPixmap);
5604 6640
5605 /* Determine the background color of ximg. If HOW is `(R G B)' 6641 /* Determine the background color of ximg. If HOW is `(R G B)'
5606 take that as color. Otherwise, try to determine the color 6642 take that as color. Otherwise, use the image's background color. */
5607 heuristically. */ 6643 use_img_background = 1;
5608 look_at_corners_p = 1;
5609 6644
5610 if (CONSP (how)) 6645 if (CONSP (how))
5611 { 6646 {
5612 int rgb[3], i = 0; 6647 int rgb[3], i;
5613 6648
5614 while (i < 3 6649 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5615 && CONSP (how)
5616 && NATNUMP (XCAR (how)))
5617 { 6650 {
5618 rgb[i] = XFASTINT (XCAR (how)) & 0xffff; 6651 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5619 how = XCDR (how); 6652 how = XCDR (how);
5620 } 6653 }
5621 6654
5622 if (i == 3 && NILP (how)) 6655 if (i == 3 && NILP (how))
5623 { 6656 {
5624 char color_name[30]; 6657 char color_name[30];
5625 XColor exact, color;
5626 Colormap cmap;
5627
5628 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]); 6658 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5629 6659 bg = x_alloc_image_color (f, img, build_string (color_name), 0);
5630 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f)); 6660 use_img_background = 0;
5631 if (XLookupColor (dpy, cmap, color_name, &exact, &color))
5632 {
5633 bg = color.pixel;
5634 look_at_corners_p = 0;
5635 }
5636 } 6661 }
5637 } 6662 }
5638 6663
5639 if (look_at_corners_p) 6664 if (use_img_background)
5640 { 6665 bg = four_corners_best (ximg, img->width, img->height);
5641 unsigned long corners[4];
5642 int i, best_count;
5643
5644 /* Get the colors at the corners of ximg. */
5645 corners[0] = XGetPixel (ximg, 0, 0);
5646 corners[1] = XGetPixel (ximg, img->width - 1, 0);
5647 corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
5648 corners[3] = XGetPixel (ximg, 0, img->height - 1);
5649
5650 /* Choose the most frequently found color as background. */
5651 for (i = best_count = 0; i < 4; ++i)
5652 {
5653 int j, n;
5654
5655 for (j = n = 0; j < 4; ++j)
5656 if (corners[i] == corners[j])
5657 ++n;
5658
5659 if (n > best_count)
5660 bg = corners[i], best_count = n;
5661 }
5662 }
5663 6666
5664 /* Set all bits in mask_img to 1 whose color in ximg is different 6667 /* Set all bits in mask_img to 1 whose color in ximg is different
5665 from the background color bg. */ 6668 from the background color bg. */
5666 for (y = 0; y < img->height; ++y) 6669 for (y = 0; y < img->height; ++y)
5667 for (x = 0; x < img->width; ++x) 6670 for (x = 0; x < img->width; ++x)
5668 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg); 6671 XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
6672
6673 /* Fill in the background_transparent field while we have the mask handy. */
6674 image_background_transparent (img, f, mask_img);
5669 6675
5670 /* Put mask_img into img->mask. */ 6676 /* Put mask_img into img->mask. */
5671 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 6677 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5672 x_destroy_x_image (mask_img); 6678 x_destroy_x_image (mask_img);
5673 XDestroyImage (ximg); 6679 XDestroyImage (ximg);
5674 6680
5675 UNBLOCK_INPUT;
5676 #endif /* MAC_TODO */
5677
5678 return 1; 6681 return 1;
5679 } 6682 }
5680 6683
5681 6684
5682 6685
5683 /*********************************************************************** 6686 /***********************************************************************
5684 PBM (mono, gray, color) 6687 PBM (mono, gray, color)
5685 ***********************************************************************/ 6688 ***********************************************************************/
5686 #ifdef HAVE_PBM
5687 6689
5688 static int pbm_image_p P_ ((Lisp_Object object)); 6690 static int pbm_image_p P_ ((Lisp_Object object));
5689 static int pbm_load P_ ((struct frame *f, struct image *img)); 6691 static int pbm_load P_ ((struct frame *f, struct image *img));
5690 static int pbm_scan_number P_ ((unsigned char **, unsigned char *)); 6692 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5691 6693
5703 PBM_ASCENT, 6705 PBM_ASCENT,
5704 PBM_MARGIN, 6706 PBM_MARGIN,
5705 PBM_RELIEF, 6707 PBM_RELIEF,
5706 PBM_ALGORITHM, 6708 PBM_ALGORITHM,
5707 PBM_HEURISTIC_MASK, 6709 PBM_HEURISTIC_MASK,
6710 PBM_MASK,
6711 PBM_FOREGROUND,
6712 PBM_BACKGROUND,
5708 PBM_LAST 6713 PBM_LAST
5709 }; 6714 };
5710 6715
5711 /* Vector of image_keyword structures describing the format 6716 /* Vector of image_keyword structures describing the format
5712 of valid user-defined image specifications. */ 6717 of valid user-defined image specifications. */
5714 static struct image_keyword pbm_format[PBM_LAST] = 6719 static struct image_keyword pbm_format[PBM_LAST] =
5715 { 6720 {
5716 {":type", IMAGE_SYMBOL_VALUE, 1}, 6721 {":type", IMAGE_SYMBOL_VALUE, 1},
5717 {":file", IMAGE_STRING_VALUE, 0}, 6722 {":file", IMAGE_STRING_VALUE, 0},
5718 {":data", IMAGE_STRING_VALUE, 0}, 6723 {":data", IMAGE_STRING_VALUE, 0},
5719 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 6724 {":ascent", IMAGE_ASCENT_VALUE, 0},
5720 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 6725 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5721 {":relief", IMAGE_INTEGER_VALUE, 0}, 6726 {":relief", IMAGE_INTEGER_VALUE, 0},
5722 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 6727 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5723 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 6728 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6729 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6730 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
6731 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5724 }; 6732 };
5725 6733
5726 /* Structure describing the image type `pbm'. */ 6734 /* Structure describing the image type `pbm'. */
5727 6735
5728 static struct image_type pbm_type = 6736 static struct image_type pbm_type =
5743 { 6751 {
5744 struct image_keyword fmt[PBM_LAST]; 6752 struct image_keyword fmt[PBM_LAST];
5745 6753
5746 bcopy (pbm_format, fmt, sizeof fmt); 6754 bcopy (pbm_format, fmt, sizeof fmt);
5747 6755
5748 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm) 6756 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5749 || (fmt[PBM_ASCENT].count
5750 && XFASTINT (fmt[PBM_ASCENT].value) > 100))
5751 return 0; 6757 return 0;
5752 6758
5753 /* Must specify either :data or :file. */ 6759 /* Must specify either :data or :file. */
5754 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1; 6760 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5755 } 6761 }
5761 6767
5762 static int 6768 static int
5763 pbm_scan_number (s, end) 6769 pbm_scan_number (s, end)
5764 unsigned char **s, *end; 6770 unsigned char **s, *end;
5765 { 6771 {
5766 int c, val = -1; 6772 int c = 0, val = -1;
5767 6773
5768 while (*s < end) 6774 while (*s < end)
5769 { 6775 {
5770 /* Skip white-space. */ 6776 /* Skip white-space. */
5771 while (*s < end && (c = *(*s)++, isspace (c))) 6777 while (*s < end && (c = *(*s)++, isspace (c)))
5791 6797
5792 return val; 6798 return val;
5793 } 6799 }
5794 6800
5795 6801
5796 /* Read FILE into memory. Value is a pointer to a buffer allocated
5797 with xmalloc holding FILE's contents. Value is null if an error
5798 occurred. *SIZE is set to the size of the file. */
5799
5800 static char *
5801 pbm_read_file (file, size)
5802 Lisp_Object file;
5803 int *size;
5804 {
5805 FILE *fp = NULL;
5806 char *buf = NULL;
5807 struct stat st;
5808
5809 if (stat (SDATA (file), &st) == 0
5810 && (fp = fopen (SDATA (file), "r")) != NULL
5811 && (buf = (char *) xmalloc (st.st_size),
5812 fread (buf, 1, st.st_size, fp) == st.st_size))
5813 {
5814 *size = st.st_size;
5815 fclose (fp);
5816 }
5817 else
5818 {
5819 if (fp)
5820 fclose (fp);
5821 if (buf)
5822 {
5823 xfree (buf);
5824 buf = NULL;
5825 }
5826 }
5827
5828 return buf;
5829 }
5830
5831
5832 /* Load PBM image IMG for use on frame F. */ 6802 /* Load PBM image IMG for use on frame F. */
5833 6803
5834 static int 6804 static int
5835 pbm_load (f, img) 6805 pbm_load (f, img)
5836 struct frame *f; 6806 struct frame *f;
5837 struct image *img; 6807 struct image *img;
5838 { 6808 {
5839 int raw_p, x, y; 6809 int raw_p, x, y;
5840 int width, height, max_color_idx = 0; 6810 int width, height, max_color_idx = 0;
5841 XImage *ximg; 6811 XImagePtr ximg;
5842 Lisp_Object file, specified_file; 6812 Lisp_Object file, specified_file;
5843 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; 6813 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5844 struct gcpro gcpro1; 6814 struct gcpro gcpro1;
5845 unsigned char *contents = NULL; 6815 unsigned char *contents = NULL;
5846 unsigned char *end, *p; 6816 unsigned char *end, *p;
5852 6822
5853 if (STRINGP (specified_file)) 6823 if (STRINGP (specified_file))
5854 { 6824 {
5855 file = x_find_image_file (specified_file); 6825 file = x_find_image_file (specified_file);
5856 if (!STRINGP (file)) 6826 if (!STRINGP (file))
5857 { 6827 {
5858 image_error ("Cannot find image file `%s'", specified_file, Qnil); 6828 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5859 UNGCPRO; 6829 UNGCPRO;
5860 return 0; 6830 return 0;
5861 } 6831 }
5862 6832
5863 contents = pbm_read_file (file, &size); 6833 contents = slurp_file (SDATA (file), &size);
5864 if (contents == NULL) 6834 if (contents == NULL)
5865 { 6835 {
5866 image_error ("Error reading `%s'", file, Qnil); 6836 image_error ("Error reading `%s'", file, Qnil);
5867 UNGCPRO; 6837 UNGCPRO;
5868 return 0; 6838 return 0;
5935 if (width < 0 6905 if (width < 0
5936 || height < 0 6906 || height < 0
5937 || (type != PBM_MONO && max_color_idx < 0)) 6907 || (type != PBM_MONO && max_color_idx < 0))
5938 goto error; 6908 goto error;
5939 6909
5940 BLOCK_INPUT;
5941 if (!x_create_x_image_and_pixmap (f, width, height, 0, 6910 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5942 &ximg, &img->pixmap)) 6911 &ximg, &img->pixmap))
5943 { 6912 goto error;
5944 UNBLOCK_INPUT; 6913
5945 goto error; 6914 #if 0 /* TODO: color tables. */
5946 }
5947
5948 /* Initialize the color hash table. */ 6915 /* Initialize the color hash table. */
5949 init_color_table (); 6916 init_color_table ();
6917 #endif
5950 6918
5951 if (type == PBM_MONO) 6919 if (type == PBM_MONO)
5952 { 6920 {
5953 int c = 0, g; 6921 int c = 0, g;
6922 struct image_keyword fmt[PBM_LAST];
6923 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
6924 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
6925
6926 /* Parse the image specification. */
6927 bcopy (pbm_format, fmt, sizeof fmt);
6928 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
6929
6930 /* Get foreground and background colors, maybe allocate colors. */
6931 if (fmt[PBM_FOREGROUND].count
6932 && STRINGP (fmt[PBM_FOREGROUND].value))
6933 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
6934 if (fmt[PBM_BACKGROUND].count
6935 && STRINGP (fmt[PBM_BACKGROUND].value))
6936 {
6937 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
6938 img->background = bg;
6939 img->background_valid = 1;
6940 }
5954 6941
5955 for (y = 0; y < height; ++y) 6942 for (y = 0; y < height; ++y)
5956 for (x = 0; x < width; ++x) 6943 for (x = 0; x < width; ++x)
5957 { 6944 {
5958 if (raw_p) 6945 if (raw_p)
5963 c <<= 1; 6950 c <<= 1;
5964 } 6951 }
5965 else 6952 else
5966 g = pbm_scan_number (&p, end); 6953 g = pbm_scan_number (&p, end);
5967 6954
5968 XPutPixel (ximg, x, y, (g 6955 XPutPixel (ximg, x, y, g ? fg : bg);
5969 ? FRAME_FOREGROUND_PIXEL (f)
5970 : FRAME_BACKGROUND_PIXEL (f)));
5971 } 6956 }
5972 } 6957 }
5973 else 6958 else
5974 { 6959 {
5975 for (y = 0; y < height; ++y) 6960 for (y = 0; y < height; ++y)
5992 b = pbm_scan_number (&p, end); 6977 b = pbm_scan_number (&p, end);
5993 } 6978 }
5994 6979
5995 if (r < 0 || g < 0 || b < 0) 6980 if (r < 0 || g < 0 || b < 0)
5996 { 6981 {
5997 xfree (ximg->data); 6982 x_destroy_x_image (ximg);
5998 ximg->data = NULL;
5999 XDestroyImage (ximg);
6000 UNBLOCK_INPUT;
6001 image_error ("Invalid pixel value in image `%s'", 6983 image_error ("Invalid pixel value in image `%s'",
6002 img->spec, Qnil); 6984 img->spec, Qnil);
6003 goto error; 6985 goto error;
6004 } 6986 }
6005 6987
6006 /* RGB values are now in the range 0..max_color_idx. 6988 /* RGB values are now in the range 0..max_color_idx.
6007 Scale this to the range 0..0xffff supported by X. */ 6989 Scale this to the range 0..0xffff supported by X. */
6008 r = (double) r * 65535 / max_color_idx; 6990 r = (double) r * 65535 / max_color_idx;
6010 b = (double) b * 65535 / max_color_idx; 6992 b = (double) b * 65535 / max_color_idx;
6011 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b)); 6993 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6012 } 6994 }
6013 } 6995 }
6014 6996
6997 #if 0 /* TODO: color tables. */
6015 /* Store in IMG->colors the colors allocated for the image, and 6998 /* Store in IMG->colors the colors allocated for the image, and
6016 free the color table. */ 6999 free the color table. */
6017 img->colors = colors_in_color_table (&img->ncolors); 7000 img->colors = colors_in_color_table (&img->ncolors);
6018 free_color_table (); 7001 free_color_table ();
7002 #endif
7003
7004 img->width = width;
7005 img->height = height;
7006
7007 /* Maybe fill in the background field while we have ximg handy. */
7008 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7009 IMAGE_BACKGROUND (img, f, ximg);
6019 7010
6020 /* Put the image into a pixmap. */ 7011 /* Put the image into a pixmap. */
6021 x_put_x_image (f, ximg, img->pixmap, width, height); 7012 x_put_x_image (f, ximg, img->pixmap, width, height);
6022 x_destroy_x_image (ximg); 7013 x_destroy_x_image (ximg);
6023 UNBLOCK_INPUT;
6024
6025 img->width = width;
6026 img->height = height;
6027 7014
6028 UNGCPRO; 7015 UNGCPRO;
6029 xfree (contents); 7016 xfree (contents);
6030 return 1; 7017 return 1;
6031 } 7018 }
6032 #endif /* HAVE_PBM */ 7019
6033 7020
6034 7021
6035 /*********************************************************************** 7022 /***********************************************************************
6036 PNG 7023 PNG
6037 ***********************************************************************/ 7024 ***********************************************************************/
6038 7025
6039 #if HAVE_PNG
6040
6041 #include <png.h>
6042 7026
6043 /* Function prototypes. */ 7027 /* Function prototypes. */
6044 7028
6045 static int png_image_p P_ ((Lisp_Object object)); 7029 static int png_image_p P_ ((Lisp_Object object));
6046 static int png_load P_ ((struct frame *f, struct image *img)); 7030 static int png_load P_ ((struct frame *f, struct image *img));
6059 PNG_ASCENT, 7043 PNG_ASCENT,
6060 PNG_MARGIN, 7044 PNG_MARGIN,
6061 PNG_RELIEF, 7045 PNG_RELIEF,
6062 PNG_ALGORITHM, 7046 PNG_ALGORITHM,
6063 PNG_HEURISTIC_MASK, 7047 PNG_HEURISTIC_MASK,
7048 PNG_MASK,
7049 PNG_BACKGROUND,
6064 PNG_LAST 7050 PNG_LAST
6065 }; 7051 };
6066 7052
6067 /* Vector of image_keyword structures describing the format 7053 /* Vector of image_keyword structures describing the format
6068 of valid user-defined image specifications. */ 7054 of valid user-defined image specifications. */
6070 static struct image_keyword png_format[PNG_LAST] = 7056 static struct image_keyword png_format[PNG_LAST] =
6071 { 7057 {
6072 {":type", IMAGE_SYMBOL_VALUE, 1}, 7058 {":type", IMAGE_SYMBOL_VALUE, 1},
6073 {":data", IMAGE_STRING_VALUE, 0}, 7059 {":data", IMAGE_STRING_VALUE, 0},
6074 {":file", IMAGE_STRING_VALUE, 0}, 7060 {":file", IMAGE_STRING_VALUE, 0},
6075 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 7061 {":ascent", IMAGE_ASCENT_VALUE, 0},
6076 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 7062 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6077 {":relief", IMAGE_INTEGER_VALUE, 0}, 7063 {":relief", IMAGE_INTEGER_VALUE, 0},
6078 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 7064 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6079 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 7065 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7066 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7067 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6080 }; 7068 };
6081 7069
6082 /* Structure describing the image type `png'. */ 7070 /* Structure describing the image type `png'. */
6083 7071
6084 static struct image_type png_type = 7072 static struct image_type png_type =
6098 Lisp_Object object; 7086 Lisp_Object object;
6099 { 7087 {
6100 struct image_keyword fmt[PNG_LAST]; 7088 struct image_keyword fmt[PNG_LAST];
6101 bcopy (png_format, fmt, sizeof fmt); 7089 bcopy (png_format, fmt, sizeof fmt);
6102 7090
6103 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng) 7091 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
6104 || (fmt[PNG_ASCENT].count
6105 && XFASTINT (fmt[PNG_ASCENT].value) > 100))
6106 return 0; 7092 return 0;
6107 7093
6108 /* Must specify either the :data or :file keyword. */ 7094 /* Must specify either the :data or :file keyword. */
6109 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1; 7095 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6110 } 7096 }
6111 7097
7098
7099 #ifndef HAVE_PNG
7100 static int
7101 png_load (f, img)
7102 struct frame *f;
7103 struct image *img;
7104 {
7105 #ifdef MAC_OSX
7106 if (MyCGImageCreateWithPNGDataProvider)
7107 return image_load_quartz2d (f, img, 1);
7108 else
7109 #endif
7110 return image_load_quicktime (f, img, kQTFileTypePNG);
7111 }
7112 #else
7113
7114 #if defined HAVE_LIBPNG_PNG_H
7115 # include <libpng/png.h>
7116 #else
7117 # include <png.h>
7118 #endif
6112 7119
6113 /* Error and warning handlers installed when the PNG library 7120 /* Error and warning handlers installed when the PNG library
6114 is initialized. */ 7121 is initialized. */
6115 7122
6116 static void 7123 static void
6172 struct image *img; 7179 struct image *img;
6173 { 7180 {
6174 Lisp_Object file, specified_file; 7181 Lisp_Object file, specified_file;
6175 Lisp_Object specified_data; 7182 Lisp_Object specified_data;
6176 int x, y, i; 7183 int x, y, i;
6177 XImage *ximg, *mask_img = NULL; 7184 XImagePtr ximg, mask_img = NULL;
6178 struct gcpro gcpro1; 7185 struct gcpro gcpro1;
6179 png_struct *png_ptr = NULL; 7186 png_struct *png_ptr = NULL;
6180 png_info *info_ptr = NULL, *end_info = NULL; 7187 png_info *info_ptr = NULL, *end_info = NULL;
6181 FILE *fp = NULL; 7188 FILE *volatile fp = NULL;
6182 png_byte sig[8]; 7189 png_byte sig[8];
6183 png_byte *pixels = NULL; 7190 png_byte * volatile pixels = NULL;
6184 png_byte **rows = NULL; 7191 png_byte ** volatile rows = NULL;
6185 png_uint_32 width, height; 7192 png_uint_32 width, height;
6186 int bit_depth, color_type, interlace_type; 7193 int bit_depth, color_type, interlace_type;
6187 png_byte channels; 7194 png_byte channels;
6188 png_uint_32 row_bytes; 7195 png_uint_32 row_bytes;
6189 int transparent_p; 7196 int transparent_p;
6190 char *gamma_str; 7197 double screen_gamma;
6191 double screen_gamma, image_gamma;
6192 int intent;
6193 struct png_memory_storage tbr; /* Data to be read */ 7198 struct png_memory_storage tbr; /* Data to be read */
6194 7199
6195 /* Find out what file to load. */ 7200 /* Find out what file to load. */
6196 specified_file = image_spec_value (img->spec, QCfile, NULL); 7201 specified_file = image_spec_value (img->spec, QCfile, NULL);
6197 specified_data = image_spec_value (img->spec, QCdata, NULL); 7202 specified_data = image_spec_value (img->spec, QCdata, NULL);
6200 7205
6201 if (NILP (specified_data)) 7206 if (NILP (specified_data))
6202 { 7207 {
6203 file = x_find_image_file (specified_file); 7208 file = x_find_image_file (specified_file);
6204 if (!STRINGP (file)) 7209 if (!STRINGP (file))
6205 { 7210 {
6206 image_error ("Cannot find image file `%s'", specified_file, Qnil); 7211 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6207 UNGCPRO; 7212 UNGCPRO;
6208 return 0; 7213 return 0;
6209 } 7214 }
6210 7215
6211 /* Open the image file. */ 7216 /* Open the image file. */
6212 fp = fopen (SDATA (file), "rb"); 7217 fp = fopen (SDATA (file), "rb");
6213 if (!fp) 7218 if (!fp)
6214 { 7219 {
6215 image_error ("Cannot open image file `%s'", file, Qnil); 7220 image_error ("Cannot open image file `%s'", file, Qnil);
6216 UNGCPRO; 7221 UNGCPRO;
6217 fclose (fp); 7222 fclose (fp);
6218 return 0; 7223 return 0;
6219 } 7224 }
6220 7225
6221 /* Check PNG signature. */ 7226 /* Check PNG signature. */
6222 if (fread (sig, 1, sizeof sig, fp) != sizeof sig 7227 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6223 || !png_check_sig (sig, sizeof sig)) 7228 || !png_check_sig (sig, sizeof sig))
6224 { 7229 {
6225 image_error ("Not a PNG file:` %s'", file, Qnil); 7230 image_error ("Not a PNG file: `%s'", file, Qnil);
6226 UNGCPRO; 7231 UNGCPRO;
6227 fclose (fp); 7232 fclose (fp);
6228 return 0; 7233 return 0;
6229 } 7234 }
6230 } 7235 }
6231 else 7236 else
6232 { 7237 {
6233 /* Read from memory. */ 7238 /* Read from memory. */
6234 tbr.bytes = SDATA (specified_data); 7239 tbr.bytes = SDATA (specified_data);
6323 /* Convert grayscale images to RGB. */ 7328 /* Convert grayscale images to RGB. */
6324 if (color_type == PNG_COLOR_TYPE_GRAY 7329 if (color_type == PNG_COLOR_TYPE_GRAY
6325 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 7330 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6326 png_set_gray_to_rgb (png_ptr); 7331 png_set_gray_to_rgb (png_ptr);
6327 7332
6328 /* The value 2.2 is a guess for PC monitors from PNG example.c. */ 7333 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
6329 gamma_str = getenv ("SCREEN_GAMMA"); 7334
6330 screen_gamma = gamma_str ? atof (gamma_str) : 2.2; 7335 #if 0 /* Avoid double gamma correction for PNG images. */
6331 7336 { /* Tell the PNG lib to handle gamma correction for us. */
6332 /* Tell the PNG lib to handle gamma correction for us. */ 7337 int intent;
6333 7338 double image_gamma;
6334 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED) 7339 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6335 if (png_get_sRGB (png_ptr, info_ptr, &intent)) 7340 if (png_get_sRGB (png_ptr, info_ptr, &intent))
6336 /* There is a special chunk in the image specifying the gamma. */ 7341 /* The libpng documentation says this is right in this case. */
6337 png_set_sRGB (png_ptr, info_ptr, intent); 7342 png_set_gamma (png_ptr, screen_gamma, 0.45455);
6338 else 7343 else
6339 #endif 7344 #endif
6340 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma)) 7345 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
6341 /* Image contains gamma information. */ 7346 /* Image contains gamma information. */
6342 png_set_gamma (png_ptr, screen_gamma, image_gamma); 7347 png_set_gamma (png_ptr, screen_gamma, image_gamma);
6343 else 7348 else
6344 /* Use a default of 0.5 for the image gamma. */ 7349 /* Use the standard default for the image gamma. */
6345 png_set_gamma (png_ptr, screen_gamma, 0.5); 7350 png_set_gamma (png_ptr, screen_gamma, 0.45455);
7351 }
7352 #endif /* if 0 */
6346 7353
6347 /* Handle alpha channel by combining the image with a background 7354 /* Handle alpha channel by combining the image with a background
6348 color. Do this only if a real alpha channel is supplied. For 7355 color. Do this only if a real alpha channel is supplied. For
6349 simple transparency, we prefer a clipping mask. */ 7356 simple transparency, we prefer a clipping mask. */
6350 if (!transparent_p) 7357 if (!transparent_p)
6351 { 7358 {
6352 png_color_16 *image_background; 7359 png_color_16 *image_bg;
6353 7360 Lisp_Object specified_bg
6354 if (png_get_bKGD (png_ptr, info_ptr, &image_background)) 7361 = image_spec_value (img->spec, QCbackground, NULL);
7362
7363 if (STRINGP (specified_bg))
7364 /* The user specified `:background', use that. */
7365 {
7366 XColor color;
7367 if (mac_defined_color (f, SDATA (specified_bg), &color, 0))
7368 {
7369 png_color_16 user_bg;
7370
7371 bzero (&user_bg, sizeof user_bg);
7372 user_bg.red = color.red >> 8;
7373 user_bg.green = color.green >> 8;
7374 user_bg.blue = color.blue >> 8;
7375
7376 png_set_background (png_ptr, &user_bg,
7377 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
7378 }
7379 }
7380 else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
6355 /* Image contains a background color with which to 7381 /* Image contains a background color with which to
6356 combine the image. */ 7382 combine the image. */
6357 png_set_background (png_ptr, image_background, 7383 png_set_background (png_ptr, image_bg,
6358 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); 7384 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6359 else 7385 else
6360 { 7386 {
6361 /* Image does not contain a background color with which 7387 /* Image does not contain a background color with which
6362 to combine the image data via an alpha channel. Use 7388 to combine the image data via an alpha channel. Use
6363 the frame's background instead. */ 7389 the frame's background instead. */
6364 XColor color; 7390 unsigned long color;
7391 png_color_16 frame_background;
7392 color = FRAME_BACKGROUND_PIXEL (f);
7393 #if 0 /* TODO : Colormap support. */
6365 Colormap cmap; 7394 Colormap cmap;
6366 png_color_16 frame_background; 7395
6367 7396 cmap = FRAME_X_COLORMAP (f);
6368 BLOCK_INPUT; 7397 x_query_color (f, &color);
6369 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f)); 7398 #endif
6370 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6371 XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
6372 UNBLOCK_INPUT;
6373
6374 bzero (&frame_background, sizeof frame_background); 7399 bzero (&frame_background, sizeof frame_background);
6375 frame_background.red = color.red; 7400 frame_background.red = RED_FROM_ULONG (color);
6376 frame_background.green = color.green; 7401 frame_background.green = GREEN_FROM_ULONG (color);
6377 frame_background.blue = color.blue; 7402 frame_background.blue = BLUE_FROM_ULONG (color);
6378 7403
6379 png_set_background (png_ptr, &frame_background, 7404 png_set_background (png_ptr, &frame_background,
6380 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); 7405 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6381 } 7406 }
6382 } 7407 }
6408 { 7433 {
6409 fclose (fp); 7434 fclose (fp);
6410 fp = NULL; 7435 fp = NULL;
6411 } 7436 }
6412 7437
6413 BLOCK_INPUT;
6414
6415 /* Create the X image and pixmap. */ 7438 /* Create the X image and pixmap. */
6416 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, 7439 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6417 &img->pixmap)) 7440 &img->pixmap))
6418 { 7441 goto error;
6419 UNBLOCK_INPUT;
6420 goto error;
6421 }
6422 7442
6423 /* Create an image and pixmap serving as mask if the PNG image 7443 /* Create an image and pixmap serving as mask if the PNG image
6424 contains an alpha channel. */ 7444 contains an alpha channel. */
6425 if (channels == 4 7445 if (channels == 4
6426 && !transparent_p 7446 && !transparent_p
6427 && !x_create_x_image_and_pixmap (f, width, height, 1, 7447 && !x_create_x_image_and_pixmap (f, width, height, 1,
6428 &mask_img, &img->mask)) 7448 &mask_img, &img->mask))
6429 { 7449 {
6430 x_destroy_x_image (ximg); 7450 x_destroy_x_image (ximg);
6431 XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap); 7451 XFreePixmap (FRAME_MAC_DISPLAY (f), img->pixmap);
6432 img->pixmap = 0; 7452 img->pixmap = NULL;
6433 UNBLOCK_INPUT;
6434 goto error; 7453 goto error;
6435 } 7454 }
6436 7455
6437 /* Fill the X image and mask from PNG data. */ 7456 /* Fill the X image and mask from PNG data. */
7457 #if 0 /* TODO: Color tables. */
6438 init_color_table (); 7458 init_color_table ();
7459 #endif
6439 7460
6440 for (y = 0; y < height; ++y) 7461 for (y = 0; y < height; ++y)
6441 { 7462 {
6442 png_byte *p = rows[y]; 7463 png_byte *p = rows[y];
6443 7464
6467 the frame's background color to combine the image with. */ 7488 the frame's background color to combine the image with. */
6468 7489
6469 if (channels == 4) 7490 if (channels == 4)
6470 { 7491 {
6471 if (mask_img) 7492 if (mask_img)
6472 XPutPixel (mask_img, x, y, *p > 0); 7493 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
6473 ++p; 7494 ++p;
6474 } 7495 }
6475 } 7496 }
6476 } 7497 }
6477 7498
7499 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7500 /* Set IMG's background color from the PNG image, unless the user
7501 overrode it. */
7502 {
7503 png_color_16 *bg;
7504 if (png_get_bKGD (png_ptr, info_ptr, &bg))
7505 {
7506 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
7507 img->background_valid = 1;
7508 }
7509 }
7510
7511 #if 0 /* TODO: Color tables. */
6478 /* Remember colors allocated for this image. */ 7512 /* Remember colors allocated for this image. */
6479 img->colors = colors_in_color_table (&img->ncolors); 7513 img->colors = colors_in_color_table (&img->ncolors);
6480 free_color_table (); 7514 free_color_table ();
7515 #endif
6481 7516
6482 /* Clean up. */ 7517 /* Clean up. */
6483 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info); 7518 png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6484 xfree (rows); 7519 xfree (rows);
6485 xfree (pixels); 7520 xfree (pixels);
6486 7521
6487 img->width = width; 7522 img->width = width;
6488 img->height = height; 7523 img->height = height;
6489 7524
7525 /* Maybe fill in the background field while we have ximg handy. */
7526 IMAGE_BACKGROUND (img, f, ximg);
7527
6490 /* Put the image into the pixmap, then free the X image and its buffer. */ 7528 /* Put the image into the pixmap, then free the X image and its buffer. */
6491 x_put_x_image (f, ximg, img->pixmap, width, height); 7529 x_put_x_image (f, ximg, img->pixmap, width, height);
6492 x_destroy_x_image (ximg); 7530 x_destroy_x_image (ximg);
6493 7531
6494 /* Same for the mask. */ 7532 /* Same for the mask. */
6495 if (mask_img) 7533 if (mask_img)
6496 { 7534 {
7535 /* Fill in the background_transparent field while we have the mask
7536 handy. */
7537 image_background_transparent (img, f, mask_img);
7538
6497 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 7539 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6498 x_destroy_x_image (mask_img); 7540 x_destroy_x_image (mask_img);
6499 } 7541 }
6500 7542
6501 UNBLOCK_INPUT;
6502 UNGCPRO; 7543 UNGCPRO;
6503 return 1; 7544 return 1;
6504 } 7545 }
6505 7546
6506 #endif /* HAVE_PNG != 0 */ 7547 #endif /* HAVE_PNG */
6507 7548
6508 7549
6509 7550
6510 /*********************************************************************** 7551 /***********************************************************************
6511 JPEG 7552 JPEG
6512 ***********************************************************************/ 7553 ***********************************************************************/
6513
6514 #if HAVE_JPEG
6515
6516 /* Work around a warning about HAVE_STDLIB_H being redefined in
6517 jconfig.h. */
6518 #ifdef HAVE_STDLIB_H
6519 #define HAVE_STDLIB_H_1
6520 #undef HAVE_STDLIB_H
6521 #endif /* HAVE_STLIB_H */
6522
6523 #include <jpeglib.h>
6524 #include <jerror.h>
6525 #include <setjmp.h>
6526
6527 #ifdef HAVE_STLIB_H_1
6528 #define HAVE_STDLIB_H 1
6529 #endif
6530 7554
6531 static int jpeg_image_p P_ ((Lisp_Object object)); 7555 static int jpeg_image_p P_ ((Lisp_Object object));
6532 static int jpeg_load P_ ((struct frame *f, struct image *img)); 7556 static int jpeg_load P_ ((struct frame *f, struct image *img));
6533 7557
6534 /* The symbol `jpeg' identifying images of this type. */ 7558 /* The symbol `jpeg' identifying images of this type. */
6545 JPEG_ASCENT, 7569 JPEG_ASCENT,
6546 JPEG_MARGIN, 7570 JPEG_MARGIN,
6547 JPEG_RELIEF, 7571 JPEG_RELIEF,
6548 JPEG_ALGORITHM, 7572 JPEG_ALGORITHM,
6549 JPEG_HEURISTIC_MASK, 7573 JPEG_HEURISTIC_MASK,
7574 JPEG_MASK,
7575 JPEG_BACKGROUND,
6550 JPEG_LAST 7576 JPEG_LAST
6551 }; 7577 };
6552 7578
6553 /* Vector of image_keyword structures describing the format 7579 /* Vector of image_keyword structures describing the format
6554 of valid user-defined image specifications. */ 7580 of valid user-defined image specifications. */
6556 static struct image_keyword jpeg_format[JPEG_LAST] = 7582 static struct image_keyword jpeg_format[JPEG_LAST] =
6557 { 7583 {
6558 {":type", IMAGE_SYMBOL_VALUE, 1}, 7584 {":type", IMAGE_SYMBOL_VALUE, 1},
6559 {":data", IMAGE_STRING_VALUE, 0}, 7585 {":data", IMAGE_STRING_VALUE, 0},
6560 {":file", IMAGE_STRING_VALUE, 0}, 7586 {":file", IMAGE_STRING_VALUE, 0},
6561 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 7587 {":ascent", IMAGE_ASCENT_VALUE, 0},
6562 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 7588 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6563 {":relief", IMAGE_INTEGER_VALUE, 0}, 7589 {":relief", IMAGE_INTEGER_VALUE, 0},
6564 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 7590 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6565 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 7591 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7592 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7593 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6566 }; 7594 };
6567 7595
6568 /* Structure describing the image type `jpeg'. */ 7596 /* Structure describing the image type `jpeg'. */
6569 7597
6570 static struct image_type jpeg_type = 7598 static struct image_type jpeg_type =
6585 { 7613 {
6586 struct image_keyword fmt[JPEG_LAST]; 7614 struct image_keyword fmt[JPEG_LAST];
6587 7615
6588 bcopy (jpeg_format, fmt, sizeof fmt); 7616 bcopy (jpeg_format, fmt, sizeof fmt);
6589 7617
6590 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg) 7618 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6591 || (fmt[JPEG_ASCENT].count
6592 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
6593 return 0; 7619 return 0;
6594 7620
6595 /* Must specify either the :data or :file keyword. */ 7621 /* Must specify either the :data or :file keyword. */
6596 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1; 7622 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6597 } 7623 }
6598 7624
7625
7626 #ifndef HAVE_JPEG
7627 static int
7628 jpeg_load (f, img)
7629 struct frame *f;
7630 struct image *img;
7631 {
7632 #ifdef MAC_OSX
7633 return image_load_quartz2d (f, img, 0);
7634 #else
7635 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7636 #endif
7637 }
7638 #else
7639
7640 /* Work around a warning about HAVE_STDLIB_H being redefined in
7641 jconfig.h. */
7642 #ifdef HAVE_STDLIB_H
7643 #define HAVE_STDLIB_H_1
7644 #undef HAVE_STDLIB_H
7645 #endif /* HAVE_STLIB_H */
7646
7647 #include <jpeglib.h>
7648 #include <jerror.h>
7649 #include <setjmp.h>
7650
7651 #ifdef HAVE_STLIB_H_1
7652 #define HAVE_STDLIB_H 1
7653 #endif
6599 7654
6600 struct my_jpeg_error_mgr 7655 struct my_jpeg_error_mgr
6601 { 7656 {
6602 struct jpeg_error_mgr pub; 7657 struct jpeg_error_mgr pub;
6603 jmp_buf setjmp_buffer; 7658 jmp_buf setjmp_buffer;
6604 }; 7659 };
6605 7660
7661
6606 static void 7662 static void
6607 my_error_exit (cinfo) 7663 my_error_exit (cinfo)
6608 j_common_ptr cinfo; 7664 j_common_ptr cinfo;
6609 { 7665 {
6610 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err; 7666 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6611 longjmp (mgr->setjmp_buffer, 1); 7667 longjmp (mgr->setjmp_buffer, 1);
6612 } 7668 }
7669
6613 7670
6614 /* Init source method for JPEG data source manager. Called by 7671 /* Init source method for JPEG data source manager. Called by
6615 jpeg_read_header() before any data is actually read. See 7672 jpeg_read_header() before any data is actually read. See
6616 libjpeg.doc from the JPEG lib distribution. */ 7673 libjpeg.doc from the JPEG lib distribution. */
6617 7674
6717 { 7774 {
6718 struct jpeg_decompress_struct cinfo; 7775 struct jpeg_decompress_struct cinfo;
6719 struct my_jpeg_error_mgr mgr; 7776 struct my_jpeg_error_mgr mgr;
6720 Lisp_Object file, specified_file; 7777 Lisp_Object file, specified_file;
6721 Lisp_Object specified_data; 7778 Lisp_Object specified_data;
6722 FILE *fp = NULL; 7779 FILE * volatile fp = NULL;
6723 JSAMPARRAY buffer; 7780 JSAMPARRAY buffer;
6724 int row_stride, x, y; 7781 int row_stride, x, y;
6725 XImage *ximg = NULL; 7782 XImagePtr ximg = NULL;
6726 int rc; 7783 int rc;
6727 unsigned long *colors; 7784 unsigned long *colors;
6728 int width, height; 7785 int width, height;
6729 struct gcpro gcpro1; 7786 struct gcpro gcpro1;
6730 7787
6736 7793
6737 if (NILP (specified_data)) 7794 if (NILP (specified_data))
6738 { 7795 {
6739 file = x_find_image_file (specified_file); 7796 file = x_find_image_file (specified_file);
6740 if (!STRINGP (file)) 7797 if (!STRINGP (file))
6741 { 7798 {
6742 image_error ("Cannot find image file `%s'", specified_file, Qnil); 7799 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6743 UNGCPRO; 7800 UNGCPRO;
6744 return 0; 7801 return 0;
6745 } 7802 }
6746 7803
6747 fp = fopen (SDATA (file), "r"); 7804 fp = fopen (SDATA (file), "r");
6748 if (fp == NULL) 7805 if (fp == NULL)
6749 { 7806 {
6750 image_error ("Cannot open `%s'", file, Qnil); 7807 image_error ("Cannot open `%s'", file, Qnil);
6751 UNGCPRO; 7808 UNGCPRO;
6752 return 0; 7809 return 0;
6753 } 7810 }
6754 } 7811 }
6755 7812
6756 /* Customize libjpeg's error handling to call my_error_exit when an 7813 /* Customize libjpeg's error handling to call my_error_exit when an
6757 error is detected. This function will perform a longjmp. */ 7814 error is detected. This function will perform a longjmp. */
7815 cinfo.err = jpeg_std_error (&mgr.pub);
6758 mgr.pub.error_exit = my_error_exit; 7816 mgr.pub.error_exit = my_error_exit;
6759 cinfo.err = jpeg_std_error (&mgr.pub);
6760 7817
6761 if ((rc = setjmp (mgr.setjmp_buffer)) != 0) 7818 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6762 { 7819 {
6763 if (rc == 1) 7820 if (rc == 1)
6764 { 7821 {
6769 build_string (buffer)); 7826 build_string (buffer));
6770 } 7827 }
6771 7828
6772 /* Close the input file and destroy the JPEG object. */ 7829 /* Close the input file and destroy the JPEG object. */
6773 if (fp) 7830 if (fp)
6774 fclose (fp); 7831 fclose ((FILE *) fp);
6775 jpeg_destroy_decompress (&cinfo); 7832 jpeg_destroy_decompress (&cinfo);
6776
6777 BLOCK_INPUT;
6778 7833
6779 /* If we already have an XImage, free that. */ 7834 /* If we already have an XImage, free that. */
6780 x_destroy_x_image (ximg); 7835 x_destroy_x_image (ximg);
6781 7836
6782 /* Free pixmap and colors. */ 7837 /* Free pixmap and colors. */
6783 x_clear_image (f, img); 7838 x_clear_image (f, img);
6784 7839
6785 UNBLOCK_INPUT;
6786 UNGCPRO; 7840 UNGCPRO;
6787 return 0; 7841 return 0;
6788 } 7842 }
6789 7843
6790 /* Create the JPEG decompression object. Let it read from fp. 7844 /* Create the JPEG decompression object. Let it read from fp.
6791 Read the JPEG image header. */ 7845 Read the JPEG image header. */
6792 jpeg_create_decompress (&cinfo); 7846 jpeg_create_decompress (&cinfo);
6793 7847
6794 if (NILP (specified_data)) 7848 if (NILP (specified_data))
6795 jpeg_stdio_src (&cinfo, fp); 7849 jpeg_stdio_src (&cinfo, (FILE *) fp);
6796 else 7850 else
6797 jpeg_memory_src (&cinfo, SDATA (specified_data), 7851 jpeg_memory_src (&cinfo, SDATA (specified_data),
6798 SBYTES (specified_data)); 7852 SBYTES (specified_data));
6799 7853
6800 jpeg_read_header (&cinfo, TRUE); 7854 jpeg_read_header (&cinfo, TRUE);
6801 7855
6802 /* Customize decompression so that color quantization will be used. 7856 /* Customize decompression so that color quantization will be used.
6803 Start decompression. */ 7857 Start decompression. */
6804 cinfo.quantize_colors = TRUE; 7858 cinfo.quantize_colors = TRUE;
6805 jpeg_start_decompress (&cinfo); 7859 jpeg_start_decompress (&cinfo);
6806 width = img->width = cinfo.output_width; 7860 width = img->width = cinfo.output_width;
6807 height = img->height = cinfo.output_height; 7861 height = img->height = cinfo.output_height;
6808 7862
6809 BLOCK_INPUT;
6810
6811 /* Create X image and pixmap. */ 7863 /* Create X image and pixmap. */
6812 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, 7864 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6813 &img->pixmap)) 7865 longjmp (mgr.setjmp_buffer, 2);
6814 {
6815 UNBLOCK_INPUT;
6816 longjmp (mgr.setjmp_buffer, 2);
6817 }
6818 7866
6819 /* Allocate colors. When color quantization is used, 7867 /* Allocate colors. When color quantization is used,
6820 cinfo.actual_number_of_colors has been set with the number of 7868 cinfo.actual_number_of_colors has been set with the number of
6821 colors generated, and cinfo.colormap is a two-dimensional array 7869 colors generated, and cinfo.colormap is a two-dimensional array
6822 of color indices in the range 0..cinfo.actual_number_of_colors. 7870 of color indices in the range 0..cinfo.actual_number_of_colors.
6829 else if (cinfo.out_color_components > 1) 7877 else if (cinfo.out_color_components > 1)
6830 ir = 0, ig = 1, ib = 0; 7878 ir = 0, ig = 1, ib = 0;
6831 else 7879 else
6832 ir = 0, ig = 0, ib = 0; 7880 ir = 0, ig = 0, ib = 0;
6833 7881
7882 #if 0 /* TODO: Color tables. */
6834 /* Use the color table mechanism because it handles colors that 7883 /* Use the color table mechanism because it handles colors that
6835 cannot be allocated nicely. Such colors will be replaced with 7884 cannot be allocated nicely. Such colors will be replaced with
6836 a default color, and we don't have to care about which colors 7885 a default color, and we don't have to care about which colors
6837 can be freed safely, and which can't. */ 7886 can be freed safely, and which can't. */
6838 init_color_table (); 7887 init_color_table ();
7888 #endif
6839 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors 7889 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6840 * sizeof *colors); 7890 * sizeof *colors);
6841 7891
6842 for (i = 0; i < cinfo.actual_number_of_colors; ++i) 7892 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6843 { 7893 {
6847 int g = cinfo.colormap[ig][i] << 8; 7897 int g = cinfo.colormap[ig][i] << 8;
6848 int b = cinfo.colormap[ib][i] << 8; 7898 int b = cinfo.colormap[ib][i] << 8;
6849 colors[i] = lookup_rgb_color (f, r, g, b); 7899 colors[i] = lookup_rgb_color (f, r, g, b);
6850 } 7900 }
6851 7901
7902 #if 0 /* TODO: Color tables. */
6852 /* Remember those colors actually allocated. */ 7903 /* Remember those colors actually allocated. */
6853 img->colors = colors_in_color_table (&img->ncolors); 7904 img->colors = colors_in_color_table (&img->ncolors);
6854 free_color_table (); 7905 free_color_table ();
7906 #endif
6855 } 7907 }
6856 7908
6857 /* Read pixels. */ 7909 /* Read pixels. */
6858 row_stride = width * cinfo.output_components; 7910 row_stride = width * cinfo.output_components;
6859 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE, 7911 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6867 7919
6868 /* Clean up. */ 7920 /* Clean up. */
6869 jpeg_finish_decompress (&cinfo); 7921 jpeg_finish_decompress (&cinfo);
6870 jpeg_destroy_decompress (&cinfo); 7922 jpeg_destroy_decompress (&cinfo);
6871 if (fp) 7923 if (fp)
6872 fclose (fp); 7924 fclose ((FILE *) fp);
7925
7926 /* Maybe fill in the background field while we have ximg handy. */
7927 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7928 IMAGE_BACKGROUND (img, f, ximg);
6873 7929
6874 /* Put the image into the pixmap. */ 7930 /* Put the image into the pixmap. */
6875 x_put_x_image (f, ximg, img->pixmap, width, height); 7931 x_put_x_image (f, ximg, img->pixmap, width, height);
6876 x_destroy_x_image (ximg); 7932 x_destroy_x_image (ximg);
6877 UNBLOCK_INPUT;
6878 UNGCPRO; 7933 UNGCPRO;
6879 return 1; 7934 return 1;
6880 } 7935 }
6881 7936
6882 #endif /* HAVE_JPEG */ 7937 #endif /* HAVE_JPEG */
6884 7939
6885 7940
6886 /*********************************************************************** 7941 /***********************************************************************
6887 TIFF 7942 TIFF
6888 ***********************************************************************/ 7943 ***********************************************************************/
6889
6890 #if HAVE_TIFF
6891
6892 #include <tiffio.h>
6893 7944
6894 static int tiff_image_p P_ ((Lisp_Object object)); 7945 static int tiff_image_p P_ ((Lisp_Object object));
6895 static int tiff_load P_ ((struct frame *f, struct image *img)); 7946 static int tiff_load P_ ((struct frame *f, struct image *img));
6896 7947
6897 /* The symbol `tiff' identifying images of this type. */ 7948 /* The symbol `tiff' identifying images of this type. */
6908 TIFF_ASCENT, 7959 TIFF_ASCENT,
6909 TIFF_MARGIN, 7960 TIFF_MARGIN,
6910 TIFF_RELIEF, 7961 TIFF_RELIEF,
6911 TIFF_ALGORITHM, 7962 TIFF_ALGORITHM,
6912 TIFF_HEURISTIC_MASK, 7963 TIFF_HEURISTIC_MASK,
7964 TIFF_MASK,
7965 TIFF_BACKGROUND,
6913 TIFF_LAST 7966 TIFF_LAST
6914 }; 7967 };
6915 7968
6916 /* Vector of image_keyword structures describing the format 7969 /* Vector of image_keyword structures describing the format
6917 of valid user-defined image specifications. */ 7970 of valid user-defined image specifications. */
6919 static struct image_keyword tiff_format[TIFF_LAST] = 7972 static struct image_keyword tiff_format[TIFF_LAST] =
6920 { 7973 {
6921 {":type", IMAGE_SYMBOL_VALUE, 1}, 7974 {":type", IMAGE_SYMBOL_VALUE, 1},
6922 {":data", IMAGE_STRING_VALUE, 0}, 7975 {":data", IMAGE_STRING_VALUE, 0},
6923 {":file", IMAGE_STRING_VALUE, 0}, 7976 {":file", IMAGE_STRING_VALUE, 0},
6924 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 7977 {":ascent", IMAGE_ASCENT_VALUE, 0},
6925 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 7978 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6926 {":relief", IMAGE_INTEGER_VALUE, 0}, 7979 {":relief", IMAGE_INTEGER_VALUE, 0},
6927 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 7980 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6928 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 7981 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7982 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7983 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6929 }; 7984 };
6930 7985
6931 /* Structure describing the image type `tiff'. */ 7986 /* Structure describing the image type `tiff'. */
6932 7987
6933 static struct image_type tiff_type = 7988 static struct image_type tiff_type =
6947 Lisp_Object object; 8002 Lisp_Object object;
6948 { 8003 {
6949 struct image_keyword fmt[TIFF_LAST]; 8004 struct image_keyword fmt[TIFF_LAST];
6950 bcopy (tiff_format, fmt, sizeof fmt); 8005 bcopy (tiff_format, fmt, sizeof fmt);
6951 8006
6952 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff) 8007 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6953 || (fmt[TIFF_ASCENT].count
6954 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
6955 return 0; 8008 return 0;
6956 8009
6957 /* Must specify either the :data or :file keyword. */ 8010 /* Must specify either the :data or :file keyword. */
6958 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1; 8011 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6959 } 8012 }
6960 8013
8014 #ifndef HAVE_TIFF
8015
8016 static int
8017 tiff_load (f, img)
8018 struct frame *f;
8019 struct image *img;
8020 {
8021 return image_load_quicktime (f, img, kQTFileTypeTIFF);
8022 }
8023
8024 #else
8025
8026 #include <tiffio.h>
6961 8027
6962 /* Reading from a memory buffer for TIFF images Based on the PNG 8028 /* Reading from a memory buffer for TIFF images Based on the PNG
6963 memory source, but we have to provide a lot of extra functions. 8029 memory source, but we have to provide a lot of extra functions.
6964 Blah. 8030 Blah.
6965 8031
6973 unsigned char *bytes; 8039 unsigned char *bytes;
6974 size_t len; 8040 size_t len;
6975 int index; 8041 int index;
6976 } 8042 }
6977 tiff_memory_source; 8043 tiff_memory_source;
8044
6978 8045
6979 static size_t 8046 static size_t
6980 tiff_read_from_memory (data, buf, size) 8047 tiff_read_from_memory (data, buf, size)
6981 thandle_t data; 8048 thandle_t data;
6982 tdata_t buf; 8049 tdata_t buf;
6989 bcopy (src->bytes + src->index, buf, size); 8056 bcopy (src->bytes + src->index, buf, size);
6990 src->index += size; 8057 src->index += size;
6991 return size; 8058 return size;
6992 } 8059 }
6993 8060
8061
6994 static size_t 8062 static size_t
6995 tiff_write_from_memory (data, buf, size) 8063 tiff_write_from_memory (data, buf, size)
6996 thandle_t data; 8064 thandle_t data;
6997 tdata_t buf; 8065 tdata_t buf;
6998 tsize_t size; 8066 tsize_t size;
6999 { 8067 {
7000 return (size_t) -1; 8068 return (size_t) -1;
7001 } 8069 }
7002 8070
8071
7003 static toff_t 8072 static toff_t
7004 tiff_seek_in_memory (data, off, whence) 8073 tiff_seek_in_memory (data, off, whence)
7005 thandle_t data; 8074 thandle_t data;
7006 toff_t off; 8075 toff_t off;
7007 int whence; 8076 int whence;
7021 8090
7022 case SEEK_CUR: /* Go from current position. */ 8091 case SEEK_CUR: /* Go from current position. */
7023 idx = src->index + off; 8092 idx = src->index + off;
7024 break; 8093 break;
7025 8094
7026 default: /* Invalid `whence'. */ 8095 default: /* Invalid `whence'. */
7027 return -1; 8096 return -1;
7028 } 8097 }
7029 8098
7030 if (idx > src->len || idx < 0) 8099 if (idx > src->len || idx < 0)
7031 return -1; 8100 return -1;
7032 8101
7033 src->index = idx; 8102 src->index = idx;
7034 return src->index; 8103 return src->index;
7035 } 8104 }
8105
7036 8106
7037 static int 8107 static int
7038 tiff_close_memory (data) 8108 tiff_close_memory (data)
7039 thandle_t data; 8109 thandle_t data;
7040 { 8110 {
7041 /* NOOP */ 8111 /* NOOP */
7042 return 0; 8112 return 0;
7043 } 8113 }
8114
7044 8115
7045 static int 8116 static int
7046 tiff_mmap_memory (data, pbase, psize) 8117 tiff_mmap_memory (data, pbase, psize)
7047 thandle_t data; 8118 thandle_t data;
7048 tdata_t *pbase; 8119 tdata_t *pbase;
7050 { 8121 {
7051 /* It is already _IN_ memory. */ 8122 /* It is already _IN_ memory. */
7052 return 0; 8123 return 0;
7053 } 8124 }
7054 8125
8126
7055 static void 8127 static void
7056 tiff_unmap_memory (data, base, size) 8128 tiff_unmap_memory (data, base, size)
7057 thandle_t data; 8129 thandle_t data;
7058 tdata_t base; 8130 tdata_t base;
7059 toff_t size; 8131 toff_t size;
7060 { 8132 {
7061 /* We don't need to do this. */ 8133 /* We don't need to do this. */
7062 } 8134 }
7063 8135
8136
7064 static toff_t 8137 static toff_t
7065 tiff_size_of_memory (data) 8138 tiff_size_of_memory (data)
7066 thandle_t data; 8139 thandle_t data;
7067 { 8140 {
7068 return ((tiff_memory_source *) data)->len; 8141 return ((tiff_memory_source *) data)->len;
7069 } 8142 }
8143
8144
8145 static void
8146 tiff_error_handler (title, format, ap)
8147 const char *title, *format;
8148 va_list ap;
8149 {
8150 char buf[512];
8151 int len;
8152
8153 len = sprintf (buf, "TIFF error: %s ", title);
8154 vsprintf (buf + len, format, ap);
8155 add_to_log (buf, Qnil, Qnil);
8156 }
8157
8158
8159 static void
8160 tiff_warning_handler (title, format, ap)
8161 const char *title, *format;
8162 va_list ap;
8163 {
8164 char buf[512];
8165 int len;
8166
8167 len = sprintf (buf, "TIFF warning: %s ", title);
8168 vsprintf (buf + len, format, ap);
8169 add_to_log (buf, Qnil, Qnil);
8170 }
8171
7070 8172
7071 /* Load TIFF image IMG for use on frame F. Value is non-zero if 8173 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7072 successful. */ 8174 successful. */
7073 8175
7074 static int 8176 static int
7080 Lisp_Object specified_data; 8182 Lisp_Object specified_data;
7081 TIFF *tiff; 8183 TIFF *tiff;
7082 int width, height, x, y; 8184 int width, height, x, y;
7083 uint32 *buf; 8185 uint32 *buf;
7084 int rc; 8186 int rc;
7085 XImage *ximg; 8187 XImagePtr ximg;
7086 struct gcpro gcpro1; 8188 struct gcpro gcpro1;
7087 tiff_memory_source memsrc; 8189 tiff_memory_source memsrc;
7088 8190
7089 specified_file = image_spec_value (img->spec, QCfile, NULL); 8191 specified_file = image_spec_value (img->spec, QCfile, NULL);
7090 specified_data = image_spec_value (img->spec, QCdata, NULL); 8192 specified_data = image_spec_value (img->spec, QCdata, NULL);
7091 file = Qnil; 8193 file = Qnil;
7092 GCPRO1 (file); 8194 GCPRO1 (file);
7093 8195
8196 TIFFSetErrorHandler (tiff_error_handler);
8197 TIFFSetWarningHandler (tiff_warning_handler);
8198
7094 if (NILP (specified_data)) 8199 if (NILP (specified_data))
7095 { 8200 {
7096 /* Read from a file */ 8201 /* Read from a file */
7097 file = x_find_image_file (specified_file); 8202 file = x_find_image_file (specified_file);
7098 if (!STRINGP (file)) 8203 if (!STRINGP (file))
7099 { 8204 {
7100 image_error ("Cannot find image file `%s'", file, Qnil); 8205 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7101 UNGCPRO; 8206 UNGCPRO;
7102 return 0; 8207 return 0;
7103 } 8208 }
7104 8209
7105 /* Try to open the image file. */ 8210 /* Try to open the image file. */
7106 tiff = TIFFOpen (SDATA (file), "r"); 8211 tiff = TIFFOpen (SDATA (file), "r");
7107 if (tiff == NULL) 8212 if (tiff == NULL)
7108 { 8213 {
7109 image_error ("Cannot open `%s'", file, Qnil); 8214 image_error ("Cannot open `%s'", file, Qnil);
7110 UNGCPRO; 8215 UNGCPRO;
7111 return 0; 8216 return 0;
7112 } 8217 }
7113 } 8218 }
7114 else 8219 else
7115 { 8220 {
7116 /* Memory source! */ 8221 /* Memory source! */
7117 memsrc.bytes = SDATA (specified_data); 8222 memsrc.bytes = SDATA (specified_data);
7149 xfree (buf); 8254 xfree (buf);
7150 UNGCPRO; 8255 UNGCPRO;
7151 return 0; 8256 return 0;
7152 } 8257 }
7153 8258
7154 BLOCK_INPUT;
7155
7156 /* Create the X image and pixmap. */ 8259 /* Create the X image and pixmap. */
7157 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 8260 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7158 { 8261 {
7159 UNBLOCK_INPUT;
7160 xfree (buf); 8262 xfree (buf);
7161 UNGCPRO; 8263 UNGCPRO;
7162 return 0; 8264 return 0;
7163 } 8265 }
7164 8266
8267 #if 0 /* TODO: Color tables. */
7165 /* Initialize the color table. */ 8268 /* Initialize the color table. */
7166 init_color_table (); 8269 init_color_table ();
8270 #endif
7167 8271
7168 /* Process the pixel raster. Origin is in the lower-left corner. */ 8272 /* Process the pixel raster. Origin is in the lower-left corner. */
7169 for (y = 0; y < height; ++y) 8273 for (y = 0; y < height; ++y)
7170 { 8274 {
7171 uint32 *row = buf + y * width; 8275 uint32 *row = buf + y * width;
7178 int b = TIFFGetB (abgr) << 8; 8282 int b = TIFFGetB (abgr) << 8;
7179 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b)); 8283 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7180 } 8284 }
7181 } 8285 }
7182 8286
8287 #if 0 /* TODO: Color tables. */
7183 /* Remember the colors allocated for the image. Free the color table. */ 8288 /* Remember the colors allocated for the image. Free the color table. */
7184 img->colors = colors_in_color_table (&img->ncolors); 8289 img->colors = colors_in_color_table (&img->ncolors);
7185 free_color_table (); 8290 free_color_table ();
8291 #endif
8292
8293 img->width = width;
8294 img->height = height;
8295
8296 /* Maybe fill in the background field while we have ximg handy. */
8297 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8298 IMAGE_BACKGROUND (img, f, ximg);
7186 8299
7187 /* Put the image into the pixmap, then free the X image and its buffer. */ 8300 /* Put the image into the pixmap, then free the X image and its buffer. */
7188 x_put_x_image (f, ximg, img->pixmap, width, height); 8301 x_put_x_image (f, ximg, img->pixmap, width, height);
7189 x_destroy_x_image (ximg); 8302 x_destroy_x_image (ximg);
7190 xfree (buf); 8303 xfree (buf);
7191 UNBLOCK_INPUT;
7192
7193 img->width = width;
7194 img->height = height;
7195 8304
7196 UNGCPRO; 8305 UNGCPRO;
7197 return 1; 8306 return 1;
7198 } 8307 }
7199 8308
7200 #endif /* HAVE_TIFF != 0 */ 8309 #endif /* HAVE_TIFF */
7201 8310
7202 8311
7203 8312
7204 /*********************************************************************** 8313 /***********************************************************************
7205 GIF 8314 GIF
7206 ***********************************************************************/ 8315 ***********************************************************************/
7207
7208 #if HAVE_GIF
7209
7210 #include <gif_lib.h>
7211 8316
7212 static int gif_image_p P_ ((Lisp_Object object)); 8317 static int gif_image_p P_ ((Lisp_Object object));
7213 static int gif_load P_ ((struct frame *f, struct image *img)); 8318 static int gif_load P_ ((struct frame *f, struct image *img));
7214 8319
7215 /* The symbol `gif' identifying images of this type. */ 8320 /* The symbol `gif' identifying images of this type. */
7226 GIF_ASCENT, 8331 GIF_ASCENT,
7227 GIF_MARGIN, 8332 GIF_MARGIN,
7228 GIF_RELIEF, 8333 GIF_RELIEF,
7229 GIF_ALGORITHM, 8334 GIF_ALGORITHM,
7230 GIF_HEURISTIC_MASK, 8335 GIF_HEURISTIC_MASK,
8336 GIF_MASK,
7231 GIF_IMAGE, 8337 GIF_IMAGE,
8338 GIF_BACKGROUND,
7232 GIF_LAST 8339 GIF_LAST
7233 }; 8340 };
7234 8341
7235 /* Vector of image_keyword structures describing the format 8342 /* Vector of image_keyword structures describing the format
7236 of valid user-defined image specifications. */ 8343 of valid user-defined image specifications. */
7238 static struct image_keyword gif_format[GIF_LAST] = 8345 static struct image_keyword gif_format[GIF_LAST] =
7239 { 8346 {
7240 {":type", IMAGE_SYMBOL_VALUE, 1}, 8347 {":type", IMAGE_SYMBOL_VALUE, 1},
7241 {":data", IMAGE_STRING_VALUE, 0}, 8348 {":data", IMAGE_STRING_VALUE, 0},
7242 {":file", IMAGE_STRING_VALUE, 0}, 8349 {":file", IMAGE_STRING_VALUE, 0},
7243 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 8350 {":ascent", IMAGE_ASCENT_VALUE, 0},
7244 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 8351 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7245 {":relief", IMAGE_INTEGER_VALUE, 0}, 8352 {":relief", IMAGE_INTEGER_VALUE, 0},
7246 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 8353 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7247 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 8354 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7248 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} 8355 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8356 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8357 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7249 }; 8358 };
7250 8359
7251 /* Structure describing the image type `gif'. */ 8360 /* Structure describing the image type `gif'. */
7252 8361
7253 static struct image_type gif_type = 8362 static struct image_type gif_type =
7257 gif_load, 8366 gif_load,
7258 x_clear_image, 8367 x_clear_image,
7259 NULL 8368 NULL
7260 }; 8369 };
7261 8370
8371
7262 /* Return non-zero if OBJECT is a valid GIF image specification. */ 8372 /* Return non-zero if OBJECT is a valid GIF image specification. */
7263 8373
7264 static int 8374 static int
7265 gif_image_p (object) 8375 gif_image_p (object)
7266 Lisp_Object object; 8376 Lisp_Object object;
7267 { 8377 {
7268 struct image_keyword fmt[GIF_LAST]; 8378 struct image_keyword fmt[GIF_LAST];
7269 bcopy (gif_format, fmt, sizeof fmt); 8379 bcopy (gif_format, fmt, sizeof fmt);
7270 8380
7271 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif) 8381 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7272 || (fmt[GIF_ASCENT].count
7273 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
7274 return 0; 8382 return 0;
7275 8383
7276 /* Must specify either the :data or :file keyword. */ 8384 /* Must specify either the :data or :file keyword. */
7277 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1; 8385 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7278 } 8386 }
8387
8388 #ifndef HAVE_GIF
8389
8390 static int
8391 gif_load (f, img)
8392 struct frame *f;
8393 struct image *img;
8394 {
8395 Lisp_Object specified_file, file;
8396 Lisp_Object specified_data;
8397 OSErr err;
8398 Boolean graphic_p, movie_p, prefer_graphic_p;
8399 Handle dh = NULL;
8400 Movie movie = NULL;
8401 Lisp_Object image;
8402 Track track = NULL;
8403 Media media = NULL;
8404 long nsamples;
8405 Rect rect;
8406 Lisp_Object specified_bg;
8407 XColor color;
8408 RGBColor bg_color;
8409 int width, height;
8410 XImagePtr ximg;
8411 TimeValue time;
8412 struct gcpro gcpro1;
8413 int ino;
8414
8415 specified_file = image_spec_value (img->spec, QCfile, NULL);
8416 specified_data = image_spec_value (img->spec, QCdata, NULL);
8417
8418 if (NILP (specified_data))
8419 {
8420 /* Read from a file */
8421 FSSpec fss;
8422 short refnum;
8423
8424 err = find_image_fsspec (specified_file, &file, &fss);
8425 if (err != noErr)
8426 {
8427 if (err == fnfErr)
8428 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8429 else
8430 goto open_error;
8431 }
8432
8433 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
8434 &graphic_p, &movie_p, &prefer_graphic_p, 0);
8435 if (err != noErr)
8436 goto open_error;
8437
8438 if (!graphic_p && !movie_p)
8439 goto open_error;
8440 if (prefer_graphic_p)
8441 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
8442 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
8443 if (err != noErr)
8444 goto open_error;
8445 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
8446 CloseMovieFile (refnum);
8447 if (err != noErr)
8448 {
8449 image_error ("Error reading `%s'", file, Qnil);
8450 return 0;
8451 }
8452 }
8453 else
8454 {
8455 /* Memory source! */
8456 Handle dref = NULL;
8457 long file_type_atom[3];
8458
8459 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
8460 if (err != noErr)
8461 {
8462 image_error ("Cannot allocate data handle for `%s'",
8463 img->spec, Qnil);
8464 goto error;
8465 }
8466
8467 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
8468 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
8469 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
8470 err = PtrToHand (&dh, &dref, sizeof (Handle));
8471 if (err == noErr)
8472 /* no file name */
8473 err = PtrAndHand ("\p", dref, 1);
8474 if (err == noErr)
8475 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
8476 if (err != noErr)
8477 {
8478 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
8479 goto error;
8480 }
8481 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8482 &movie_p, &prefer_graphic_p, 0);
8483 if (err != noErr)
8484 goto open_error;
8485
8486 if (!graphic_p && !movie_p)
8487 goto open_error;
8488 if (prefer_graphic_p)
8489 {
8490 int success_p;
8491
8492 DisposeHandle (dref);
8493 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8494 DisposeHandle (dh);
8495 return success_p;
8496 }
8497 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8498 HandleDataHandlerSubType);
8499 DisposeHandle (dref);
8500 if (err != noErr)
8501 goto open_error;
8502 }
8503
8504 image = image_spec_value (img->spec, QCindex, NULL);
8505 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8506 track = GetMovieIndTrack (movie, 1);
8507 media = GetTrackMedia (track);
8508 nsamples = GetMediaSampleCount (media);
8509 if (ino >= nsamples)
8510 {
8511 image_error ("Invalid image number `%s' in image `%s'",
8512 image, img->spec);
8513 goto error;
8514 }
8515
8516 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8517 if (!STRINGP (specified_bg) ||
8518 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8519 {
8520 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8521 color.red = RED16_FROM_ULONG (color.pixel);
8522 color.green = GREEN16_FROM_ULONG (color.pixel);
8523 color.blue = BLUE16_FROM_ULONG (color.pixel);
8524 }
8525 GetMovieBox (movie, &rect);
8526 width = img->width = rect.right - rect.left;
8527 height = img->height = rect.bottom - rect.top;
8528 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8529 goto error;
8530
8531 SetGWorld (ximg, NULL);
8532 bg_color.red = color.red;
8533 bg_color.green = color.green;
8534 bg_color.blue = color.blue;
8535 RGBBackColor (&bg_color);
8536 SetMovieActive (movie, TRUE);
8537 SetMovieGWorld (movie, ximg, NULL);
8538 SampleNumToMediaTime (media, ino + 1, &time, NULL);
8539 SetMovieTimeValue (movie, time);
8540 MoviesTask (movie, 0L);
8541 DisposeTrackMedia (media);
8542 DisposeMovieTrack (track);
8543 DisposeMovie (movie);
8544 if (dh)
8545 DisposeHandle (dh);
8546 /* Maybe fill in the background field while we have ximg handy. */
8547 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8548 IMAGE_BACKGROUND (img, f, ximg);
8549
8550 /* Put the image into the pixmap. */
8551 x_put_x_image (f, ximg, img->pixmap, width, height);
8552 x_destroy_x_image (ximg);
8553 return 1;
8554
8555 open_error:
8556 image_error ("Cannot open `%s'", file, Qnil);
8557 error:
8558 if (media)
8559 DisposeTrackMedia (media);
8560 if (track)
8561 DisposeMovieTrack (track);
8562 if (movie)
8563 DisposeMovie (movie);
8564 if (dh)
8565 DisposeHandle (dh);
8566 return 0;
8567 }
8568
8569 #else
8570
8571 #define DrawText gif_DrawText /* avoid conflict with QuickdrawText.h */
8572 #include <gif_lib.h>
8573 #undef DrawText
7279 8574
7280 /* Reading a GIF image from memory 8575 /* Reading a GIF image from memory
7281 Based on the PNG memory stuff to a certain extent. */ 8576 Based on the PNG memory stuff to a certain extent. */
7282 8577
7283 typedef struct 8578 typedef struct
7285 unsigned char *bytes; 8580 unsigned char *bytes;
7286 size_t len; 8581 size_t len;
7287 int index; 8582 int index;
7288 } 8583 }
7289 gif_memory_source; 8584 gif_memory_source;
8585
7290 8586
7291 /* Make the current memory source available to gif_read_from_memory. 8587 /* Make the current memory source available to gif_read_from_memory.
7292 It's done this way because not all versions of libungif support 8588 It's done this way because not all versions of libungif support
7293 a UserData field in the GifFileType structure. */ 8589 a UserData field in the GifFileType structure. */
7294 static gif_memory_source *current_gif_memory_src; 8590 static gif_memory_source *current_gif_memory_src;
7319 struct image *img; 8615 struct image *img;
7320 { 8616 {
7321 Lisp_Object file, specified_file; 8617 Lisp_Object file, specified_file;
7322 Lisp_Object specified_data; 8618 Lisp_Object specified_data;
7323 int rc, width, height, x, y, i; 8619 int rc, width, height, x, y, i;
7324 XImage *ximg; 8620 XImagePtr ximg;
7325 ColorMapObject *gif_color_map; 8621 ColorMapObject *gif_color_map;
7326 unsigned long pixel_colors[256]; 8622 unsigned long pixel_colors[256];
7327 GifFileType *gif; 8623 GifFileType *gif;
7328 struct gcpro gcpro1; 8624 struct gcpro gcpro1;
7329 Lisp_Object image; 8625 Lisp_Object image;
7338 8634
7339 if (NILP (specified_data)) 8635 if (NILP (specified_data))
7340 { 8636 {
7341 file = x_find_image_file (specified_file); 8637 file = x_find_image_file (specified_file);
7342 if (!STRINGP (file)) 8638 if (!STRINGP (file))
7343 { 8639 {
7344 image_error ("Cannot find image file `%s'", specified_file, Qnil); 8640 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7345 UNGCPRO; 8641 UNGCPRO;
7346 return 0; 8642 return 0;
7347 } 8643 }
7348 8644
7349 /* Open the GIF file. */ 8645 /* Open the GIF file. */
7350 gif = DGifOpenFileName (SDATA (file)); 8646 gif = DGifOpenFileName (SDATA (file));
7351 if (gif == NULL) 8647 if (gif == NULL)
7352 { 8648 {
7353 image_error ("Cannot open `%s'", file, Qnil); 8649 image_error ("Cannot open `%s'", file, Qnil);
7354 UNGCPRO; 8650 UNGCPRO;
7355 return 0; 8651 return 0;
7356 } 8652 }
7357 } 8653 }
7358 else 8654 else
7359 { 8655 {
7360 /* Read from memory! */ 8656 /* Read from memory! */
7361 current_gif_memory_src = &memsrc; 8657 current_gif_memory_src = &memsrc;
7362 memsrc.bytes = SDATA (specified_data); 8658 memsrc.bytes = SDATA (specified_data);
7363 memsrc.len = SBYTES (specified_data); 8659 memsrc.len = SBYTES (specified_data);
7364 memsrc.index = 0; 8660 memsrc.index = 0;
7365 8661
7366 gif = DGifOpen(&memsrc, gif_read_from_memory); 8662 gif = DGifOpen (&memsrc, gif_read_from_memory);
7367 if (!gif) 8663 if (!gif)
7368 { 8664 {
7369 image_error ("Cannot open memory source `%s'", img->spec, Qnil); 8665 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7370 UNGCPRO; 8666 UNGCPRO;
7371 return 0; 8667 return 0;
7385 image = image_spec_value (img->spec, QCindex, NULL); 8681 image = image_spec_value (img->spec, QCindex, NULL);
7386 ino = INTEGERP (image) ? XFASTINT (image) : 0; 8682 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7387 if (ino >= gif->ImageCount) 8683 if (ino >= gif->ImageCount)
7388 { 8684 {
7389 image_error ("Invalid image number `%s' in image `%s'", 8685 image_error ("Invalid image number `%s' in image `%s'",
7390 image, img->spec); 8686 image, img->spec);
7391 DGifCloseFile (gif); 8687 DGifCloseFile (gif);
7392 UNGCPRO; 8688 UNGCPRO;
7393 return 0; 8689 return 0;
7394 } 8690 }
7395 8691
7396 width = img->width = gif->SWidth; 8692 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
7397 height = img->height = gif->SHeight; 8693 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
7398
7399 BLOCK_INPUT;
7400 8694
7401 /* Create the X image and pixmap. */ 8695 /* Create the X image and pixmap. */
7402 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 8696 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7403 { 8697 {
7404 UNBLOCK_INPUT;
7405 DGifCloseFile (gif); 8698 DGifCloseFile (gif);
7406 UNGCPRO; 8699 UNGCPRO;
7407 return 0; 8700 return 0;
7408 } 8701 }
7409 8702
7410 /* Allocate colors. */ 8703 /* Allocate colors. */
7411 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap; 8704 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7412 if (!gif_color_map) 8705 if (!gif_color_map)
7413 gif_color_map = gif->SColorMap; 8706 gif_color_map = gif->SColorMap;
8707 #if 0 /* TODO: Color tables */
7414 init_color_table (); 8708 init_color_table ();
8709 #endif
7415 bzero (pixel_colors, sizeof pixel_colors); 8710 bzero (pixel_colors, sizeof pixel_colors);
7416 8711
7417 for (i = 0; i < gif_color_map->ColorCount; ++i) 8712 for (i = 0; i < gif_color_map->ColorCount; ++i)
7418 { 8713 {
7419 int r = gif_color_map->Colors[i].Red << 8; 8714 int r = gif_color_map->Colors[i].Red << 8;
7420 int g = gif_color_map->Colors[i].Green << 8; 8715 int g = gif_color_map->Colors[i].Green << 8;
7421 int b = gif_color_map->Colors[i].Blue << 8; 8716 int b = gif_color_map->Colors[i].Blue << 8;
7422 pixel_colors[i] = lookup_rgb_color (f, r, g, b); 8717 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7423 } 8718 }
7424 8719
8720 #if 0 /* TODO: Color tables */
7425 img->colors = colors_in_color_table (&img->ncolors); 8721 img->colors = colors_in_color_table (&img->ncolors);
7426 free_color_table (); 8722 free_color_table ();
8723 #endif
7427 8724
7428 /* Clear the part of the screen image that are not covered by 8725 /* Clear the part of the screen image that are not covered by
7429 the image from the GIF file. Full animated GIF support 8726 the image from the GIF file. Full animated GIF support
7430 requires more than can be done here (see the gif89 spec, 8727 requires more than can be done here (see the gif89 spec,
7431 disposal methods). Let's simply assume that the part 8728 disposal methods). Let's simply assume that the part
7458 8755
7459 if (gif->SavedImages[ino].ImageDesc.Interlace) 8756 if (gif->SavedImages[ino].ImageDesc.Interlace)
7460 { 8757 {
7461 static int interlace_start[] = {0, 4, 2, 1}; 8758 static int interlace_start[] = {0, 4, 2, 1};
7462 static int interlace_increment[] = {8, 8, 4, 2}; 8759 static int interlace_increment[] = {8, 8, 4, 2};
7463 int pass, inc; 8760 int pass;
7464 int row = interlace_start[0]; 8761 int row = interlace_start[0];
7465 8762
7466 pass = 0; 8763 pass = 0;
7467 8764
7468 for (y = 0; y < image_height; y++) 8765 for (y = 0; y < image_height; y++)
7487 else 8784 else
7488 { 8785 {
7489 for (y = 0; y < image_height; ++y) 8786 for (y = 0; y < image_height; ++y)
7490 for (x = 0; x < image_width; ++x) 8787 for (x = 0; x < image_width; ++x)
7491 { 8788 {
7492 int i = raster[y* image_width + x]; 8789 int i = raster[y * image_width + x];
7493 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]); 8790 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
7494 } 8791 }
7495 } 8792 }
7496 8793
7497 DGifCloseFile (gif); 8794 DGifCloseFile (gif);
8795
8796 /* Maybe fill in the background field while we have ximg handy. */
8797 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8798 IMAGE_BACKGROUND (img, f, ximg);
7498 8799
7499 /* Put the image into the pixmap, then free the X image and its buffer. */ 8800 /* Put the image into the pixmap, then free the X image and its buffer. */
7500 x_put_x_image (f, ximg, img->pixmap, width, height); 8801 x_put_x_image (f, ximg, img->pixmap, width, height);
7501 x_destroy_x_image (ximg); 8802 x_destroy_x_image (ximg);
7502 UNBLOCK_INPUT;
7503 8803
7504 UNGCPRO; 8804 UNGCPRO;
7505 return 1; 8805 return 1;
7506 } 8806 }
7507 8807 #endif /* HAVE_GIF */
7508 #endif /* HAVE_GIF != 0 */
7509 8808
7510 8809
7511 8810
7512 /*********************************************************************** 8811 /***********************************************************************
7513 Ghostscript 8812 Ghostscript
7514 ***********************************************************************/ 8813 ***********************************************************************/
7515 8814
8815 /* The symbol `postscript' identifying images of this type. */
8816
8817 Lisp_Object Qpostscript;
8818
8819 /* Keyword symbols. */
8820
8821 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8822
7516 #ifdef HAVE_GHOSTSCRIPT 8823 #ifdef HAVE_GHOSTSCRIPT
7517 static int gs_image_p P_ ((Lisp_Object object)); 8824 static int gs_image_p P_ ((Lisp_Object object));
7518 static int gs_load P_ ((struct frame *f, struct image *img)); 8825 static int gs_load P_ ((struct frame *f, struct image *img));
7519 static void gs_clear_image P_ ((struct frame *f, struct image *img)); 8826 static void gs_clear_image P_ ((struct frame *f, struct image *img));
7520
7521 /* The symbol `postscript' identifying images of this type. */
7522
7523 Lisp_Object Qpostscript;
7524
7525 /* Keyword symbols. */
7526
7527 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
7528 8827
7529 /* Indices of image specification fields in gs_format, below. */ 8828 /* Indices of image specification fields in gs_format, below. */
7530 8829
7531 enum gs_keyword_index 8830 enum gs_keyword_index
7532 { 8831 {
7539 GS_ASCENT, 8838 GS_ASCENT,
7540 GS_MARGIN, 8839 GS_MARGIN,
7541 GS_RELIEF, 8840 GS_RELIEF,
7542 GS_ALGORITHM, 8841 GS_ALGORITHM,
7543 GS_HEURISTIC_MASK, 8842 GS_HEURISTIC_MASK,
8843 GS_MASK,
8844 GS_BACKGROUND,
7544 GS_LAST 8845 GS_LAST
7545 }; 8846 };
7546 8847
7547 /* Vector of image_keyword structures describing the format 8848 /* Vector of image_keyword structures describing the format
7548 of valid user-defined image specifications. */ 8849 of valid user-defined image specifications. */
7553 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1}, 8854 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7554 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1}, 8855 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7555 {":file", IMAGE_STRING_VALUE, 1}, 8856 {":file", IMAGE_STRING_VALUE, 1},
7556 {":loader", IMAGE_FUNCTION_VALUE, 0}, 8857 {":loader", IMAGE_FUNCTION_VALUE, 0},
7557 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1}, 8858 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
7558 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 8859 {":ascent", IMAGE_ASCENT_VALUE, 0},
7559 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, 8860 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7560 {":relief", IMAGE_INTEGER_VALUE, 0}, 8861 {":relief", IMAGE_INTEGER_VALUE, 0},
7561 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, 8862 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7562 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 8863 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8864 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8865 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7563 }; 8866 };
7564 8867
7565 /* Structure describing the image type `ghostscript'. */ 8868 /* Structure describing the image type `ghostscript'. */
7566 8869
7567 static struct image_type gs_type = 8870 static struct image_type gs_type =
7598 Lisp_Object tem; 8901 Lisp_Object tem;
7599 int i; 8902 int i;
7600 8903
7601 bcopy (gs_format, fmt, sizeof fmt); 8904 bcopy (gs_format, fmt, sizeof fmt);
7602 8905
7603 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript) 8906 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
7604 || (fmt[GS_ASCENT].count
7605 && XFASTINT (fmt[GS_ASCENT].value) > 100))
7606 return 0; 8907 return 0;
7607 8908
7608 /* Bounding box must be a list or vector containing 4 integers. */ 8909 /* Bounding box must be a list or vector containing 4 integers. */
7609 tem = fmt[GS_BOUNDING_BOX].value; 8910 tem = fmt[GS_BOUNDING_BOX].value;
7610 if (CONSP (tem)) 8911 if (CONSP (tem))
7649 image specification. Sizes in the specification are in pt. 1 pt 8950 image specification. Sizes in the specification are in pt. 1 pt
7650 = 1/72 in, xdpi and ydpi are stored in the frame's X display 8951 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7651 info. */ 8952 info. */
7652 pt_width = image_spec_value (img->spec, QCpt_width, NULL); 8953 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
7653 in_width = XFASTINT (pt_width) / 72.0; 8954 in_width = XFASTINT (pt_width) / 72.0;
7654 img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx; 8955 img->width = in_width * FRAME_MAC_DISPLAY_INFO (f)->resx;
7655 pt_height = image_spec_value (img->spec, QCpt_height, NULL); 8956 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
7656 in_height = XFASTINT (pt_height) / 72.0; 8957 in_height = XFASTINT (pt_height) / 72.0;
7657 img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy; 8958 img->height = in_height * FRAME_MAC_DISPLAY_INFO (f)->resy;
7658 8959
7659 /* Create the pixmap. */ 8960 /* Create the pixmap. */
7660 BLOCK_INPUT; 8961 xassert (img->pixmap == NULL);
7661 xassert (img->pixmap == 0); 8962 img->pixmap = XCreatePixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
7662 img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
7663 img->width, img->height, 8963 img->width, img->height,
7664 DefaultDepthOfScreen (FRAME_X_SCREEN (f))); 8964 one_mac_display_info.n_planes);
7665 UNBLOCK_INPUT;
7666 8965
7667 if (!img->pixmap) 8966 if (!img->pixmap)
7668 { 8967 {
7669 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil); 8968 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
7670 return 0; 8969 return 0;
7675 other places in redisplay like calling window scroll functions 8974 other places in redisplay like calling window scroll functions
7676 don't either. Let the Lisp loader use `unwind-protect' instead. */ 8975 don't either. Let the Lisp loader use `unwind-protect' instead. */
7677 GCPRO2 (window_and_pixmap_id, pixel_colors); 8976 GCPRO2 (window_and_pixmap_id, pixel_colors);
7678 8977
7679 sprintf (buffer, "%lu %lu", 8978 sprintf (buffer, "%lu %lu",
7680 (unsigned long) FRAME_W32_WINDOW (f), 8979 (unsigned long) FRAME_MAC_WINDOW (f),
7681 (unsigned long) img->pixmap); 8980 (unsigned long) img->pixmap);
7682 window_and_pixmap_id = build_string (buffer); 8981 window_and_pixmap_id = build_string (buffer);
7683 8982
7684 sprintf (buffer, "%lu %lu", 8983 sprintf (buffer, "%lu %lu",
7685 FRAME_FOREGROUND_PIXEL (f), 8984 FRAME_FOREGROUND_PIXEL (f),
7717 /* Find the image containing PIXMAP. */ 9016 /* Find the image containing PIXMAP. */
7718 for (i = 0; i < c->used; ++i) 9017 for (i = 0; i < c->used; ++i)
7719 if (c->images[i]->pixmap == pixmap) 9018 if (c->images[i]->pixmap == pixmap)
7720 break; 9019 break;
7721 9020
9021 /* Should someone in between have cleared the image cache, for
9022 instance, give up. */
9023 if (i == c->used)
9024 return;
9025
7722 /* Kill the GS process. We should have found PIXMAP in the image 9026 /* Kill the GS process. We should have found PIXMAP in the image
7723 cache and its image should contain a process object. */ 9027 cache and its image should contain a process object. */
7724 xassert (i < c->used);
7725 img = c->images[i]; 9028 img = c->images[i];
7726 xassert (PROCESSP (img->data.lisp_val)); 9029 xassert (PROCESSP (img->data.lisp_val));
7727 Fkill_process (img->data.lisp_val, Qnil); 9030 Fkill_process (img->data.lisp_val, Qnil);
7728 img->data.lisp_val = Qnil; 9031 img->data.lisp_val = Qnil;
7729 9032
9033 #if 0
7730 /* On displays with a mutable colormap, figure out the colors 9034 /* On displays with a mutable colormap, figure out the colors
7731 allocated for the image by looking at the pixels of an XImage for 9035 allocated for the image by looking at the pixels of an XImage for
7732 img->pixmap. */ 9036 img->pixmap. */
7733 class = FRAME_W32_DISPLAY_INFO (f)->visual->class; 9037 class = FRAME_MAC_DISPLAY_INFO (f)->visual->class;
7734 if (class != StaticColor && class != StaticGray && class != TrueColor) 9038 if (class != StaticColor && class != StaticGray && class != TrueColor)
7735 { 9039 {
7736 XImage *ximg; 9040 XImagePtr ximg;
7737 9041
7738 BLOCK_INPUT; 9042 BLOCK_INPUT;
7739 9043
7740 /* Try to get an XImage for img->pixmep. */ 9044 /* Try to get an XImage for img->pixmep. */
7741 ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap, 9045 ximg = XGetImage (FRAME_MAC_DISPLAY (f), img->pixmap,
7742 0, 0, img->width, img->height, ~0, ZPixmap); 9046 0, 0, img->width, img->height, ~0, ZPixmap);
7743 if (ximg) 9047 if (ximg)
7744 { 9048 {
7745 int x, y; 9049 int x, y;
7746 9050
7767 freeing the colors. */ 9071 freeing the colors. */
7768 /* We have allocated colors once, but Ghostscript has also 9072 /* We have allocated colors once, but Ghostscript has also
7769 allocated colors on behalf of us. So, to get the 9073 allocated colors on behalf of us. So, to get the
7770 reference counts right, free them once. */ 9074 reference counts right, free them once. */
7771 if (img->ncolors) 9075 if (img->ncolors)
7772 { 9076 x_free_colors (f, img->colors, img->ncolors);
7773 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
7774 XFreeColors (FRAME_W32_DISPLAY (f), cmap,
7775 img->colors, img->ncolors, 0);
7776 }
7777 #endif 9077 #endif
7778 } 9078 }
7779 else 9079 else
7780 image_error ("Cannot get X image of `%s'; colors will not be freed", 9080 image_error ("Cannot get X image of `%s'; colors will not be freed",
7781 img->spec, Qnil); 9081 img->spec, Qnil);
7782 9082
7783 UNBLOCK_INPUT; 9083 UNBLOCK_INPUT;
7784 } 9084 }
9085 #endif
9086
9087 /* Now that we have the pixmap, compute mask and transform the
9088 image if requested. */
9089 BLOCK_INPUT;
9090 postprocess_image (f, img);
9091 UNBLOCK_INPUT;
7785 } 9092 }
7786 9093
7787 #endif /* HAVE_GHOSTSCRIPT */ 9094 #endif /* HAVE_GHOSTSCRIPT */
7788 9095
7789 9096
8804 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky); 10111 = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
8805 10112
8806 10113
8807 Qlaplace = intern ("laplace"); 10114 Qlaplace = intern ("laplace");
8808 staticpro (&Qlaplace); 10115 staticpro (&Qlaplace);
10116 Qemboss = intern ("emboss");
10117 staticpro (&Qemboss);
10118 Qedge_detection = intern ("edge-detection");
10119 staticpro (&Qedge_detection);
10120 Qheuristic = intern ("heuristic");
10121 staticpro (&Qheuristic);
10122 QCmatrix = intern (":matrix");
10123 staticpro (&QCmatrix);
10124 QCcolor_adjustment = intern (":color-adjustment");
10125 staticpro (&QCcolor_adjustment);
10126 QCmask = intern (":mask");
10127 staticpro (&QCmask);
8809 10128
8810 Qface_set_after_frame_default = intern ("face-set-after-frame-default"); 10129 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
8811 staticpro (&Qface_set_after_frame_default); 10130 staticpro (&Qface_set_after_frame_default);
8812 10131
8813 Fput (Qundefined_color, Qerror_conditions, 10132 Fput (Qundefined_color, Qerror_conditions,
8814 Fcons (Qundefined_color, Fcons (Qerror, Qnil))); 10133 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
8815 Fput (Qundefined_color, Qerror_message, 10134 Fput (Qundefined_color, Qerror_message,
8816 build_string ("Undefined color")); 10135 build_string ("Undefined color"));
10136
10137 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
10138 doc: /* Non-nil means always draw a cross over disabled images.
10139 Disabled images are those having an `:conversion disabled' property.
10140 A cross is always drawn on black & white displays. */);
10141 cross_disabled_images = 0;
8817 10142
8818 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path, 10143 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8819 doc: /* List of directories to search for window system bitmap files. */); 10144 doc: /* List of directories to search for window system bitmap files. */);
8820 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH"); 10145 Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
8821 10146
8878 When an image has not been displayed this many seconds, remove it 10203 When an image has not been displayed this many seconds, remove it
8879 from the image cache. Value must be an integer or nil with nil 10204 from the image cache. Value must be an integer or nil with nil
8880 meaning don't clear the cache. */); 10205 meaning don't clear the cache. */);
8881 Vimage_cache_eviction_delay = make_number (30 * 60); 10206 Vimage_cache_eviction_delay = make_number (30 * 60);
8882 10207
10208 /* X window properties. */
8883 defsubr (&Sx_change_window_property); 10209 defsubr (&Sx_change_window_property);
8884 defsubr (&Sx_delete_window_property); 10210 defsubr (&Sx_delete_window_property);
8885 defsubr (&Sx_window_property); 10211 defsubr (&Sx_window_property);
10212
8886 defsubr (&Sxw_display_color_p); 10213 defsubr (&Sxw_display_color_p);
8887 defsubr (&Sx_display_grayscale_p); 10214 defsubr (&Sx_display_grayscale_p);
8888 defsubr (&Sxw_color_defined_p); 10215 defsubr (&Sxw_color_defined_p);
8889 defsubr (&Sxw_color_values); 10216 defsubr (&Sxw_color_values);
8890 defsubr (&Sx_server_max_request_size); 10217 defsubr (&Sx_server_max_request_size);
8917 #endif 10244 #endif
8918 10245
8919 load_font_func = x_load_font; 10246 load_font_func = x_load_font;
8920 find_ccl_program_func = x_find_ccl_program; 10247 find_ccl_program_func = x_find_ccl_program;
8921 query_font_func = x_query_font; 10248 query_font_func = x_query_font;
8922
8923 set_frame_fontset_func = x_set_font; 10249 set_frame_fontset_func = x_set_font;
8924 check_window_system_func = check_mac; 10250 check_window_system_func = check_mac;
8925 10251
8926 #if 0 /* MAC_TODO: Image support for Mac Images. */ 10252 /* Images. */
8927 Qxbm = intern ("xbm"); 10253 Qxbm = intern ("xbm");
8928 staticpro (&Qxbm); 10254 staticpro (&Qxbm);
8929 QCtype = intern (":type");
8930 staticpro (&QCtype);
8931 QCconversion = intern (":conversion"); 10255 QCconversion = intern (":conversion");
8932 staticpro (&QCconversion); 10256 staticpro (&QCconversion);
8933 QCheuristic_mask = intern (":heuristic-mask"); 10257 QCheuristic_mask = intern (":heuristic-mask");
8934 staticpro (&QCheuristic_mask); 10258 staticpro (&QCheuristic_mask);
8935 QCcolor_symbols = intern (":color-symbols"); 10259 QCcolor_symbols = intern (":color-symbols");
8958 #if HAVE_XPM 10282 #if HAVE_XPM
8959 Qxpm = intern ("xpm"); 10283 Qxpm = intern ("xpm");
8960 staticpro (&Qxpm); 10284 staticpro (&Qxpm);
8961 #endif 10285 #endif
8962 10286
8963 #if HAVE_JPEG
8964 Qjpeg = intern ("jpeg"); 10287 Qjpeg = intern ("jpeg");
8965 staticpro (&Qjpeg); 10288 staticpro (&Qjpeg);
8966 #endif 10289
8967
8968 #if HAVE_TIFF
8969 Qtiff = intern ("tiff"); 10290 Qtiff = intern ("tiff");
8970 staticpro (&Qtiff); 10291 staticpro (&Qtiff);
8971 #endif 10292
8972
8973 #if HAVE_GIF
8974 Qgif = intern ("gif"); 10293 Qgif = intern ("gif");
8975 staticpro (&Qgif); 10294 staticpro (&Qgif);
8976 #endif 10295
8977
8978 #if HAVE_PNG
8979 Qpng = intern ("png"); 10296 Qpng = intern ("png");
8980 staticpro (&Qpng); 10297 staticpro (&Qpng);
8981 #endif
8982 10298
8983 defsubr (&Sclear_image_cache); 10299 defsubr (&Sclear_image_cache);
10300 defsubr (&Simage_size);
10301 defsubr (&Simage_mask_p);
8984 10302
8985 #if GLYPH_DEBUG 10303 #if GLYPH_DEBUG
8986 defsubr (&Simagep); 10304 defsubr (&Simagep);
8987 defsubr (&Slookup_image); 10305 defsubr (&Slookup_image);
8988 #endif 10306 #endif
8989 #endif /* MAC_TODO */
8990 10307
8991 hourglass_atimer = NULL; 10308 hourglass_atimer = NULL;
8992 hourglass_shown_p = 0; 10309 hourglass_shown_p = 0;
8993 10310
8994 defsubr (&Sx_show_tip); 10311 defsubr (&Sx_show_tip);
8995 defsubr (&Sx_hide_tip); 10312 defsubr (&Sx_hide_tip);
10313 tip_timer = Qnil;
8996 staticpro (&tip_timer); 10314 staticpro (&tip_timer);
8997 tip_timer = Qnil; 10315 tip_frame = Qnil;
10316 staticpro (&tip_frame);
8998 10317
8999 #if 0 /* MAC_TODO */ 10318 #if 0 /* MAC_TODO */
9000 defsubr (&Sx_file_dialog); 10319 defsubr (&Sx_file_dialog);
9001 #endif 10320 #endif
9002 } 10321 }
9007 { 10326 {
9008 image_types = NULL; 10327 image_types = NULL;
9009 Vimage_types = Qnil; 10328 Vimage_types = Qnil;
9010 10329
9011 define_image_type (&xbm_type); 10330 define_image_type (&xbm_type);
9012 #if 0 /* NTEMACS_TODO : Image support for W32 */ 10331 #if HAVE_GHOSTSCRIPT
9013 define_image_type (&gs_type); 10332 define_image_type (&gs_type);
10333 #endif
9014 define_image_type (&pbm_type); 10334 define_image_type (&pbm_type);
9015 10335
9016 #if HAVE_XPM 10336 #if HAVE_XPM
9017 define_image_type (&xpm_type); 10337 define_image_type (&xpm_type);
9018 #endif 10338 #endif
9019 10339
9020 #if HAVE_JPEG
9021 define_image_type (&jpeg_type); 10340 define_image_type (&jpeg_type);
10341 define_image_type (&tiff_type);
10342 define_image_type (&gif_type);
10343 define_image_type (&png_type);
10344
10345 /* Animated gifs use QuickTime Movie Toolbox. So initialize it
10346 here. */
10347 EnterMovies ();
10348 #ifdef MAC_OSX
10349 init_image_func_pointer ();
9022 #endif 10350 #endif
9023
9024 #if HAVE_TIFF
9025 define_image_type (&tiff_type);
9026 #endif
9027
9028 #if HAVE_GIF
9029 define_image_type (&gif_type);
9030 #endif
9031
9032 #if HAVE_PNG
9033 define_image_type (&png_type);
9034 #endif
9035 #endif /* NTEMACS_TODO */
9036 } 10351 }
9037 10352
9038 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc 10353 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc
9039 (do not change this comment) */ 10354 (do not change this comment) */