diff options
| author | Alan Third | 2019-01-02 21:00:09 +0000 |
|---|---|---|
| committer | Alan Third | 2019-01-10 19:24:20 +0000 |
| commit | a1b7a3f2a3957a399d6c3c7bcffa07ac67da82fc (patch) | |
| tree | 478594bd679f2db099fcb6320750f24fcedf5fc6 /src/image.c | |
| parent | c342b26371480316024e1e5d63cd8b3f035dda69 (diff) | |
| download | emacs-a1b7a3f2a3957a399d6c3c7bcffa07ac67da82fc.tar.gz emacs-a1b7a3f2a3957a399d6c3c7bcffa07ac67da82fc.zip | |
Add native image scaling (bug#33587)
* configure.ac: Test for XRender outside of xft checks.
* src/Makefile.in (XRENDER_LIBS): List XRender libs separately from
xft libs.
* lisp/image.el (image--get-imagemagick-and-warn): Allow resizing if
native scaling is available.
* src/dispextern.h: Add XRender and image scaling stuff.
(struct image): Add XRender Pictures.
* src/image.c (x_create_bitmap_mask):
(image_create_x_image_and_pixmap): Handle XRender Picture.
(scale_image_size):
(compute_image_size): Make available when any form of scaling is
enabled.
(x_set_image_size): New function.
(lookup_image): Set image size.
(x_create_x_image_and_pixmap): Create XRender Picture when necessary.
(x_put_x_image): Handle the case where desired size != actual size.
(free_image): Free XRender Pictures.
(Fimage_scaling_p): New function.
(syms_of_image): Add image-scaling-p.
* src/nsimage.m (ns_load_image): Remove NS specific resizing.
([EmacsImage setSizeFromSpec:]): Remove method.
(ns_image_set_size): New function.
* src/nsterm.m (ns_draw_fringe_bitmap): Cocoa and GNUstep both have
the same compositing functions, so remove unnecessary difference.
* src/xterm.c (x_composite_image): New function.
(x_draw_image_foreground): Use new x_composite_image function.
* doc/lispref/display.texi (Image Descriptors): Document
image-scaling-p and add resizing descriptors.
(ImageMagick Images): Remove resizing descriptors.
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 312 |
1 files changed, 208 insertions, 104 deletions
diff --git a/src/image.c b/src/image.c index 87e0c071eef..84c31dcfc3c 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -408,8 +408,13 @@ x_destroy_all_bitmaps (Display_Info *dpyinfo) | |||
| 408 | dpyinfo->bitmaps_last = 0; | 408 | dpyinfo->bitmaps_last = 0; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | #ifndef HAVE_XRENDER | ||
| 412 | /* Required for the definition of x_create_x_image_and_pixmap below. */ | ||
| 413 | typedef void Picture; | ||
| 414 | #endif | ||
| 415 | |||
| 411 | static bool x_create_x_image_and_pixmap (struct frame *, int, int, int, | 416 | static bool x_create_x_image_and_pixmap (struct frame *, int, int, int, |
| 412 | XImagePtr *, Pixmap *); | 417 | XImagePtr *, Pixmap *, Picture *); |
| 413 | static void x_destroy_x_image (XImagePtr ximg); | 418 | static void x_destroy_x_image (XImagePtr ximg); |
| 414 | 419 | ||
| 415 | #ifdef HAVE_NTGUI | 420 | #ifdef HAVE_NTGUI |
| @@ -472,7 +477,8 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id) | |||
| 472 | return; | 477 | return; |
| 473 | } | 478 | } |
| 474 | 479 | ||
| 475 | result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask); | 480 | result = x_create_x_image_and_pixmap (f, width, height, 1, |
| 481 | &mask_img, &mask, NULL); | ||
| 476 | 482 | ||
| 477 | unblock_input (); | 483 | unblock_input (); |
| 478 | if (!result) | 484 | if (!result) |
| @@ -1011,6 +1017,13 @@ free_image (struct frame *f, struct image *img) | |||
| 1011 | 1017 | ||
| 1012 | c->images[img->id] = NULL; | 1018 | c->images[img->id] = NULL; |
| 1013 | 1019 | ||
| 1020 | #ifdef HAVE_XRENDER | ||
| 1021 | if (img->picture) | ||
| 1022 | XRenderFreePicture (FRAME_X_DISPLAY (f), img->picture); | ||
| 1023 | if (img->mask_picture) | ||
| 1024 | XRenderFreePicture (FRAME_X_DISPLAY (f), img->mask_picture); | ||
| 1025 | #endif | ||
| 1026 | |||
| 1014 | /* Windows NT redefines 'free', but in this file, we need to | 1027 | /* Windows NT redefines 'free', but in this file, we need to |
| 1015 | avoid the redefinition. */ | 1028 | avoid the redefinition. */ |
| 1016 | #ifdef WINDOWSNT | 1029 | #ifdef WINDOWSNT |
| @@ -1747,6 +1760,147 @@ postprocess_image (struct frame *f, struct image *img) | |||
| 1747 | } | 1760 | } |
| 1748 | } | 1761 | } |
| 1749 | 1762 | ||
| 1763 | #if defined (HAVE_IMAGEMAGICK) || defined (HAVE_NATIVE_SCALING) | ||
| 1764 | /* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER, | ||
| 1765 | safely rounded and clipped to int range. */ | ||
| 1766 | |||
| 1767 | static int | ||
| 1768 | scale_image_size (int size, size_t divisor, size_t multiplier) | ||
| 1769 | { | ||
| 1770 | if (divisor != 0) | ||
| 1771 | { | ||
| 1772 | double s = size; | ||
| 1773 | double scaled = s * multiplier / divisor + 0.5; | ||
| 1774 | if (scaled < INT_MAX) | ||
| 1775 | return scaled; | ||
| 1776 | } | ||
| 1777 | return INT_MAX; | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | /* Compute the desired size of an image with native size WIDTH x HEIGHT. | ||
| 1781 | Use SPEC to deduce the size. Store the desired size into | ||
| 1782 | *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ | ||
| 1783 | static void | ||
| 1784 | compute_image_size (size_t width, size_t height, | ||
| 1785 | Lisp_Object spec, | ||
| 1786 | int *d_width, int *d_height) | ||
| 1787 | { | ||
| 1788 | Lisp_Object value; | ||
| 1789 | int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1; | ||
| 1790 | double scale = 1; | ||
| 1791 | |||
| 1792 | value = image_spec_value (spec, QCscale, NULL); | ||
| 1793 | if (NUMBERP (value)) | ||
| 1794 | scale = XFLOATINT (value); | ||
| 1795 | |||
| 1796 | value = image_spec_value (spec, QCmax_width, NULL); | ||
| 1797 | if (FIXNATP (value)) | ||
| 1798 | max_width = min (XFIXNAT (value), INT_MAX); | ||
| 1799 | |||
| 1800 | value = image_spec_value (spec, QCmax_height, NULL); | ||
| 1801 | if (FIXNATP (value)) | ||
| 1802 | max_height = min (XFIXNAT (value), INT_MAX); | ||
| 1803 | |||
| 1804 | /* If width and/or height is set in the display spec assume we want | ||
| 1805 | to scale to those values. If either h or w is unspecified, the | ||
| 1806 | unspecified should be calculated from the specified to preserve | ||
| 1807 | aspect ratio. */ | ||
| 1808 | value = image_spec_value (spec, QCwidth, NULL); | ||
| 1809 | if (FIXNATP (value)) | ||
| 1810 | { | ||
| 1811 | desired_width = min (XFIXNAT (value) * scale, INT_MAX); | ||
| 1812 | /* :width overrides :max-width. */ | ||
| 1813 | max_width = -1; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | value = image_spec_value (spec, QCheight, NULL); | ||
| 1817 | if (FIXNATP (value)) | ||
| 1818 | { | ||
| 1819 | desired_height = min (XFIXNAT (value) * scale, INT_MAX); | ||
| 1820 | /* :height overrides :max-height. */ | ||
| 1821 | max_height = -1; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | /* If we have both width/height set explicitly, we skip past all the | ||
| 1825 | aspect ratio-preserving computations below. */ | ||
| 1826 | if (desired_width != -1 && desired_height != -1) | ||
| 1827 | goto out; | ||
| 1828 | |||
| 1829 | width = width * scale; | ||
| 1830 | height = height * scale; | ||
| 1831 | |||
| 1832 | if (desired_width != -1) | ||
| 1833 | /* Width known, calculate height. */ | ||
| 1834 | desired_height = scale_image_size (desired_width, width, height); | ||
| 1835 | else if (desired_height != -1) | ||
| 1836 | /* Height known, calculate width. */ | ||
| 1837 | desired_width = scale_image_size (desired_height, height, width); | ||
| 1838 | else | ||
| 1839 | { | ||
| 1840 | desired_width = width; | ||
| 1841 | desired_height = height; | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | if (max_width != -1 && desired_width > max_width) | ||
| 1845 | { | ||
| 1846 | /* The image is wider than :max-width. */ | ||
| 1847 | desired_width = max_width; | ||
| 1848 | desired_height = scale_image_size (desired_width, width, height); | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | if (max_height != -1 && desired_height > max_height) | ||
| 1852 | { | ||
| 1853 | /* The image is higher than :max-height. */ | ||
| 1854 | desired_height = max_height; | ||
| 1855 | desired_width = scale_image_size (desired_height, height, width); | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | out: | ||
| 1859 | *d_width = desired_width; | ||
| 1860 | *d_height = desired_height; | ||
| 1861 | } | ||
| 1862 | |||
| 1863 | #ifdef HAVE_NATIVE_SCALING | ||
| 1864 | static void | ||
| 1865 | x_set_image_size (struct frame *f, struct image *img) | ||
| 1866 | { | ||
| 1867 | #ifdef HAVE_IMAGEMAGICK | ||
| 1868 | /* ImageMagick images are already the correct size. */ | ||
| 1869 | if (!EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick)) | ||
| 1870 | #endif | ||
| 1871 | { | ||
| 1872 | int width, height; | ||
| 1873 | |||
| 1874 | compute_image_size (img->width, img->height, img->spec, &width, &height); | ||
| 1875 | |||
| 1876 | #ifdef HAVE_NS | ||
| 1877 | ns_image_set_size (img->pixmap, width, height); | ||
| 1878 | img->width = width; | ||
| 1879 | img->height = height; | ||
| 1880 | #endif | ||
| 1881 | |||
| 1882 | #ifdef HAVE_XRENDER | ||
| 1883 | if (img->picture) | ||
| 1884 | { | ||
| 1885 | double xscale = (double) img->width/width; | ||
| 1886 | double yscale = (double) img->height/height; | ||
| 1887 | |||
| 1888 | XTransform tmat = {{{XDoubleToFixed (xscale), XDoubleToFixed (0), XDoubleToFixed (0)}, | ||
| 1889 | {XDoubleToFixed (0), XDoubleToFixed (yscale), XDoubleToFixed (0)}, | ||
| 1890 | {XDoubleToFixed (0), XDoubleToFixed (0), XDoubleToFixed (1)}}}; | ||
| 1891 | |||
| 1892 | XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture, FilterBest, 0, 0); | ||
| 1893 | XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat); | ||
| 1894 | |||
| 1895 | img->width = width; | ||
| 1896 | img->height = height; | ||
| 1897 | } | ||
| 1898 | #endif | ||
| 1899 | } | ||
| 1900 | } | ||
| 1901 | #endif | ||
| 1902 | #endif /* HAVE_IMAGEMAGICK || HAVE_XRENDER || HAVE_NS */ | ||
| 1903 | |||
| 1750 | 1904 | ||
| 1751 | /* Return the id of image with Lisp specification SPEC on frame F. | 1905 | /* Return the id of image with Lisp specification SPEC on frame F. |
| 1752 | SPEC must be a valid Lisp image specification (see valid_image_p). */ | 1906 | SPEC must be a valid Lisp image specification (see valid_image_p). */ |
| @@ -1802,6 +1956,9 @@ lookup_image (struct frame *f, Lisp_Object spec) | |||
| 1802 | `:background COLOR'. */ | 1956 | `:background COLOR'. */ |
| 1803 | Lisp_Object ascent, margin, relief, bg; | 1957 | Lisp_Object ascent, margin, relief, bg; |
| 1804 | int relief_bound; | 1958 | int relief_bound; |
| 1959 | #ifdef HAVE_NATIVE_SCALING | ||
| 1960 | x_set_image_size (f, img); | ||
| 1961 | #endif | ||
| 1805 | 1962 | ||
| 1806 | ascent = image_spec_value (spec, QCascent, NULL); | 1963 | ascent = image_spec_value (spec, QCascent, NULL); |
| 1807 | if (FIXNUMP (ascent)) | 1964 | if (FIXNUMP (ascent)) |
| @@ -1976,12 +2133,15 @@ x_check_image_size (XImagePtr ximg, int width, int height) | |||
| 1976 | 2133 | ||
| 1977 | static bool | 2134 | static bool |
| 1978 | x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | 2135 | x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, |
| 1979 | XImagePtr *ximg, Pixmap *pixmap) | 2136 | XImagePtr *ximg, Pixmap *pixmap, Picture *picture) |
| 1980 | { | 2137 | { |
| 1981 | #ifdef HAVE_X_WINDOWS | 2138 | #ifdef HAVE_X_WINDOWS |
| 1982 | Display *display = FRAME_X_DISPLAY (f); | 2139 | Display *display = FRAME_X_DISPLAY (f); |
| 1983 | Drawable drawable = FRAME_X_DRAWABLE (f); | 2140 | Drawable drawable = FRAME_X_DRAWABLE (f); |
| 1984 | Screen *screen = FRAME_X_SCREEN (f); | 2141 | Screen *screen = FRAME_X_SCREEN (f); |
| 2142 | #ifdef HAVE_XRENDER | ||
| 2143 | int event_basep, error_basep; | ||
| 2144 | #endif | ||
| 1985 | 2145 | ||
| 1986 | eassert (input_blocked_p ()); | 2146 | eassert (input_blocked_p ()); |
| 1987 | 2147 | ||
| @@ -2018,6 +2178,21 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 2018 | return 0; | 2178 | return 0; |
| 2019 | } | 2179 | } |
| 2020 | 2180 | ||
| 2181 | #ifdef HAVE_XRENDER | ||
| 2182 | if (picture && XRenderQueryExtension (display, &event_basep, &error_basep)) | ||
| 2183 | { | ||
| 2184 | XRenderPictFormat *format; | ||
| 2185 | XRenderPictureAttributes attr; | ||
| 2186 | |||
| 2187 | /* FIXME: Do we need to handle all possible bit depths? */ | ||
| 2188 | format = XRenderFindStandardFormat (display, | ||
| 2189 | depth > 24 ? PictStandardARGB32 | ||
| 2190 | : depth > 8 ? PictStandardRGB24 | ||
| 2191 | : PictStandardA8); | ||
| 2192 | *picture = XRenderCreatePicture (display, *pixmap, format, 0, &attr); | ||
| 2193 | } | ||
| 2194 | #endif | ||
| 2195 | |||
| 2021 | return 1; | 2196 | return 1; |
| 2022 | #endif /* HAVE_X_WINDOWS */ | 2197 | #endif /* HAVE_X_WINDOWS */ |
| 2023 | 2198 | ||
| @@ -2163,7 +2338,8 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he | |||
| 2163 | 2338 | ||
| 2164 | eassert (input_blocked_p ()); | 2339 | eassert (input_blocked_p ()); |
| 2165 | gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL); | 2340 | gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL); |
| 2166 | XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height); | 2341 | XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, |
| 2342 | ximg->width, ximg->height); | ||
| 2167 | XFreeGC (FRAME_X_DISPLAY (f), gc); | 2343 | XFreeGC (FRAME_X_DISPLAY (f), gc); |
| 2168 | #endif /* HAVE_X_WINDOWS */ | 2344 | #endif /* HAVE_X_WINDOWS */ |
| 2169 | 2345 | ||
| @@ -2192,7 +2368,13 @@ image_create_x_image_and_pixmap (struct frame *f, struct image *img, | |||
| 2192 | eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP); | 2368 | eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP); |
| 2193 | 2369 | ||
| 2194 | return x_create_x_image_and_pixmap (f, width, height, depth, ximg, | 2370 | return x_create_x_image_and_pixmap (f, width, height, depth, ximg, |
| 2195 | !mask_p ? &img->pixmap : &img->mask); | 2371 | !mask_p ? &img->pixmap : &img->mask, |
| 2372 | #ifdef HAVE_XRENDER | ||
| 2373 | !mask_p ? &img->picture : &img->mask_picture | ||
| 2374 | #else | ||
| 2375 | NULL | ||
| 2376 | #endif | ||
| 2377 | ); | ||
| 2196 | } | 2378 | } |
| 2197 | 2379 | ||
| 2198 | /* Put X image XIMG into image IMG on frame F, as a mask if and only | 2380 | /* Put X image XIMG into image IMG on frame F, as a mask if and only |
| @@ -8101,105 +8283,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 8101 | ImageMagick | 8283 | ImageMagick |
| 8102 | ***********************************************************************/ | 8284 | ***********************************************************************/ |
| 8103 | 8285 | ||
| 8104 | /* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER, | ||
| 8105 | safely rounded and clipped to int range. */ | ||
| 8106 | |||
| 8107 | static int | ||
| 8108 | scale_image_size (int size, size_t divisor, size_t multiplier) | ||
| 8109 | { | ||
| 8110 | if (divisor != 0) | ||
| 8111 | { | ||
| 8112 | double s = size; | ||
| 8113 | double scaled = s * multiplier / divisor + 0.5; | ||
| 8114 | if (scaled < INT_MAX) | ||
| 8115 | return scaled; | ||
| 8116 | } | ||
| 8117 | return INT_MAX; | ||
| 8118 | } | ||
| 8119 | |||
| 8120 | /* Compute the desired size of an image with native size WIDTH x HEIGHT. | ||
| 8121 | Use SPEC to deduce the size. Store the desired size into | ||
| 8122 | *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ | ||
| 8123 | static void | ||
| 8124 | compute_image_size (size_t width, size_t height, | ||
| 8125 | Lisp_Object spec, | ||
| 8126 | int *d_width, int *d_height) | ||
| 8127 | { | ||
| 8128 | Lisp_Object value; | ||
| 8129 | int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1; | ||
| 8130 | double scale = 1; | ||
| 8131 | |||
| 8132 | value = image_spec_value (spec, QCscale, NULL); | ||
| 8133 | if (NUMBERP (value)) | ||
| 8134 | scale = XFLOATINT (value); | ||
| 8135 | |||
| 8136 | value = image_spec_value (spec, QCmax_width, NULL); | ||
| 8137 | if (FIXNATP (value)) | ||
| 8138 | max_width = min (XFIXNAT (value), INT_MAX); | ||
| 8139 | |||
| 8140 | value = image_spec_value (spec, QCmax_height, NULL); | ||
| 8141 | if (FIXNATP (value)) | ||
| 8142 | max_height = min (XFIXNAT (value), INT_MAX); | ||
| 8143 | |||
| 8144 | /* If width and/or height is set in the display spec assume we want | ||
| 8145 | to scale to those values. If either h or w is unspecified, the | ||
| 8146 | unspecified should be calculated from the specified to preserve | ||
| 8147 | aspect ratio. */ | ||
| 8148 | value = image_spec_value (spec, QCwidth, NULL); | ||
| 8149 | if (FIXNATP (value)) | ||
| 8150 | { | ||
| 8151 | desired_width = min (XFIXNAT (value) * scale, INT_MAX); | ||
| 8152 | /* :width overrides :max-width. */ | ||
| 8153 | max_width = -1; | ||
| 8154 | } | ||
| 8155 | |||
| 8156 | value = image_spec_value (spec, QCheight, NULL); | ||
| 8157 | if (FIXNATP (value)) | ||
| 8158 | { | ||
| 8159 | desired_height = min (XFIXNAT (value) * scale, INT_MAX); | ||
| 8160 | /* :height overrides :max-height. */ | ||
| 8161 | max_height = -1; | ||
| 8162 | } | ||
| 8163 | |||
| 8164 | /* If we have both width/height set explicitly, we skip past all the | ||
| 8165 | aspect ratio-preserving computations below. */ | ||
| 8166 | if (desired_width != -1 && desired_height != -1) | ||
| 8167 | goto out; | ||
| 8168 | |||
| 8169 | width = width * scale; | ||
| 8170 | height = height * scale; | ||
| 8171 | |||
| 8172 | if (desired_width != -1) | ||
| 8173 | /* Width known, calculate height. */ | ||
| 8174 | desired_height = scale_image_size (desired_width, width, height); | ||
| 8175 | else if (desired_height != -1) | ||
| 8176 | /* Height known, calculate width. */ | ||
| 8177 | desired_width = scale_image_size (desired_height, height, width); | ||
| 8178 | else | ||
| 8179 | { | ||
| 8180 | desired_width = width; | ||
| 8181 | desired_height = height; | ||
| 8182 | } | ||
| 8183 | |||
| 8184 | if (max_width != -1 && desired_width > max_width) | ||
| 8185 | { | ||
| 8186 | /* The image is wider than :max-width. */ | ||
| 8187 | desired_width = max_width; | ||
| 8188 | desired_height = scale_image_size (desired_width, width, height); | ||
| 8189 | } | ||
| 8190 | |||
| 8191 | if (max_height != -1 && desired_height > max_height) | ||
| 8192 | { | ||
| 8193 | /* The image is higher than :max-height. */ | ||
| 8194 | desired_height = max_height; | ||
| 8195 | desired_width = scale_image_size (desired_height, height, width); | ||
| 8196 | } | ||
| 8197 | |||
| 8198 | out: | ||
| 8199 | *d_width = desired_width; | ||
| 8200 | *d_height = desired_height; | ||
| 8201 | } | ||
| 8202 | |||
| 8203 | static bool imagemagick_image_p (Lisp_Object); | 8286 | static bool imagemagick_image_p (Lisp_Object); |
| 8204 | static bool imagemagick_load (struct frame *, struct image *); | 8287 | static bool imagemagick_load (struct frame *, struct image *); |
| 8205 | static void imagemagick_clear_image (struct frame *, struct image *); | 8288 | static void imagemagick_clear_image (struct frame *, struct image *); |
| @@ -9816,6 +9899,25 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, | |||
| 9816 | Initialization | 9899 | Initialization |
| 9817 | ***********************************************************************/ | 9900 | ***********************************************************************/ |
| 9818 | 9901 | ||
| 9902 | DEFUN ("image-scaling-p", Fimage_scaling_p, Simage_scaling_p, 0, 1, 0, | ||
| 9903 | doc: /* Test whether FRAME supports resizing images. | ||
| 9904 | Return t if FRAME supports native scaling, nil otherwise. */) | ||
| 9905 | (Lisp_Object frame) | ||
| 9906 | { | ||
| 9907 | #ifdef HAVE_NS | ||
| 9908 | return Qt; | ||
| 9909 | #elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER) | ||
| 9910 | int event_basep, error_basep; | ||
| 9911 | |||
| 9912 | if (XRenderQueryExtension | ||
| 9913 | (FRAME_X_DISPLAY (decode_window_system_frame (frame)), | ||
| 9914 | &event_basep, &error_basep)) | ||
| 9915 | return Qt; | ||
| 9916 | #endif | ||
| 9917 | |||
| 9918 | return Qnil; | ||
| 9919 | } | ||
| 9920 | |||
| 9819 | DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0, | 9921 | DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0, |
| 9820 | doc: /* Initialize image library implementing image type TYPE. | 9922 | doc: /* Initialize image library implementing image type TYPE. |
| 9821 | Return non-nil if TYPE is a supported image type. | 9923 | Return non-nil if TYPE is a supported image type. |
| @@ -10058,6 +10160,8 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 10058 | defsubr (&Slookup_image); | 10160 | defsubr (&Slookup_image); |
| 10059 | #endif | 10161 | #endif |
| 10060 | 10162 | ||
| 10163 | defsubr (&Simage_scaling_p); | ||
| 10164 | |||
| 10061 | DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images, | 10165 | DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images, |
| 10062 | doc: /* Non-nil means always draw a cross over disabled images. | 10166 | doc: /* Non-nil means always draw a cross over disabled images. |
| 10063 | Disabled images are those having a `:conversion disabled' property. | 10167 | Disabled images are those having a `:conversion disabled' property. |