diff options
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 790 |
1 files changed, 694 insertions, 96 deletions
diff --git a/src/image.c b/src/image.c index 34db5e53367..438e132807f 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 23 | #include <signal.h> | 23 | #include <signal.h> |
| 24 | #include <stdio.h> | 24 | #include <stdio.h> |
| 25 | #include <math.h> | 25 | #include <math.h> |
| 26 | #include <ctype.h> | ||
| 26 | 27 | ||
| 27 | #ifdef HAVE_UNISTD_H | 28 | #ifdef HAVE_UNISTD_H |
| 28 | #include <unistd.h> | 29 | #include <unistd.h> |
| @@ -51,7 +52,6 @@ Boston, MA 02111-1307, USA. */ | |||
| 51 | typedef struct x_bitmap_record Bitmap_Record; | 52 | typedef struct x_bitmap_record Bitmap_Record; |
| 52 | #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) | 53 | #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) |
| 53 | #define NO_PIXMAP None | 54 | #define NO_PIXMAP None |
| 54 | #define PNG_BG_COLOR_SHIFT 0 | ||
| 55 | 55 | ||
| 56 | #define RGB_PIXEL_COLOR unsigned long | 56 | #define RGB_PIXEL_COLOR unsigned long |
| 57 | 57 | ||
| @@ -69,7 +69,6 @@ typedef struct x_bitmap_record Bitmap_Record; | |||
| 69 | typedef struct w32_bitmap_record Bitmap_Record; | 69 | typedef struct w32_bitmap_record Bitmap_Record; |
| 70 | #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y) | 70 | #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y) |
| 71 | #define NO_PIXMAP 0 | 71 | #define NO_PIXMAP 0 |
| 72 | #define PNG_BG_COLOR_SHIFT 0 | ||
| 73 | 72 | ||
| 74 | #define RGB_PIXEL_COLOR COLORREF | 73 | #define RGB_PIXEL_COLOR COLORREF |
| 75 | 74 | ||
| @@ -104,7 +103,6 @@ typedef struct mac_bitmap_record Bitmap_Record; | |||
| 104 | 103 | ||
| 105 | #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) | 104 | #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) |
| 106 | #define NO_PIXMAP 0 | 105 | #define NO_PIXMAP 0 |
| 107 | #define PNG_BG_COLOR_SHIFT 8 | ||
| 108 | 106 | ||
| 109 | #define RGB_PIXEL_COLOR unsigned long | 107 | #define RGB_PIXEL_COLOR unsigned long |
| 110 | 108 | ||
| @@ -177,14 +175,19 @@ XPutPixel (ximage, x, y, pixel) | |||
| 177 | int x, y; | 175 | int x, y; |
| 178 | unsigned long pixel; | 176 | unsigned long pixel; |
| 179 | { | 177 | { |
| 178 | CGrafPtr old_port; | ||
| 179 | GDHandle old_gdh; | ||
| 180 | RGBColor color; | 180 | RGBColor color; |
| 181 | 181 | ||
| 182 | GetGWorld (&old_port, &old_gdh); | ||
| 182 | SetGWorld (ximage, NULL); | 183 | SetGWorld (ximage, NULL); |
| 183 | 184 | ||
| 184 | color.red = RED16_FROM_ULONG (pixel); | 185 | color.red = RED16_FROM_ULONG (pixel); |
| 185 | color.green = GREEN16_FROM_ULONG (pixel); | 186 | color.green = GREEN16_FROM_ULONG (pixel); |
| 186 | color.blue = BLUE16_FROM_ULONG (pixel); | 187 | color.blue = BLUE16_FROM_ULONG (pixel); |
| 187 | SetCPixel (x, y, &color); | 188 | SetCPixel (x, y, &color); |
| 189 | |||
| 190 | SetGWorld (old_port, old_gdh); | ||
| 188 | } | 191 | } |
| 189 | 192 | ||
| 190 | static unsigned long | 193 | static unsigned long |
| @@ -192,11 +195,16 @@ XGetPixel (ximage, x, y) | |||
| 192 | XImagePtr ximage; | 195 | XImagePtr ximage; |
| 193 | int x, y; | 196 | int x, y; |
| 194 | { | 197 | { |
| 198 | CGrafPtr old_port; | ||
| 199 | GDHandle old_gdh; | ||
| 195 | RGBColor color; | 200 | RGBColor color; |
| 196 | 201 | ||
| 202 | GetGWorld (&old_port, &old_gdh); | ||
| 197 | SetGWorld (ximage, NULL); | 203 | SetGWorld (ximage, NULL); |
| 198 | 204 | ||
| 199 | GetCPixel (x, y, &color); | 205 | GetCPixel (x, y, &color); |
| 206 | |||
| 207 | SetGWorld (old_port, old_gdh); | ||
| 200 | return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8); | 208 | return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8); |
| 201 | } | 209 | } |
| 202 | 210 | ||
| @@ -206,7 +214,7 @@ XDestroyImage (ximg) | |||
| 206 | { | 214 | { |
| 207 | UnlockPixels (GetGWorldPixMap (ximg)); | 215 | UnlockPixels (GetGWorldPixMap (ximg)); |
| 208 | } | 216 | } |
| 209 | #endif | 217 | #endif /* MAC_OS */ |
| 210 | 218 | ||
| 211 | 219 | ||
| 212 | /* Functions to access the contents of a bitmap, given an id. */ | 220 | /* Functions to access the contents of a bitmap, given an id. */ |
| @@ -598,6 +606,14 @@ x_create_bitmap_mask (f, id) | |||
| 598 | 606 | ||
| 599 | static struct image_type *image_types; | 607 | static struct image_type *image_types; |
| 600 | 608 | ||
| 609 | /* A list of symbols, one for each supported image type. */ | ||
| 610 | |||
| 611 | Lisp_Object Vimage_types; | ||
| 612 | |||
| 613 | /* Cache for delayed-loading image types. */ | ||
| 614 | |||
| 615 | static Lisp_Object Vimage_type_cache; | ||
| 616 | |||
| 601 | /* The symbol `xbm' which is used as the type symbol for XBM images. */ | 617 | /* The symbol `xbm' which is used as the type symbol for XBM images. */ |
| 602 | 618 | ||
| 603 | Lisp_Object Qxbm; | 619 | Lisp_Object Qxbm; |
| @@ -622,7 +638,7 @@ Lisp_Object Vimage_cache_eviction_delay; | |||
| 622 | 638 | ||
| 623 | /* Function prototypes. */ | 639 | /* Function prototypes. */ |
| 624 | 640 | ||
| 625 | static void define_image_type P_ ((struct image_type *type)); | 641 | static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded)); |
| 626 | static struct image_type *lookup_image_type P_ ((Lisp_Object symbol)); | 642 | static struct image_type *lookup_image_type P_ ((Lisp_Object symbol)); |
| 627 | static void image_error P_ ((char *format, Lisp_Object, Lisp_Object)); | 643 | static void image_error P_ ((char *format, Lisp_Object, Lisp_Object)); |
| 628 | static void x_laplace P_ ((struct frame *, struct image *)); | 644 | static void x_laplace P_ ((struct frame *, struct image *)); |
| @@ -630,21 +646,37 @@ static void x_emboss P_ ((struct frame *, struct image *)); | |||
| 630 | static int x_build_heuristic_mask P_ ((struct frame *, struct image *, | 646 | static int x_build_heuristic_mask P_ ((struct frame *, struct image *, |
| 631 | Lisp_Object)); | 647 | Lisp_Object)); |
| 632 | 648 | ||
| 649 | #define CACHE_IMAGE_TYPE(type, status) \ | ||
| 650 | do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0) | ||
| 651 | |||
| 652 | #define ADD_IMAGE_TYPE(type) \ | ||
| 653 | do { Vimage_types = Fcons (type, Vimage_types); } while (0) | ||
| 633 | 654 | ||
| 634 | /* Define a new image type from TYPE. This adds a copy of TYPE to | 655 | /* Define a new image type from TYPE. This adds a copy of TYPE to |
| 635 | image_types and adds the symbol *TYPE->type to Vimage_types. */ | 656 | image_types and caches the loading status of TYPE. */ |
| 636 | 657 | ||
| 637 | static void | 658 | static Lisp_Object |
| 638 | define_image_type (type) | 659 | define_image_type (type, loaded) |
| 639 | struct image_type *type; | 660 | struct image_type *type; |
| 661 | int loaded; | ||
| 640 | { | 662 | { |
| 641 | /* Make a copy of TYPE to avoid a bus error in a dumped Emacs. | 663 | Lisp_Object success; |
| 642 | The initialized data segment is read-only. */ | 664 | |
| 643 | struct image_type *p = (struct image_type *) xmalloc (sizeof *p); | 665 | if (!loaded) |
| 644 | bcopy (type, p, sizeof *p); | 666 | success = Qnil; |
| 645 | p->next = image_types; | 667 | else |
| 646 | image_types = p; | 668 | { |
| 647 | Vimage_types = Fcons (*p->type, Vimage_types); | 669 | /* Make a copy of TYPE to avoid a bus error in a dumped Emacs. |
| 670 | The initialized data segment is read-only. */ | ||
| 671 | struct image_type *p = (struct image_type *) xmalloc (sizeof *p); | ||
| 672 | bcopy (type, p, sizeof *p); | ||
| 673 | p->next = image_types; | ||
| 674 | image_types = p; | ||
| 675 | success = Qt; | ||
| 676 | } | ||
| 677 | |||
| 678 | CACHE_IMAGE_TYPE(*type->type, success); | ||
| 679 | return success; | ||
| 648 | } | 680 | } |
| 649 | 681 | ||
| 650 | 682 | ||
| @@ -657,6 +689,10 @@ lookup_image_type (symbol) | |||
| 657 | { | 689 | { |
| 658 | struct image_type *type; | 690 | struct image_type *type; |
| 659 | 691 | ||
| 692 | /* We must initialize the image-type if it hasn't been already. */ | ||
| 693 | if (NILP (Finit_image_library (symbol))) | ||
| 694 | return 0; /* unimplemented */ | ||
| 695 | |||
| 660 | for (type = image_types; type; type = type->next) | 696 | for (type = image_types; type; type = type->next) |
| 661 | if (EQ (symbol, *type->type)) | 697 | if (EQ (symbol, *type->type)) |
| 662 | break; | 698 | break; |
| @@ -1079,13 +1115,21 @@ prepare_image_for_display (f, img) | |||
| 1079 | drawn in face FACE. */ | 1115 | drawn in face FACE. */ |
| 1080 | 1116 | ||
| 1081 | int | 1117 | int |
| 1082 | image_ascent (img, face) | 1118 | image_ascent (img, face, slice) |
| 1083 | struct image *img; | 1119 | struct image *img; |
| 1084 | struct face *face; | 1120 | struct face *face; |
| 1121 | struct glyph_slice *slice; | ||
| 1085 | { | 1122 | { |
| 1086 | int height = img->height + img->vmargin; | 1123 | int height; |
| 1087 | int ascent; | 1124 | int ascent; |
| 1088 | 1125 | ||
| 1126 | if (slice->height == img->height) | ||
| 1127 | height = img->height + img->vmargin; | ||
| 1128 | else if (slice->y == 0) | ||
| 1129 | height = slice->height + img->vmargin; | ||
| 1130 | else | ||
| 1131 | height = slice->height; | ||
| 1132 | |||
| 1089 | if (img->ascent == CENTERED_IMAGE_ASCENT) | 1133 | if (img->ascent == CENTERED_IMAGE_ASCENT) |
| 1090 | { | 1134 | { |
| 1091 | if (face->font) | 1135 | if (face->font) |
| @@ -1172,7 +1216,7 @@ four_corners_best (ximg, width, height) | |||
| 1172 | /* Return the `background' field of IMG. If IMG doesn't have one yet, | 1216 | /* Return the `background' field of IMG. If IMG doesn't have one yet, |
| 1173 | it is guessed heuristically. If non-zero, XIMG is an existing | 1217 | it is guessed heuristically. If non-zero, XIMG is an existing |
| 1174 | XImage object (or device context with the image selected on W32) to | 1218 | XImage object (or device context with the image selected on W32) to |
| 1175 | use for the heuristic. */ | 1219 | use for the heuristic. */ |
| 1176 | 1220 | ||
| 1177 | RGB_PIXEL_COLOR | 1221 | RGB_PIXEL_COLOR |
| 1178 | image_background (img, f, ximg) | 1222 | image_background (img, f, ximg) |
| @@ -1205,7 +1249,7 @@ image_background (img, f, ximg) | |||
| 1205 | 1249 | ||
| 1206 | if (free_ximg) | 1250 | if (free_ximg) |
| 1207 | Destroy_Image (ximg, prev); | 1251 | Destroy_Image (ximg, prev); |
| 1208 | 1252 | ||
| 1209 | img->background_valid = 1; | 1253 | img->background_valid = 1; |
| 1210 | } | 1254 | } |
| 1211 | 1255 | ||
| @@ -1581,6 +1625,11 @@ lookup_image (f, spec) | |||
| 1581 | Lisp_Object spec; | 1625 | Lisp_Object spec; |
| 1582 | { | 1626 | { |
| 1583 | struct image_cache *c = FRAME_X_IMAGE_CACHE (f); | 1627 | struct image_cache *c = FRAME_X_IMAGE_CACHE (f); |
| 1628 | #ifdef _MSC_VER | ||
| 1629 | /* Work around a problem with MinGW builds of graphics libraries | ||
| 1630 | not honoring calling conventions. */ | ||
| 1631 | static | ||
| 1632 | #endif | ||
| 1584 | struct image *img; | 1633 | struct image *img; |
| 1585 | int i; | 1634 | int i; |
| 1586 | unsigned hash; | 1635 | unsigned hash; |
| @@ -1768,6 +1817,33 @@ forall_images_in_image_cache (f, fn) | |||
| 1768 | if (!fn_##func) return 0; \ | 1817 | if (!fn_##func) return 0; \ |
| 1769 | } | 1818 | } |
| 1770 | 1819 | ||
| 1820 | /* Load a DLL implementing an image type. | ||
| 1821 | The `image-library-alist' variable associates a symbol, | ||
| 1822 | identifying an image type, to a list of possible filenames. | ||
| 1823 | The function returns NULL if no library could be loaded for | ||
| 1824 | the given image type, or if the library was previously loaded; | ||
| 1825 | else the handle of the DLL. */ | ||
| 1826 | static HMODULE | ||
| 1827 | w32_delayed_load (Lisp_Object libraries, Lisp_Object type) | ||
| 1828 | { | ||
| 1829 | HMODULE library = NULL; | ||
| 1830 | |||
| 1831 | if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache))) | ||
| 1832 | { | ||
| 1833 | Lisp_Object dlls = Fassq (type, libraries); | ||
| 1834 | |||
| 1835 | if (CONSP (dlls)) | ||
| 1836 | for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls)) | ||
| 1837 | { | ||
| 1838 | CHECK_STRING_CAR (dlls); | ||
| 1839 | if (library = LoadLibrary (SDATA (XCAR (dlls)))) | ||
| 1840 | break; | ||
| 1841 | } | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | return library; | ||
| 1845 | } | ||
| 1846 | |||
| 1771 | #endif /* HAVE_NTGUI */ | 1847 | #endif /* HAVE_NTGUI */ |
| 1772 | 1848 | ||
| 1773 | static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int, | 1849 | static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int, |
| @@ -2191,6 +2267,10 @@ image_load_qt_1 (f, img, type, fss, dh) | |||
| 2191 | goto error; | 2267 | goto error; |
| 2192 | if (draw_all_pixels != graphicsImporterDrawsAllPixels) | 2268 | if (draw_all_pixels != graphicsImporterDrawsAllPixels) |
| 2193 | { | 2269 | { |
| 2270 | CGrafPtr old_port; | ||
| 2271 | GDHandle old_gdh; | ||
| 2272 | |||
| 2273 | GetGWorld (&old_port, &old_gdh); | ||
| 2194 | SetGWorld (ximg, NULL); | 2274 | SetGWorld (ximg, NULL); |
| 2195 | bg_color.red = color.red; | 2275 | bg_color.red = color.red; |
| 2196 | bg_color.green = color.green; | 2276 | bg_color.green = color.green; |
| @@ -2202,6 +2282,7 @@ image_load_qt_1 (f, img, type, fss, dh) | |||
| 2202 | #else | 2282 | #else |
| 2203 | EraseRect (&(ximg->portRect)); | 2283 | EraseRect (&(ximg->portRect)); |
| 2204 | #endif | 2284 | #endif |
| 2285 | SetGWorld (old_port, old_gdh); | ||
| 2205 | } | 2286 | } |
| 2206 | GraphicsImportSetGWorld (gi, ximg, NULL); | 2287 | GraphicsImportSetGWorld (gi, ximg, NULL); |
| 2207 | GraphicsImportDraw (gi); | 2288 | GraphicsImportDraw (gi); |
| @@ -2990,7 +3071,7 @@ xbm_load_image (f, img, contents, end) | |||
| 2990 | non_default_colors = 1; | 3071 | non_default_colors = 1; |
| 2991 | } | 3072 | } |
| 2992 | 3073 | ||
| 2993 | Create_Pixmap_From_Bitmap_Data (f, img, data, | 3074 | Create_Pixmap_From_Bitmap_Data (f, img, data, |
| 2994 | foreground, background, | 3075 | foreground, background, |
| 2995 | non_default_colors); | 3076 | non_default_colors); |
| 2996 | xfree (data); | 3077 | xfree (data); |
| @@ -3164,28 +3245,36 @@ xbm_load (f, img) | |||
| 3164 | XPM images | 3245 | XPM images |
| 3165 | ***********************************************************************/ | 3246 | ***********************************************************************/ |
| 3166 | 3247 | ||
| 3167 | #ifdef HAVE_XPM | 3248 | #if defined (HAVE_XPM) || defined (MAC_OS) |
| 3168 | 3249 | ||
| 3169 | static int xpm_image_p P_ ((Lisp_Object object)); | 3250 | static int xpm_image_p P_ ((Lisp_Object object)); |
| 3170 | static int xpm_load P_ ((struct frame *f, struct image *img)); | 3251 | static int xpm_load P_ ((struct frame *f, struct image *img)); |
| 3171 | static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); | 3252 | static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); |
| 3172 | 3253 | ||
| 3254 | #endif /* HAVE_XPM || MAC_OS */ | ||
| 3255 | |||
| 3256 | #ifdef HAVE_XPM | ||
| 3173 | #ifdef HAVE_NTGUI | 3257 | #ifdef HAVE_NTGUI |
| 3174 | /* Indicate to xpm.h that we don't have Xlib. */ | 3258 | /* Indicate to xpm.h that we don't have Xlib. */ |
| 3175 | #define FOR_MSW | 3259 | #define FOR_MSW |
| 3176 | /* simx.h in xpm defines XColor and XImage differently than Emacs. */ | 3260 | /* simx.h in xpm defines XColor and XImage differently than Emacs. */ |
| 3261 | /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */ | ||
| 3177 | #define XColor xpm_XColor | 3262 | #define XColor xpm_XColor |
| 3178 | #define XImage xpm_XImage | 3263 | #define XImage xpm_XImage |
| 3264 | #define Display xpm_Display | ||
| 3179 | #define PIXEL_ALREADY_TYPEDEFED | 3265 | #define PIXEL_ALREADY_TYPEDEFED |
| 3180 | #include "X11/xpm.h" | 3266 | #include "X11/xpm.h" |
| 3181 | #undef FOR_MSW | 3267 | #undef FOR_MSW |
| 3182 | #undef XColor | 3268 | #undef XColor |
| 3183 | #undef XImage | 3269 | #undef XImage |
| 3270 | #undef Display | ||
| 3184 | #undef PIXEL_ALREADY_TYPEDEFED | 3271 | #undef PIXEL_ALREADY_TYPEDEFED |
| 3185 | #else | 3272 | #else |
| 3186 | #include "X11/xpm.h" | 3273 | #include "X11/xpm.h" |
| 3187 | #endif /* HAVE_NTGUI */ | 3274 | #endif /* HAVE_NTGUI */ |
| 3275 | #endif /* HAVE_XPM */ | ||
| 3188 | 3276 | ||
| 3277 | #if defined (HAVE_XPM) || defined (MAC_OS) | ||
| 3189 | /* The symbol `xpm' identifying XPM-format images. */ | 3278 | /* The symbol `xpm' identifying XPM-format images. */ |
| 3190 | 3279 | ||
| 3191 | Lisp_Object Qxpm; | 3280 | Lisp_Object Qxpm; |
| @@ -3455,13 +3544,12 @@ DEF_IMGLIB_FN (XpmCreateImageFromBuffer); | |||
| 3455 | DEF_IMGLIB_FN (XpmReadFileToImage); | 3544 | DEF_IMGLIB_FN (XpmReadFileToImage); |
| 3456 | DEF_IMGLIB_FN (XImageFree); | 3545 | DEF_IMGLIB_FN (XImageFree); |
| 3457 | 3546 | ||
| 3458 | |||
| 3459 | static int | 3547 | static int |
| 3460 | init_xpm_functions (void) | 3548 | init_xpm_functions (Lisp_Object libraries) |
| 3461 | { | 3549 | { |
| 3462 | HMODULE library; | 3550 | HMODULE library; |
| 3463 | 3551 | ||
| 3464 | if (!(library = LoadLibrary ("libXpm.dll"))) | 3552 | if (!(library = w32_delayed_load (libraries, Qxpm))) |
| 3465 | return 0; | 3553 | return 0; |
| 3466 | 3554 | ||
| 3467 | LOAD_IMGLIB_FN (library, XpmFreeAttributes); | 3555 | LOAD_IMGLIB_FN (library, XpmFreeAttributes); |
| @@ -3513,10 +3601,13 @@ xpm_image_p (object) | |||
| 3513 | || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); | 3601 | || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); |
| 3514 | } | 3602 | } |
| 3515 | 3603 | ||
| 3604 | #endif /* HAVE_XPM || MAC_OS */ | ||
| 3516 | 3605 | ||
| 3517 | /* Load image IMG which will be displayed on frame F. Value is | 3606 | /* Load image IMG which will be displayed on frame F. Value is |
| 3518 | non-zero if successful. */ | 3607 | non-zero if successful. */ |
| 3519 | 3608 | ||
| 3609 | #ifdef HAVE_XPM | ||
| 3610 | |||
| 3520 | static int | 3611 | static int |
| 3521 | xpm_load (f, img) | 3612 | xpm_load (f, img) |
| 3522 | struct frame *f; | 3613 | struct frame *f; |
| @@ -3748,6 +3839,467 @@ xpm_load (f, img) | |||
| 3748 | 3839 | ||
| 3749 | #endif /* HAVE_XPM */ | 3840 | #endif /* HAVE_XPM */ |
| 3750 | 3841 | ||
| 3842 | #ifdef MAC_OS | ||
| 3843 | |||
| 3844 | /* XPM support functions for Mac OS where libxpm is not available. | ||
| 3845 | Only XPM version 3 (without any extensions) is supported. */ | ||
| 3846 | |||
| 3847 | static int xpm_scan P_ ((unsigned char **, unsigned char *, | ||
| 3848 | unsigned char **, int *)); | ||
| 3849 | static Lisp_Object xpm_make_color_table_v | ||
| 3850 | P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object), | ||
| 3851 | Lisp_Object (**) (Lisp_Object, unsigned char *, int))); | ||
| 3852 | static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *, | ||
| 3853 | int, Lisp_Object)); | ||
| 3854 | static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object, | ||
| 3855 | unsigned char *, int)); | ||
| 3856 | static Lisp_Object xpm_make_color_table_h | ||
| 3857 | P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object), | ||
| 3858 | Lisp_Object (**) (Lisp_Object, unsigned char *, int))); | ||
| 3859 | static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *, | ||
| 3860 | int, Lisp_Object)); | ||
| 3861 | static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object, | ||
| 3862 | unsigned char *, int)); | ||
| 3863 | static int xpm_str_to_color_key P_ ((char *)); | ||
| 3864 | static int xpm_load_image P_ ((struct frame *, struct image *, | ||
| 3865 | unsigned char *, unsigned char *)); | ||
| 3866 | |||
| 3867 | /* Tokens returned from xpm_scan. */ | ||
| 3868 | |||
| 3869 | enum xpm_token | ||
| 3870 | { | ||
| 3871 | XPM_TK_IDENT = 256, | ||
| 3872 | XPM_TK_STRING, | ||
| 3873 | XPM_TK_EOF | ||
| 3874 | }; | ||
| 3875 | |||
| 3876 | /* Scan an XPM data and return a character (< 256) or a token defined | ||
| 3877 | by enum xpm_token above. *S and END are the start (inclusive) and | ||
| 3878 | the end (exclusive) addresses of the data, respectively. Advance | ||
| 3879 | *S while scanning. If token is either XPM_TK_IDENT or | ||
| 3880 | XPM_TK_STRING, *BEG and *LEN are set to the start address and the | ||
| 3881 | length of the corresponding token, respectively. */ | ||
| 3882 | |||
| 3883 | static int | ||
| 3884 | xpm_scan (s, end, beg, len) | ||
| 3885 | unsigned char **s, *end, **beg; | ||
| 3886 | int *len; | ||
| 3887 | { | ||
| 3888 | int c; | ||
| 3889 | |||
| 3890 | while (*s < end) | ||
| 3891 | { | ||
| 3892 | /* Skip white-space. */ | ||
| 3893 | while (*s < end && (c = *(*s)++, isspace (c))) | ||
| 3894 | ; | ||
| 3895 | |||
| 3896 | /* gnus-pointer.xpm uses '-' in its identifier. | ||
| 3897 | sb-dir-plus.xpm uses '+' in its identifier. */ | ||
| 3898 | if (isalpha (c) || c == '_' || c == '-' || c == '+') | ||
| 3899 | { | ||
| 3900 | *beg = *s - 1; | ||
| 3901 | while (*s < end && | ||
| 3902 | (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+')) | ||
| 3903 | ++*s; | ||
| 3904 | *len = *s - *beg; | ||
| 3905 | return XPM_TK_IDENT; | ||
| 3906 | } | ||
| 3907 | else if (c == '"') | ||
| 3908 | { | ||
| 3909 | *beg = *s; | ||
| 3910 | while (*s < end && **s != '"') | ||
| 3911 | ++*s; | ||
| 3912 | *len = *s - *beg; | ||
| 3913 | if (*s < end) | ||
| 3914 | ++*s; | ||
| 3915 | return XPM_TK_STRING; | ||
| 3916 | } | ||
| 3917 | else if (c == '/') | ||
| 3918 | { | ||
| 3919 | if (*s < end && **s == '*') | ||
| 3920 | { | ||
| 3921 | /* C-style comment. */ | ||
| 3922 | ++*s; | ||
| 3923 | do | ||
| 3924 | { | ||
| 3925 | while (*s < end && *(*s)++ != '*') | ||
| 3926 | ; | ||
| 3927 | } | ||
| 3928 | while (*s < end && **s != '/'); | ||
| 3929 | if (*s < end) | ||
| 3930 | ++*s; | ||
| 3931 | } | ||
| 3932 | else | ||
| 3933 | return c; | ||
| 3934 | } | ||
| 3935 | else | ||
| 3936 | return c; | ||
| 3937 | } | ||
| 3938 | |||
| 3939 | return XPM_TK_EOF; | ||
| 3940 | } | ||
| 3941 | |||
| 3942 | /* Functions for color table lookup in XPM data. A Key is a string | ||
| 3943 | specifying the color of each pixel in XPM data. A value is either | ||
| 3944 | an integer that specifies a pixel color, Qt that specifies | ||
| 3945 | transparency, or Qnil for the unspecified color. If the length of | ||
| 3946 | the key string is one, a vector is used as a table. Otherwise, a | ||
| 3947 | hash table is used. */ | ||
| 3948 | |||
| 3949 | static Lisp_Object | ||
| 3950 | xpm_make_color_table_v (put_func, get_func) | ||
| 3951 | void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object); | ||
| 3952 | Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int); | ||
| 3953 | { | ||
| 3954 | *put_func = xpm_put_color_table_v; | ||
| 3955 | *get_func = xpm_get_color_table_v; | ||
| 3956 | return Fmake_vector (make_number (256), Qnil); | ||
| 3957 | } | ||
| 3958 | |||
| 3959 | static void | ||
| 3960 | xpm_put_color_table_v (color_table, chars_start, chars_len, color) | ||
| 3961 | Lisp_Object color_table; | ||
| 3962 | unsigned char *chars_start; | ||
| 3963 | int chars_len; | ||
| 3964 | Lisp_Object color; | ||
| 3965 | { | ||
| 3966 | XVECTOR (color_table)->contents[*chars_start] = color; | ||
| 3967 | } | ||
| 3968 | |||
| 3969 | static Lisp_Object | ||
| 3970 | xpm_get_color_table_v (color_table, chars_start, chars_len) | ||
| 3971 | Lisp_Object color_table; | ||
| 3972 | unsigned char *chars_start; | ||
| 3973 | int chars_len; | ||
| 3974 | { | ||
| 3975 | return XVECTOR (color_table)->contents[*chars_start]; | ||
| 3976 | } | ||
| 3977 | |||
| 3978 | static Lisp_Object | ||
| 3979 | xpm_make_color_table_h (put_func, get_func) | ||
| 3980 | void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object); | ||
| 3981 | Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int); | ||
| 3982 | { | ||
| 3983 | *put_func = xpm_put_color_table_h; | ||
| 3984 | *get_func = xpm_get_color_table_h; | ||
| 3985 | return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), | ||
| 3986 | make_float (DEFAULT_REHASH_SIZE), | ||
| 3987 | make_float (DEFAULT_REHASH_THRESHOLD), | ||
| 3988 | Qnil, Qnil, Qnil); | ||
| 3989 | } | ||
| 3990 | |||
| 3991 | static void | ||
| 3992 | xpm_put_color_table_h (color_table, chars_start, chars_len, color) | ||
| 3993 | Lisp_Object color_table; | ||
| 3994 | unsigned char *chars_start; | ||
| 3995 | int chars_len; | ||
| 3996 | Lisp_Object color; | ||
| 3997 | { | ||
| 3998 | struct Lisp_Hash_Table *table = XHASH_TABLE (color_table); | ||
| 3999 | unsigned hash_code; | ||
| 4000 | Lisp_Object chars = make_unibyte_string (chars_start, chars_len); | ||
| 4001 | |||
| 4002 | hash_lookup (table, chars, &hash_code); | ||
| 4003 | hash_put (table, chars, color, hash_code); | ||
| 4004 | } | ||
| 4005 | |||
| 4006 | static Lisp_Object | ||
| 4007 | xpm_get_color_table_h (color_table, chars_start, chars_len) | ||
| 4008 | Lisp_Object color_table; | ||
| 4009 | unsigned char *chars_start; | ||
| 4010 | int chars_len; | ||
| 4011 | { | ||
| 4012 | struct Lisp_Hash_Table *table = XHASH_TABLE (color_table); | ||
| 4013 | int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len), | ||
| 4014 | NULL); | ||
| 4015 | |||
| 4016 | return i >= 0 ? HASH_VALUE (table, i) : Qnil; | ||
| 4017 | } | ||
| 4018 | |||
| 4019 | enum xpm_color_key { | ||
| 4020 | XPM_COLOR_KEY_S, | ||
| 4021 | XPM_COLOR_KEY_M, | ||
| 4022 | XPM_COLOR_KEY_G4, | ||
| 4023 | XPM_COLOR_KEY_G, | ||
| 4024 | XPM_COLOR_KEY_C | ||
| 4025 | }; | ||
| 4026 | |||
| 4027 | static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"}; | ||
| 4028 | |||
| 4029 | static int | ||
| 4030 | xpm_str_to_color_key (s) | ||
| 4031 | char *s; | ||
| 4032 | { | ||
| 4033 | int i; | ||
| 4034 | |||
| 4035 | for (i = 0; | ||
| 4036 | i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0]; | ||
| 4037 | i++) | ||
| 4038 | if (strcmp (xpm_color_key_strings[i], s) == 0) | ||
| 4039 | return i; | ||
| 4040 | return -1; | ||
| 4041 | } | ||
| 4042 | |||
| 4043 | static int | ||
| 4044 | xpm_load_image (f, img, contents, end) | ||
| 4045 | struct frame *f; | ||
| 4046 | struct image *img; | ||
| 4047 | unsigned char *contents, *end; | ||
| 4048 | { | ||
| 4049 | unsigned char *s = contents, *beg, *str; | ||
| 4050 | unsigned char buffer[BUFSIZ]; | ||
| 4051 | int width, height, x, y; | ||
| 4052 | int num_colors, chars_per_pixel; | ||
| 4053 | int len, LA1; | ||
| 4054 | void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object); | ||
| 4055 | Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int); | ||
| 4056 | Lisp_Object frame, color_symbols, color_table; | ||
| 4057 | int best_key, have_mask = 0; | ||
| 4058 | XImagePtr ximg = NULL, mask_img = NULL; | ||
| 4059 | |||
| 4060 | #define match() \ | ||
| 4061 | LA1 = xpm_scan (&s, end, &beg, &len) | ||
| 4062 | |||
| 4063 | #define expect(TOKEN) \ | ||
| 4064 | if (LA1 != (TOKEN)) \ | ||
| 4065 | goto failure; \ | ||
| 4066 | else \ | ||
| 4067 | match () | ||
| 4068 | |||
| 4069 | #define expect_ident(IDENT) \ | ||
| 4070 | if (LA1 == XPM_TK_IDENT \ | ||
| 4071 | && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \ | ||
| 4072 | match (); \ | ||
| 4073 | else \ | ||
| 4074 | goto failure | ||
| 4075 | |||
| 4076 | if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0)) | ||
| 4077 | goto failure; | ||
| 4078 | s += 9; | ||
| 4079 | match(); | ||
| 4080 | expect_ident ("static"); | ||
| 4081 | expect_ident ("char"); | ||
| 4082 | expect ('*'); | ||
| 4083 | expect (XPM_TK_IDENT); | ||
| 4084 | expect ('['); | ||
| 4085 | expect (']'); | ||
| 4086 | expect ('='); | ||
| 4087 | expect ('{'); | ||
| 4088 | expect (XPM_TK_STRING); | ||
| 4089 | if (len >= BUFSIZ) | ||
| 4090 | goto failure; | ||
| 4091 | memcpy (buffer, beg, len); | ||
| 4092 | buffer[len] = '\0'; | ||
| 4093 | if (sscanf (buffer, "%d %d %d %d", &width, &height, | ||
| 4094 | &num_colors, &chars_per_pixel) != 4 | ||
| 4095 | || width <= 0 || height <= 0 | ||
| 4096 | || num_colors <= 0 || chars_per_pixel <= 0) | ||
| 4097 | goto failure; | ||
| 4098 | expect (','); | ||
| 4099 | |||
| 4100 | XSETFRAME (frame, f); | ||
| 4101 | if (!NILP (Fxw_display_color_p (frame))) | ||
| 4102 | best_key = XPM_COLOR_KEY_C; | ||
| 4103 | else if (!NILP (Fx_display_grayscale_p (frame))) | ||
| 4104 | best_key = (XFASTINT (Fx_display_planes (frame)) > 2 | ||
| 4105 | ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4); | ||
| 4106 | else | ||
| 4107 | best_key = XPM_COLOR_KEY_M; | ||
| 4108 | |||
| 4109 | color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL); | ||
| 4110 | if (chars_per_pixel == 1) | ||
| 4111 | color_table = xpm_make_color_table_v (&put_color_table, | ||
| 4112 | &get_color_table); | ||
| 4113 | else | ||
| 4114 | color_table = xpm_make_color_table_h (&put_color_table, | ||
| 4115 | &get_color_table); | ||
| 4116 | |||
| 4117 | while (num_colors-- > 0) | ||
| 4118 | { | ||
| 4119 | unsigned char *color, *max_color; | ||
| 4120 | int key, next_key, max_key = 0; | ||
| 4121 | Lisp_Object symbol_color = Qnil, color_val; | ||
| 4122 | XColor cdef; | ||
| 4123 | |||
| 4124 | expect (XPM_TK_STRING); | ||
| 4125 | if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel) | ||
| 4126 | goto failure; | ||
| 4127 | memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel); | ||
| 4128 | buffer[len - chars_per_pixel] = '\0'; | ||
| 4129 | |||
| 4130 | str = strtok (buffer, " \t"); | ||
| 4131 | if (str == NULL) | ||
| 4132 | goto failure; | ||
| 4133 | key = xpm_str_to_color_key (str); | ||
| 4134 | if (key < 0) | ||
| 4135 | goto failure; | ||
| 4136 | do | ||
| 4137 | { | ||
| 4138 | color = strtok (NULL, " \t"); | ||
| 4139 | if (color == NULL) | ||
| 4140 | goto failure; | ||
| 4141 | |||
| 4142 | while (str = strtok (NULL, " \t")) | ||
| 4143 | { | ||
| 4144 | next_key = xpm_str_to_color_key (str); | ||
| 4145 | if (next_key >= 0) | ||
| 4146 | break; | ||
| 4147 | color[strlen (color)] = ' '; | ||
| 4148 | } | ||
| 4149 | |||
| 4150 | if (key == XPM_COLOR_KEY_S) | ||
| 4151 | { | ||
| 4152 | if (NILP (symbol_color)) | ||
| 4153 | symbol_color = build_string (color); | ||
| 4154 | } | ||
| 4155 | else if (max_key < key && key <= best_key) | ||
| 4156 | { | ||
| 4157 | max_key = key; | ||
| 4158 | max_color = color; | ||
| 4159 | } | ||
| 4160 | key = next_key; | ||
| 4161 | } | ||
| 4162 | while (str); | ||
| 4163 | |||
| 4164 | color_val = Qnil; | ||
| 4165 | if (!NILP (color_symbols) && !NILP (symbol_color)) | ||
| 4166 | { | ||
| 4167 | Lisp_Object specified_color = Fassoc (symbol_color, color_symbols); | ||
| 4168 | |||
| 4169 | if (CONSP (specified_color) && STRINGP (XCDR (specified_color))) | ||
| 4170 | if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0) | ||
| 4171 | color_val = Qt; | ||
| 4172 | else if (x_defined_color (f, SDATA (XCDR (specified_color)), | ||
| 4173 | &cdef, 0)) | ||
| 4174 | color_val = make_number (cdef.pixel); | ||
| 4175 | } | ||
| 4176 | if (NILP (color_val) && max_key > 0) | ||
| 4177 | if (xstricmp (max_color, "None") == 0) | ||
| 4178 | color_val = Qt; | ||
| 4179 | else if (x_defined_color (f, max_color, &cdef, 0)) | ||
| 4180 | color_val = make_number (cdef.pixel); | ||
| 4181 | if (!NILP (color_val)) | ||
| 4182 | (*put_color_table) (color_table, beg, chars_per_pixel, color_val); | ||
| 4183 | |||
| 4184 | expect (','); | ||
| 4185 | } | ||
| 4186 | |||
| 4187 | if (!x_create_x_image_and_pixmap (f, width, height, 0, | ||
| 4188 | &ximg, &img->pixmap) | ||
| 4189 | || !x_create_x_image_and_pixmap (f, width, height, 1, | ||
| 4190 | &mask_img, &img->mask)) | ||
| 4191 | { | ||
| 4192 | image_error ("Out of memory (%s)", img->spec, Qnil); | ||
| 4193 | goto error; | ||
| 4194 | } | ||
| 4195 | |||
| 4196 | for (y = 0; y < height; y++) | ||
| 4197 | { | ||
| 4198 | expect (XPM_TK_STRING); | ||
| 4199 | str = beg; | ||
| 4200 | if (len < width * chars_per_pixel) | ||
| 4201 | goto failure; | ||
| 4202 | for (x = 0; x < width; x++, str += chars_per_pixel) | ||
| 4203 | { | ||
| 4204 | Lisp_Object color_val = | ||
| 4205 | (*get_color_table) (color_table, str, chars_per_pixel); | ||
| 4206 | |||
| 4207 | XPutPixel (ximg, x, y, | ||
| 4208 | (INTEGERP (color_val) ? XINT (color_val) | ||
| 4209 | : FRAME_FOREGROUND_PIXEL (f))); | ||
| 4210 | XPutPixel (mask_img, x, y, | ||
| 4211 | (!EQ (color_val, Qt) ? PIX_MASK_DRAW (f) | ||
| 4212 | : (have_mask = 1, PIX_MASK_RETAIN (f)))); | ||
| 4213 | } | ||
| 4214 | if (y + 1 < height) | ||
| 4215 | expect (','); | ||
| 4216 | } | ||
| 4217 | |||
| 4218 | img->width = width; | ||
| 4219 | img->height = height; | ||
| 4220 | |||
| 4221 | x_put_x_image (f, ximg, img->pixmap, width, height); | ||
| 4222 | x_destroy_x_image (ximg); | ||
| 4223 | if (have_mask) | ||
| 4224 | { | ||
| 4225 | x_put_x_image (f, mask_img, img->mask, width, height); | ||
| 4226 | x_destroy_x_image (mask_img); | ||
| 4227 | } | ||
| 4228 | else | ||
| 4229 | { | ||
| 4230 | x_destroy_x_image (mask_img); | ||
| 4231 | Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); | ||
| 4232 | img->mask = NO_PIXMAP; | ||
| 4233 | } | ||
| 4234 | |||
| 4235 | return 1; | ||
| 4236 | |||
| 4237 | failure: | ||
| 4238 | image_error ("Invalid XPM file (%s)", img->spec, Qnil); | ||
| 4239 | error: | ||
| 4240 | x_destroy_x_image (ximg); | ||
| 4241 | x_destroy_x_image (mask_img); | ||
| 4242 | x_clear_image (f, img); | ||
| 4243 | return 0; | ||
| 4244 | |||
| 4245 | #undef match | ||
| 4246 | #undef expect | ||
| 4247 | #undef expect_ident | ||
| 4248 | } | ||
| 4249 | |||
| 4250 | static int | ||
| 4251 | xpm_load (f, img) | ||
| 4252 | struct frame *f; | ||
| 4253 | struct image *img; | ||
| 4254 | { | ||
| 4255 | int success_p = 0; | ||
| 4256 | Lisp_Object file_name; | ||
| 4257 | |||
| 4258 | /* If IMG->spec specifies a file name, create a non-file spec from it. */ | ||
| 4259 | file_name = image_spec_value (img->spec, QCfile, NULL); | ||
| 4260 | if (STRINGP (file_name)) | ||
| 4261 | { | ||
| 4262 | Lisp_Object file; | ||
| 4263 | unsigned char *contents; | ||
| 4264 | int size; | ||
| 4265 | struct gcpro gcpro1; | ||
| 4266 | |||
| 4267 | file = x_find_image_file (file_name); | ||
| 4268 | GCPRO1 (file); | ||
| 4269 | if (!STRINGP (file)) | ||
| 4270 | { | ||
| 4271 | image_error ("Cannot find image file `%s'", file_name, Qnil); | ||
| 4272 | UNGCPRO; | ||
| 4273 | return 0; | ||
| 4274 | } | ||
| 4275 | |||
| 4276 | contents = slurp_file (SDATA (file), &size); | ||
| 4277 | if (contents == NULL) | ||
| 4278 | { | ||
| 4279 | image_error ("Error loading XPM image `%s'", img->spec, Qnil); | ||
| 4280 | UNGCPRO; | ||
| 4281 | return 0; | ||
| 4282 | } | ||
| 4283 | |||
| 4284 | success_p = xpm_load_image (f, img, contents, contents + size); | ||
| 4285 | xfree (contents); | ||
| 4286 | UNGCPRO; | ||
| 4287 | } | ||
| 4288 | else | ||
| 4289 | { | ||
| 4290 | Lisp_Object data; | ||
| 4291 | |||
| 4292 | data = image_spec_value (img->spec, QCdata, NULL); | ||
| 4293 | success_p = xpm_load_image (f, img, SDATA (data), | ||
| 4294 | SDATA (data) + SBYTES (data)); | ||
| 4295 | } | ||
| 4296 | |||
| 4297 | return success_p; | ||
| 4298 | } | ||
| 4299 | |||
| 4300 | #endif /* MAC_OS */ | ||
| 4301 | |||
| 4302 | |||
| 3751 | 4303 | ||
| 3752 | /*********************************************************************** | 4304 | /*********************************************************************** |
| 3753 | Color table | 4305 | Color table |
| @@ -3857,7 +4409,7 @@ lookup_rgb_color (f, r, g, b) | |||
| 3857 | /* Assemble the pixel color. */ | 4409 | /* Assemble the pixel color. */ |
| 3858 | return pr | pg | pb; | 4410 | return pr | pg | pb; |
| 3859 | } | 4411 | } |
| 3860 | 4412 | ||
| 3861 | for (p = ct_table[i]; p; p = p->next) | 4413 | for (p = ct_table[i]; p; p = p->next) |
| 3862 | if (p->r == r && p->g == g && p->b == b) | 4414 | if (p->r == r && p->g == g && p->b == b) |
| 3863 | break; | 4415 | break; |
| @@ -4968,7 +5520,7 @@ pbm_load (f, img) | |||
| 4968 | x_destroy_x_image (ximg); | 5520 | x_destroy_x_image (ximg); |
| 4969 | 5521 | ||
| 4970 | /* X and W32 versions did it here, MAC version above. ++kfs | 5522 | /* X and W32 versions did it here, MAC version above. ++kfs |
| 4971 | img->width = width; | 5523 | img->width = width; |
| 4972 | img->height = height; */ | 5524 | img->height = height; */ |
| 4973 | 5525 | ||
| 4974 | UNGCPRO; | 5526 | UNGCPRO; |
| @@ -5091,21 +5643,12 @@ DEF_IMGLIB_FN (png_read_end); | |||
| 5091 | DEF_IMGLIB_FN (png_error); | 5643 | DEF_IMGLIB_FN (png_error); |
| 5092 | 5644 | ||
| 5093 | static int | 5645 | static int |
| 5094 | init_png_functions (void) | 5646 | init_png_functions (Lisp_Object libraries) |
| 5095 | { | 5647 | { |
| 5096 | HMODULE library; | 5648 | HMODULE library; |
| 5097 | 5649 | ||
| 5098 | /* Ensure zlib is loaded. Try debug version first. */ | ||
| 5099 | if (!LoadLibrary ("zlibd.dll") | ||
| 5100 | && !LoadLibrary ("zlib.dll")) | ||
| 5101 | return 0; | ||
| 5102 | |||
| 5103 | /* Try loading libpng under probable names. */ | 5650 | /* Try loading libpng under probable names. */ |
| 5104 | if (!(library = LoadLibrary ("libpng13d.dll")) | 5651 | if (!(library = w32_delayed_load (libraries, Qpng))) |
| 5105 | && !(library = LoadLibrary ("libpng13.dll")) | ||
| 5106 | && !(library = LoadLibrary ("libpng12d.dll")) | ||
| 5107 | && !(library = LoadLibrary ("libpng12.dll")) | ||
| 5108 | && !(library = LoadLibrary ("libpng.dll"))) | ||
| 5109 | return 0; | 5652 | return 0; |
| 5110 | 5653 | ||
| 5111 | LOAD_IMGLIB_FN (library, png_get_io_ptr); | 5654 | LOAD_IMGLIB_FN (library, png_get_io_ptr); |
| @@ -5196,6 +5739,12 @@ struct png_memory_storage | |||
| 5196 | PNG_PTR is a pointer to the PNG control structure. Copy LENGTH | 5739 | PNG_PTR is a pointer to the PNG control structure. Copy LENGTH |
| 5197 | bytes from the input to DATA. */ | 5740 | bytes from the input to DATA. */ |
| 5198 | 5741 | ||
| 5742 | #ifdef _MSC_VER | ||
| 5743 | /* Work around a problem with MinGW builds of graphics libraries | ||
| 5744 | not honoring calling conventions. */ | ||
| 5745 | #pragma optimize("g", off) | ||
| 5746 | #endif | ||
| 5747 | |||
| 5199 | static void | 5748 | static void |
| 5200 | png_read_from_memory (png_ptr, data, length) | 5749 | png_read_from_memory (png_ptr, data, length) |
| 5201 | png_structp png_ptr; | 5750 | png_structp png_ptr; |
| @@ -5212,6 +5761,11 @@ png_read_from_memory (png_ptr, data, length) | |||
| 5212 | tbr->index = tbr->index + length; | 5761 | tbr->index = tbr->index + length; |
| 5213 | } | 5762 | } |
| 5214 | 5763 | ||
| 5764 | #ifdef _MSC_VER | ||
| 5765 | /* Restore normal optimization, as specified on the command line. */ | ||
| 5766 | #pragma optimize("", on) | ||
| 5767 | #endif | ||
| 5768 | |||
| 5215 | /* Load PNG image IMG for use on frame F. Value is non-zero if | 5769 | /* Load PNG image IMG for use on frame F. Value is non-zero if |
| 5216 | successful. */ | 5770 | successful. */ |
| 5217 | 5771 | ||
| @@ -5412,9 +5966,9 @@ png_load (f, img) | |||
| 5412 | png_color_16 user_bg; | 5966 | png_color_16 user_bg; |
| 5413 | 5967 | ||
| 5414 | bzero (&user_bg, sizeof user_bg); | 5968 | bzero (&user_bg, sizeof user_bg); |
| 5415 | user_bg.red = color.red >> PNG_BG_COLOR_SHIFT; | 5969 | user_bg.red = color.red >> 8; |
| 5416 | user_bg.green = color.green >> PNG_BG_COLOR_SHIFT; | 5970 | user_bg.green = color.green >> 8; |
| 5417 | user_bg.blue = color.blue >> PNG_BG_COLOR_SHIFT; | 5971 | user_bg.blue = color.blue >> 8; |
| 5418 | 5972 | ||
| 5419 | fn_png_set_background (png_ptr, &user_bg, | 5973 | fn_png_set_background (png_ptr, &user_bg, |
| 5420 | PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); | 5974 | PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); |
| @@ -5438,9 +5992,9 @@ png_load (f, img) | |||
| 5438 | x_query_color (f, &color); | 5992 | x_query_color (f, &color); |
| 5439 | 5993 | ||
| 5440 | bzero (&frame_background, sizeof frame_background); | 5994 | bzero (&frame_background, sizeof frame_background); |
| 5441 | frame_background.red = color.red; | 5995 | frame_background.red = color.red >> 8; |
| 5442 | frame_background.green = color.green; | 5996 | frame_background.green = color.green >> 8; |
| 5443 | frame_background.blue = color.blue; | 5997 | frame_background.blue = color.blue >> 8; |
| 5444 | #endif /* HAVE_X_WINDOWS */ | 5998 | #endif /* HAVE_X_WINDOWS */ |
| 5445 | 5999 | ||
| 5446 | #ifdef HAVE_NTGUI | 6000 | #ifdef HAVE_NTGUI |
| @@ -5451,9 +6005,9 @@ png_load (f, img) | |||
| 5451 | x_query_color (f, &color); | 6005 | x_query_color (f, &color); |
| 5452 | #endif | 6006 | #endif |
| 5453 | bzero (&frame_background, sizeof frame_background); | 6007 | bzero (&frame_background, sizeof frame_background); |
| 5454 | frame_background.red = 256 * GetRValue (color); | 6008 | frame_background.red = GetRValue (color); |
| 5455 | frame_background.green = 256 * GetGValue (color); | 6009 | frame_background.green = GetGValue (color); |
| 5456 | frame_background.blue = 256 * GetBValue (color); | 6010 | frame_background.blue = GetBValue (color); |
| 5457 | #endif /* HAVE_NTGUI */ | 6011 | #endif /* HAVE_NTGUI */ |
| 5458 | 6012 | ||
| 5459 | #ifdef MAC_OS | 6013 | #ifdef MAC_OS |
| @@ -5738,13 +6292,11 @@ DEF_IMGLIB_FN (jpeg_std_error); | |||
| 5738 | DEF_IMGLIB_FN (jpeg_resync_to_restart); | 6292 | DEF_IMGLIB_FN (jpeg_resync_to_restart); |
| 5739 | 6293 | ||
| 5740 | static int | 6294 | static int |
| 5741 | init_jpeg_functions (void) | 6295 | init_jpeg_functions (Lisp_Object libraries) |
| 5742 | { | 6296 | { |
| 5743 | HMODULE library; | 6297 | HMODULE library; |
| 5744 | 6298 | ||
| 5745 | if (!(library = LoadLibrary ("libjpeg.dll")) | 6299 | if (!(library = w32_delayed_load (libraries, Qjpeg))) |
| 5746 | && !(library = LoadLibrary ("jpeg-62.dll")) | ||
| 5747 | && !(library = LoadLibrary ("jpeg.dll"))) | ||
| 5748 | return 0; | 6300 | return 0; |
| 5749 | 6301 | ||
| 5750 | LOAD_IMGLIB_FN (library, jpeg_finish_decompress); | 6302 | LOAD_IMGLIB_FN (library, jpeg_finish_decompress); |
| @@ -6175,11 +6727,11 @@ DEF_IMGLIB_FN (TIFFReadRGBAImage); | |||
| 6175 | DEF_IMGLIB_FN (TIFFClose); | 6727 | DEF_IMGLIB_FN (TIFFClose); |
| 6176 | 6728 | ||
| 6177 | static int | 6729 | static int |
| 6178 | init_tiff_functions (void) | 6730 | init_tiff_functions (Lisp_Object libraries) |
| 6179 | { | 6731 | { |
| 6180 | HMODULE library; | 6732 | HMODULE library; |
| 6181 | 6733 | ||
| 6182 | if (!(library = LoadLibrary ("libtiff.dll"))) | 6734 | if (!(library = w32_delayed_load (libraries, Qtiff))) |
| 6183 | return 0; | 6735 | return 0; |
| 6184 | 6736 | ||
| 6185 | LOAD_IMGLIB_FN (library, TIFFSetErrorHandler); | 6737 | LOAD_IMGLIB_FN (library, TIFFSetErrorHandler); |
| @@ -6595,11 +7147,11 @@ DEF_IMGLIB_FN (DGifOpen); | |||
| 6595 | DEF_IMGLIB_FN (DGifOpenFileName); | 7147 | DEF_IMGLIB_FN (DGifOpenFileName); |
| 6596 | 7148 | ||
| 6597 | static int | 7149 | static int |
| 6598 | init_gif_functions (void) | 7150 | init_gif_functions (Lisp_Object libraries) |
| 6599 | { | 7151 | { |
| 6600 | HMODULE library; | 7152 | HMODULE library; |
| 6601 | 7153 | ||
| 6602 | if (!(library = LoadLibrary ("libungif.dll"))) | 7154 | if (!(library = w32_delayed_load (libraries, Qgif))) |
| 6603 | return 0; | 7155 | return 0; |
| 6604 | 7156 | ||
| 6605 | LOAD_IMGLIB_FN (library, DGifCloseFile); | 7157 | LOAD_IMGLIB_FN (library, DGifCloseFile); |
| @@ -6875,6 +7427,8 @@ gif_load (f, img) | |||
| 6875 | TimeValue time; | 7427 | TimeValue time; |
| 6876 | struct gcpro gcpro1; | 7428 | struct gcpro gcpro1; |
| 6877 | int ino; | 7429 | int ino; |
| 7430 | CGrafPtr old_port; | ||
| 7431 | GDHandle old_gdh; | ||
| 6878 | 7432 | ||
| 6879 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 7433 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 6880 | specified_data = image_spec_value (img->spec, QCdata, NULL); | 7434 | specified_data = image_spec_value (img->spec, QCdata, NULL); |
| @@ -6992,11 +7546,13 @@ gif_load (f, img) | |||
| 6992 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 7546 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 6993 | goto error; | 7547 | goto error; |
| 6994 | 7548 | ||
| 7549 | GetGWorld (&old_port, &old_gdh); | ||
| 6995 | SetGWorld (ximg, NULL); | 7550 | SetGWorld (ximg, NULL); |
| 6996 | bg_color.red = color.red; | 7551 | bg_color.red = color.red; |
| 6997 | bg_color.green = color.green; | 7552 | bg_color.green = color.green; |
| 6998 | bg_color.blue = color.blue; | 7553 | bg_color.blue = color.blue; |
| 6999 | RGBBackColor (&bg_color); | 7554 | RGBBackColor (&bg_color); |
| 7555 | SetGWorld (old_port, old_gdh); | ||
| 7000 | SetMovieActive (movie, TRUE); | 7556 | SetMovieActive (movie, TRUE); |
| 7001 | SetMovieGWorld (movie, ximg, NULL); | 7557 | SetMovieGWorld (movie, ximg, NULL); |
| 7002 | SampleNumToMediaTime (media, ino + 1, &time, NULL); | 7558 | SampleNumToMediaTime (media, ino + 1, &time, NULL); |
| @@ -7368,9 +7924,81 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "") | |||
| 7368 | Initialization | 7924 | Initialization |
| 7369 | ***********************************************************************/ | 7925 | ***********************************************************************/ |
| 7370 | 7926 | ||
| 7927 | #ifdef HAVE_NTGUI | ||
| 7928 | /* Image types that rely on external libraries are loaded dynamically | ||
| 7929 | if the library is available. */ | ||
| 7930 | #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \ | ||
| 7931 | define_image_type (image_type, init_lib_fn (libraries)) | ||
| 7932 | #else | ||
| 7933 | #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \ | ||
| 7934 | define_image_type (image_type, TRUE) | ||
| 7935 | #endif /* HAVE_NTGUI */ | ||
| 7936 | |||
| 7937 | DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0, | ||
| 7938 | doc: /* Initialize image library implementing image type TYPE. | ||
| 7939 | Return non-nil if TYPE is a supported image type. | ||
| 7940 | |||
| 7941 | Image types pbm and xbm are prebuilt; other types are loaded here. | ||
| 7942 | Libraries to load are specified in alist LIBRARIES (usually, the value | ||
| 7943 | of `image-library-alist', which see. */) | ||
| 7944 | (type, libraries) | ||
| 7945 | { | ||
| 7946 | Lisp_Object tested; | ||
| 7947 | |||
| 7948 | /* Don't try to reload the library. */ | ||
| 7949 | tested = Fassq (type, Vimage_type_cache); | ||
| 7950 | if (CONSP (tested)) | ||
| 7951 | return XCDR (tested); | ||
| 7952 | |||
| 7953 | #if defined (HAVE_XPM) || defined (MAC_OS) | ||
| 7954 | if (EQ (type, Qxpm)) | ||
| 7955 | return CHECK_LIB_AVAILABLE(&xpm_type, init_xpm_functions); | ||
| 7956 | #endif | ||
| 7957 | |||
| 7958 | #if defined (HAVE_JPEG) || defined (MAC_OS) | ||
| 7959 | if (EQ (type, Qjpeg)) | ||
| 7960 | return CHECK_LIB_AVAILABLE(&jpeg_type, init_jpeg_functions); | ||
| 7961 | #endif | ||
| 7962 | |||
| 7963 | #if defined (HAVE_TIFF) || defined (MAC_OS) | ||
| 7964 | if (EQ (type, Qtiff)) | ||
| 7965 | return CHECK_LIB_AVAILABLE(&tiff_type, init_tiff_functions); | ||
| 7966 | #endif | ||
| 7967 | |||
| 7968 | #if defined (HAVE_GIF) || defined (MAC_OS) | ||
| 7969 | if (EQ (type, Qgif)) | ||
| 7970 | return CHECK_LIB_AVAILABLE(&gif_type, init_gif_functions); | ||
| 7971 | #endif | ||
| 7972 | |||
| 7973 | #if defined (HAVE_PNG) || defined (MAC_OS) | ||
| 7974 | if (EQ (type, Qpng)) | ||
| 7975 | return CHECK_LIB_AVAILABLE(&png_type, init_png_functions); | ||
| 7976 | #endif | ||
| 7977 | |||
| 7978 | #ifdef HAVE_GHOSTSCRIPT | ||
| 7979 | if (EQ (type, Qpostscript)) | ||
| 7980 | return CHECK_LIB_AVAILABLE(&gs_type, init_gs_functions); | ||
| 7981 | #endif | ||
| 7982 | |||
| 7983 | /* If the type is not recognized, avoid testing it ever again. */ | ||
| 7984 | CACHE_IMAGE_TYPE(type, Qnil); | ||
| 7985 | return Qnil; | ||
| 7986 | } | ||
| 7987 | |||
| 7371 | void | 7988 | void |
| 7372 | syms_of_image () | 7989 | syms_of_image () |
| 7373 | { | 7990 | { |
| 7991 | /* Must be defined now becase we're going to update it below, while | ||
| 7992 | defining the supported image types. */ | ||
| 7993 | DEFVAR_LISP ("image-types", &Vimage_types, | ||
| 7994 | doc: /* List of potentially supported image types. | ||
| 7995 | Each element of the list is a symbol for a image type, like 'jpeg or 'png. | ||
| 7996 | To check whether it is really supported, use `image-type-available-p'. */); | ||
| 7997 | Vimage_types = Qnil; | ||
| 7998 | |||
| 7999 | Vimage_type_cache = Qnil; | ||
| 8000 | staticpro (&Vimage_type_cache); | ||
| 8001 | |||
| 7374 | QCascent = intern (":ascent"); | 8002 | QCascent = intern (":ascent"); |
| 7375 | staticpro (&QCascent); | 8003 | staticpro (&QCascent); |
| 7376 | QCmargin = intern (":margin"); | 8004 | QCmargin = intern (":margin"); |
| @@ -7404,6 +8032,7 @@ syms_of_image () | |||
| 7404 | Qpostscript = intern ("postscript"); | 8032 | Qpostscript = intern ("postscript"); |
| 7405 | staticpro (&Qpostscript); | 8033 | staticpro (&Qpostscript); |
| 7406 | #ifdef HAVE_GHOSTSCRIPT | 8034 | #ifdef HAVE_GHOSTSCRIPT |
| 8035 | ADD_IMAGE_TYPE(Qpostscript); | ||
| 7407 | QCloader = intern (":loader"); | 8036 | QCloader = intern (":loader"); |
| 7408 | staticpro (&QCloader); | 8037 | staticpro (&QCloader); |
| 7409 | QCbounding_box = intern (":bounding-box"); | 8038 | QCbounding_box = intern (":bounding-box"); |
| @@ -7416,35 +8045,43 @@ syms_of_image () | |||
| 7416 | 8045 | ||
| 7417 | Qpbm = intern ("pbm"); | 8046 | Qpbm = intern ("pbm"); |
| 7418 | staticpro (&Qpbm); | 8047 | staticpro (&Qpbm); |
| 8048 | ADD_IMAGE_TYPE(Qpbm); | ||
| 7419 | 8049 | ||
| 7420 | Qxbm = intern ("xbm"); | 8050 | Qxbm = intern ("xbm"); |
| 7421 | staticpro (&Qxbm); | 8051 | staticpro (&Qxbm); |
| 8052 | ADD_IMAGE_TYPE(Qxbm); | ||
| 7422 | 8053 | ||
| 7423 | #ifdef HAVE_XPM | 8054 | #if defined (HAVE_XPM) || defined (MAC_OS) |
| 7424 | Qxpm = intern ("xpm"); | 8055 | Qxpm = intern ("xpm"); |
| 7425 | staticpro (&Qxpm); | 8056 | staticpro (&Qxpm); |
| 8057 | ADD_IMAGE_TYPE(Qxpm); | ||
| 7426 | #endif | 8058 | #endif |
| 7427 | 8059 | ||
| 7428 | #if defined (HAVE_JPEG) || defined (MAC_OS) | 8060 | #if defined (HAVE_JPEG) || defined (MAC_OS) |
| 7429 | Qjpeg = intern ("jpeg"); | 8061 | Qjpeg = intern ("jpeg"); |
| 7430 | staticpro (&Qjpeg); | 8062 | staticpro (&Qjpeg); |
| 8063 | ADD_IMAGE_TYPE(Qjpeg); | ||
| 7431 | #endif | 8064 | #endif |
| 7432 | 8065 | ||
| 7433 | #if defined (HAVE_TIFF) || defined (MAC_OS) | 8066 | #if defined (HAVE_TIFF) || defined (MAC_OS) |
| 7434 | Qtiff = intern ("tiff"); | 8067 | Qtiff = intern ("tiff"); |
| 7435 | staticpro (&Qtiff); | 8068 | staticpro (&Qtiff); |
| 8069 | ADD_IMAGE_TYPE(Qtiff); | ||
| 7436 | #endif | 8070 | #endif |
| 7437 | 8071 | ||
| 7438 | #if defined (HAVE_GIF) || defined (MAC_OS) | 8072 | #if defined (HAVE_GIF) || defined (MAC_OS) |
| 7439 | Qgif = intern ("gif"); | 8073 | Qgif = intern ("gif"); |
| 7440 | staticpro (&Qgif); | 8074 | staticpro (&Qgif); |
| 8075 | ADD_IMAGE_TYPE(Qgif); | ||
| 7441 | #endif | 8076 | #endif |
| 7442 | 8077 | ||
| 7443 | #if defined (HAVE_PNG) || defined (MAC_OS) | 8078 | #if defined (HAVE_PNG) || defined (MAC_OS) |
| 7444 | Qpng = intern ("png"); | 8079 | Qpng = intern ("png"); |
| 7445 | staticpro (&Qpng); | 8080 | staticpro (&Qpng); |
| 8081 | ADD_IMAGE_TYPE(Qpng); | ||
| 7446 | #endif | 8082 | #endif |
| 7447 | 8083 | ||
| 8084 | defsubr (&Sinit_image_library); | ||
| 7448 | defsubr (&Sclear_image_cache); | 8085 | defsubr (&Sclear_image_cache); |
| 7449 | defsubr (&Simage_size); | 8086 | defsubr (&Simage_size); |
| 7450 | defsubr (&Simage_mask_p); | 8087 | defsubr (&Simage_mask_p); |
| @@ -7472,52 +8109,13 @@ meaning don't clear the cache. */); | |||
| 7472 | Vimage_cache_eviction_delay = make_number (30 * 60); | 8109 | Vimage_cache_eviction_delay = make_number (30 * 60); |
| 7473 | } | 8110 | } |
| 7474 | 8111 | ||
| 7475 | |||
| 7476 | #ifdef HAVE_NTGUI | ||
| 7477 | /* Image types that rely on external libraries are loaded dynamically | ||
| 7478 | if the library is available. */ | ||
| 7479 | #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn()) | ||
| 7480 | #else | ||
| 7481 | #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */ | ||
| 7482 | #endif /* HAVE_NTGUI */ | ||
| 7483 | |||
| 7484 | void | 8112 | void |
| 7485 | init_image () | 8113 | init_image () |
| 7486 | { | 8114 | { |
| 7487 | image_types = NULL; | 8115 | image_types = NULL; |
| 7488 | Vimage_types = Qnil; | ||
| 7489 | |||
| 7490 | define_image_type (&xbm_type); | ||
| 7491 | define_image_type (&pbm_type); | ||
| 7492 | 8116 | ||
| 7493 | #ifdef HAVE_XPM | 8117 | define_image_type (&xbm_type, TRUE); |
| 7494 | IF_LIB_AVAILABLE(init_xpm_functions) | 8118 | define_image_type (&pbm_type, TRUE); |
| 7495 | define_image_type (&xpm_type); | ||
| 7496 | #endif | ||
| 7497 | |||
| 7498 | #if defined (HAVE_JPEG) || defined (MAC_OS) | ||
| 7499 | IF_LIB_AVAILABLE(init_jpeg_functions) | ||
| 7500 | define_image_type (&jpeg_type); | ||
| 7501 | #endif | ||
| 7502 | |||
| 7503 | #if defined (HAVE_TIFF) || defined (MAC_OS) | ||
| 7504 | IF_LIB_AVAILABLE(init_tiff_functions) | ||
| 7505 | define_image_type (&tiff_type); | ||
| 7506 | #endif | ||
| 7507 | |||
| 7508 | #if defined (HAVE_GIF) || defined (MAC_OS) | ||
| 7509 | IF_LIB_AVAILABLE(init_gif_functions) | ||
| 7510 | define_image_type (&gif_type); | ||
| 7511 | #endif | ||
| 7512 | |||
| 7513 | #if defined (HAVE_PNG) || defined (MAC_OS) | ||
| 7514 | IF_LIB_AVAILABLE(init_png_functions) | ||
| 7515 | define_image_type (&png_type); | ||
| 7516 | #endif | ||
| 7517 | |||
| 7518 | #ifdef HAVE_GHOSTSCRIPT | ||
| 7519 | define_image_type (&gs_type); | ||
| 7520 | #endif | ||
| 7521 | 8119 | ||
| 7522 | #ifdef MAC_OS | 8120 | #ifdef MAC_OS |
| 7523 | /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */ | 8121 | /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */ |