Mercurial > emacs
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) */ |