diff options
| author | Eli Zaretskii | 2019-06-29 14:51:41 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2019-06-29 14:51:41 +0300 |
| commit | 74a5a332fee8a346cf65ed6656c1b08dc1df5fde (patch) | |
| tree | 9b6488ab0dccc372c643f5b521e731f26886cfb4 /src/w32term.c | |
| parent | 67b50770c050c55a26cd13b9568b01a80a449885 (diff) | |
| download | emacs-74a5a332fee8a346cf65ed6656c1b08dc1df5fde.tar.gz emacs-74a5a332fee8a346cf65ed6656c1b08dc1df5fde.zip | |
Support native image transforms on MS-Windows
This changeset also rearranges native image transform code
for other platforms to make it cleaner, and also removes
the support for native cropping. For the discussions, see
https://lists.gnu.org/archive/html/emacs-devel/2019-06/msg00242.html
* src/w32term.c (w32_image_rotations_p, transform): New functions.
(w32_draw_image_foreground): If image rotation is requested
and supported, call PlgBlt to transform the image.
(w32_initialize): Populate the PlgBlt function pointer if it
is supported.
* src/w32term.h (w32_image_rotations_p): Add prototype.
* src/dispextern.h (struct image) [HAVE_NTGUI]: New member xform.
* src/image.c (compute_image_rotation): Renamed from
image_set_rotation. Only compute and returns the rotation
angle; leave the matrix calculation for later. Log an error
message if the :rotation parameter is not a number.
(image_set_crop): Function deleted. We no longer support
native cropping, as one can display an image slice instead.
(image_set_transform): Compute the transform matrix in its
entirety here, in two variants: one for XRender and Cairo, the
other for NS and MS-Windows. call compute_image_size and
compute_image_rotation internally.
(lookup_image) [HAVE_NATIVE_TRANSFORMS]: Call only
image_set_transform. No need to pass the transform matrix to
image_set_transform.
(Fimage_transforms_p): Return a list of transform capabilities
rather than a simple boolean. Support TTY frames as well.
* src/nsimage.m (setTransform:): Don't invert the matrix, as
it is already inverted in image.c.
* test/manual/image-transforms-tests.el (test-cropping): State
in the text that only ImageMagick supports cropping.
* doc/lispref/display.texi (Image Descriptors): Update the
documentation of native image transforms.
(ImageMagick Images): Move the description of ':crop' here.
* etc/NEWS: Minor copyedits of the feature announcement.
Diffstat (limited to 'src/w32term.c')
| -rw-r--r-- | src/w32term.c | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/src/w32term.c b/src/w32term.c index 97a5fc63892..c6e175e7e5c 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -117,6 +117,10 @@ typedef struct tagGLYPHSET | |||
| 117 | /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */ | 117 | /* Dynamic linking to SetLayeredWindowAttribute (only since 2000). */ |
| 118 | BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD); | 118 | BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD); |
| 119 | 119 | ||
| 120 | /* PlgBlt is available since Windows 2000. */ | ||
| 121 | BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int); | ||
| 122 | |||
| 123 | |||
| 120 | #ifndef LWA_ALPHA | 124 | #ifndef LWA_ALPHA |
| 121 | #define LWA_ALPHA 0x02 | 125 | #define LWA_ALPHA 0x02 |
| 122 | #endif | 126 | #endif |
| @@ -1753,6 +1757,26 @@ w32_draw_glyph_string_box (struct glyph_string *s) | |||
| 1753 | } | 1757 | } |
| 1754 | } | 1758 | } |
| 1755 | 1759 | ||
| 1760 | bool | ||
| 1761 | w32_image_rotations_p (void) | ||
| 1762 | { | ||
| 1763 | return pfnPlgBlt != NULL; | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | static POINT | ||
| 1767 | transform (int x0, int y0, int x, int y, XFORM *xform) | ||
| 1768 | { | ||
| 1769 | POINT pt; | ||
| 1770 | |||
| 1771 | /* See https://docs.microsoft.com/en-us/windows/desktop/api/Wingdi/nf-wingdi-setworldtransform */ | ||
| 1772 | pt.x = | ||
| 1773 | x0 + (x - x0) * xform->eM11 + (y - y0) * xform->eM21 + xform->eDx + 0.5f; | ||
| 1774 | pt.y = | ||
| 1775 | y0 + (x - x0) * xform->eM12 + (y - y0) * xform->eM22 + xform->eDy + 0.5f; | ||
| 1776 | |||
| 1777 | return pt; | ||
| 1778 | } | ||
| 1779 | |||
| 1756 | 1780 | ||
| 1757 | /* Draw foreground of image glyph string S. */ | 1781 | /* Draw foreground of image glyph string S. */ |
| 1758 | 1782 | ||
| @@ -1798,20 +1822,31 @@ w32_draw_image_foreground (struct glyph_string *s) | |||
| 1798 | } | 1822 | } |
| 1799 | else | 1823 | else |
| 1800 | { | 1824 | { |
| 1801 | DebPrint (("w32_draw_image_foreground: GetObject failed!\n")); | 1825 | DebPrint (("w32_draw_image_foreground: GetObject(pixmap) failed!\n")); |
| 1802 | orig_width = s->slice.width; | 1826 | orig_width = s->slice.width; |
| 1803 | orig_height = s->slice.height; | 1827 | orig_height = s->slice.height; |
| 1804 | } | 1828 | } |
| 1805 | 1829 | ||
| 1806 | double w_factor = 1.0, h_factor = 1.0; | 1830 | double w_factor = 1.0, h_factor = 1.0; |
| 1807 | bool scaled = false; | 1831 | bool scaled = false, need_xform = false; |
| 1808 | int orig_slice_width = s->slice.width, | 1832 | int orig_slice_width = s->slice.width, |
| 1809 | orig_slice_height = s->slice.height; | 1833 | orig_slice_height = s->slice.height; |
| 1810 | int orig_slice_x = s->slice.x, orig_slice_y = s->slice.y; | 1834 | int orig_slice_x = s->slice.x, orig_slice_y = s->slice.y; |
| 1811 | /* For scaled images we need to restore the original slice's | 1835 | POINT corner[3]; |
| 1812 | dimensions and origin coordinates, from before the scaling. */ | 1836 | if ((s->img->xform.eM12 != 0 || s->img->xform.eM21 != 0 |
| 1813 | if (s->img->width != orig_width || s->img->height != orig_height) | 1837 | || s->img->xform.eDx != 0 || s->img->xform.eDy != 0) |
| 1838 | /* PlgBlt is not available on Windows 9X. */ | ||
| 1839 | && pfnPlgBlt) | ||
| 1814 | { | 1840 | { |
| 1841 | need_xform = true; | ||
| 1842 | corner[0] = transform (x, y, x, y, &s->img->xform); | ||
| 1843 | corner[1] = transform (x, y, x + orig_width, y, &s->img->xform); | ||
| 1844 | corner[2] = transform (x, y, x, y + orig_height, &s->img->xform); | ||
| 1845 | } | ||
| 1846 | else if (s->img->width != orig_width || s->img->height != orig_height) | ||
| 1847 | { | ||
| 1848 | /* For scaled images we need to restore the original slice's | ||
| 1849 | dimensions and origin coordinates, from before the scaling. */ | ||
| 1815 | scaled = true; | 1850 | scaled = true; |
| 1816 | w_factor = (double) orig_width / (double) s->img->width; | 1851 | w_factor = (double) orig_width / (double) s->img->width; |
| 1817 | h_factor = (double) orig_height / (double) s->img->height; | 1852 | h_factor = (double) orig_height / (double) s->img->height; |
| @@ -1828,7 +1863,15 @@ w32_draw_image_foreground (struct glyph_string *s) | |||
| 1828 | 1863 | ||
| 1829 | SetTextColor (s->hdc, RGB (255, 255, 255)); | 1864 | SetTextColor (s->hdc, RGB (255, 255, 255)); |
| 1830 | SetBkColor (s->hdc, RGB (0, 0, 0)); | 1865 | SetBkColor (s->hdc, RGB (0, 0, 0)); |
| 1831 | if (!scaled) | 1866 | if (need_xform) |
| 1867 | { | ||
| 1868 | if (!pfnPlgBlt (s->hdc, corner, compat_hdc, | ||
| 1869 | s->slice.x, s->slice.y, | ||
| 1870 | orig_width, orig_height, | ||
| 1871 | s->img->mask, s->slice.x, s->slice.y)) | ||
| 1872 | DebPrint (("PlgBlt failed!")); | ||
| 1873 | } | ||
| 1874 | else if (!scaled) | ||
| 1832 | { | 1875 | { |
| 1833 | BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, | 1876 | BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, |
| 1834 | compat_hdc, s->slice.x, s->slice.y, SRCINVERT); | 1877 | compat_hdc, s->slice.x, s->slice.y, SRCINVERT); |
| @@ -1865,7 +1908,14 @@ w32_draw_image_foreground (struct glyph_string *s) | |||
| 1865 | { | 1908 | { |
| 1866 | SetTextColor (s->hdc, s->gc->foreground); | 1909 | SetTextColor (s->hdc, s->gc->foreground); |
| 1867 | SetBkColor (s->hdc, s->gc->background); | 1910 | SetBkColor (s->hdc, s->gc->background); |
| 1868 | if (!scaled) | 1911 | if (need_xform) |
| 1912 | { | ||
| 1913 | if (!pfnPlgBlt (s->hdc, corner, compat_hdc, | ||
| 1914 | s->slice.x, s->slice.y, | ||
| 1915 | orig_width, orig_height, NULL, 0, 0)) | ||
| 1916 | DebPrint (("PlgBlt failed!")); | ||
| 1917 | } | ||
| 1918 | else if (!scaled) | ||
| 1869 | BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, | 1919 | BitBlt (s->hdc, x, y, s->slice.width, s->slice.height, |
| 1870 | compat_hdc, s->slice.x, s->slice.y, SRCCOPY); | 1920 | compat_hdc, s->slice.x, s->slice.y, SRCCOPY); |
| 1871 | else | 1921 | else |
| @@ -7354,6 +7404,11 @@ w32_initialize (void) | |||
| 7354 | 7404 | ||
| 7355 | LOAD_PROC (user_lib, SetLayeredWindowAttributes); | 7405 | LOAD_PROC (user_lib, SetLayeredWindowAttributes); |
| 7356 | 7406 | ||
| 7407 | /* PlgBlt is not available on Windows 9X. */ | ||
| 7408 | HMODULE hgdi = LoadLibrary ("gdi32.dll"); | ||
| 7409 | if (hgdi) | ||
| 7410 | LOAD_PROC (hgdi, PlgBlt); | ||
| 7411 | |||
| 7357 | #undef LOAD_PROC | 7412 | #undef LOAD_PROC |
| 7358 | 7413 | ||
| 7359 | /* Ensure scrollbar handles are at least 5 pixels. */ | 7414 | /* Ensure scrollbar handles are at least 5 pixels. */ |