diff options
| author | Eli Zaretskii | 2020-04-19 21:09:20 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2020-04-19 21:09:20 +0300 |
| commit | 423089d18b6a8528dc3c70dce28c7011680e18be (patch) | |
| tree | 35aee5f364df6829f69c7f4ef5b2e4d6de9b2f44 /src | |
| parent | 3f8b771da96f9a55dd5ed322104135a0c2c6f2e4 (diff) | |
| download | emacs-423089d18b6a8528dc3c70dce28c7011680e18be.tar.gz emacs-423089d18b6a8528dc3c70dce28c7011680e18be.zip | |
Rework how GDI+ functions are loaded dynamically in w32image.c
* src/w32image.c: Define correct WINGDIPAPI typedefs for GDI+
functions. We cannot use DEF_DLL_FN, since that is for functions
with C calling conventions, whereas GDI+ functions are __stdcall.
(gdiplus_init): Load functions from DLL manually, not via
LOAD_DLL_FN, as the latter is for __cdecl functions.
(w32_frame_delay): Initialize delay with a negative value, as zero
is a valid delay.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32image.c | 145 |
1 files changed, 102 insertions, 43 deletions
diff --git a/src/w32image.c b/src/w32image.c index 31c9b852ace..085a5db3abd 100644 --- a/src/w32image.c +++ b/src/w32image.c | |||
| @@ -40,28 +40,47 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 40 | 40 | ||
| 41 | #ifdef WINDOWSNT | 41 | #ifdef WINDOWSNT |
| 42 | 42 | ||
| 43 | DEF_DLL_FN (GpStatus, GdiplusStartup, | 43 | typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc) |
| 44 | (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *)); | 44 | (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *); |
| 45 | DEF_DLL_FN (VOID, GdiplusShutdown, (ULONG_PTR)); | 45 | typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR); |
| 46 | DEF_DLL_FN (GpStatus, GdipGetPropertyItemSize, | 46 | typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc) |
| 47 | (GpImage *, PROPID, UINT *)); | 47 | (GpImage *, PROPID, UINT *); |
| 48 | DEF_DLL_FN (GpStatus, GdipGetPropertyItem, | 48 | typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc) |
| 49 | (GpImage *, PROPID, UINT, PropertyItem *)); | 49 | (GpImage *, PROPID, UINT, PropertyItem *); |
| 50 | DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsCount, (GpImage *, UINT *)); | 50 | typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsCount_Proc) |
| 51 | DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsList, | 51 | (GpImage *, UINT *); |
| 52 | (GpImage *, GUID *, UINT)); | 52 | typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsList_Proc) |
| 53 | DEF_DLL_FN (GpStatus, GdipImageGetFrameCount, | 53 | (GpImage *, GUID *, UINT); |
| 54 | (GpImage *, GDIPCONST GUID *, UINT *)); | 54 | typedef GpStatus (WINGDIPAPI *GdipImageGetFrameCount_Proc) |
| 55 | DEF_DLL_FN (GpStatus, GdipImageSelectActiveFrame, | 55 | (GpImage *, GDIPCONST GUID *, UINT *); |
| 56 | (GpImage*, GDIPCONST GUID *, UINT)); | 56 | typedef GpStatus (WINGDIPAPI *GdipImageSelectActiveFrame_Proc) |
| 57 | DEF_DLL_FN (GpStatus, GdipCreateBitmapFromFile, (WCHAR *, GpBitmap **)); | 57 | (GpImage*, GDIPCONST GUID *, UINT); |
| 58 | DEF_DLL_FN (GpStatus, GdipCreateBitmapFromStream, (IStream *, GpBitmap **)); | 58 | typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromFile_Proc) |
| 59 | DEF_DLL_FN (IStream *, SHCreateMemStream, (const BYTE *pInit, UINT cbInit)); | 59 | (WCHAR *, GpBitmap **); |
| 60 | DEF_DLL_FN (GpStatus, GdipCreateHBITMAPFromBitmap, | 60 | typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc) |
| 61 | (GpBitmap *, HBITMAP *, ARGB)); | 61 | (IStream *, GpBitmap **); |
| 62 | DEF_DLL_FN (GpStatus, GdipDisposeImage, (GpImage *)); | 62 | typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT); |
| 63 | DEF_DLL_FN (GpStatus, GdipGetImageHeight, (GpImage *, UINT *)); | 63 | typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc) |
| 64 | DEF_DLL_FN (GpStatus, GdipGetImageWidth, (GpImage *, UINT *)); | 64 | (GpBitmap *, HBITMAP *, ARGB); |
| 65 | typedef GpStatus (WINGDIPAPI *GdipDisposeImage_Proc) (GpImage *); | ||
| 66 | typedef GpStatus (WINGDIPAPI *GdipGetImageHeight_Proc) (GpImage *, UINT *); | ||
| 67 | typedef GpStatus (WINGDIPAPI *GdipGetImageWidth_Proc) (GpImage *, UINT *); | ||
| 68 | |||
| 69 | GdiplusStartup_Proc fn_GdiplusStartup; | ||
| 70 | GdiplusShutdown_Proc fn_GdiplusShutdown; | ||
| 71 | GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize; | ||
| 72 | GdipGetPropertyItem_Proc fn_GdipGetPropertyItem; | ||
| 73 | GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount; | ||
| 74 | GdipImageGetFrameDimensionsList_Proc fn_GdipImageGetFrameDimensionsList; | ||
| 75 | GdipImageGetFrameCount_Proc fn_GdipImageGetFrameCount; | ||
| 76 | GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame; | ||
| 77 | GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile; | ||
| 78 | GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream; | ||
| 79 | SHCreateMemStream_Proc fn_SHCreateMemStream; | ||
| 80 | GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap; | ||
| 81 | GdipDisposeImage_Proc fn_GdipDisposeImage; | ||
| 82 | GdipGetImageHeight_Proc fn_GdipGetImageHeight; | ||
| 83 | GdipGetImageWidth_Proc fn_GdipGetImageWidth; | ||
| 65 | 84 | ||
| 66 | static bool | 85 | static bool |
| 67 | gdiplus_init (void) | 86 | gdiplus_init (void) |
| @@ -72,33 +91,73 @@ gdiplus_init (void) | |||
| 72 | && (shlwapi_lib = w32_delayed_load (Qshlwapi)))) | 91 | && (shlwapi_lib = w32_delayed_load (Qshlwapi)))) |
| 73 | return false; | 92 | return false; |
| 74 | 93 | ||
| 75 | LOAD_DLL_FN (gdiplus_lib, GdiplusStartup); | 94 | fn_GdiplusStartup = (GdiplusStartup_Proc) |
| 76 | LOAD_DLL_FN (gdiplus_lib, GdiplusShutdown); | 95 | get_proc_addr (gdiplus_lib, "GdiplusStartup"); |
| 77 | LOAD_DLL_FN (gdiplus_lib, GdipGetPropertyItemSize); | 96 | if (!fn_GdiplusStartup) |
| 78 | LOAD_DLL_FN (gdiplus_lib, GdipGetPropertyItem); | 97 | return false; |
| 79 | LOAD_DLL_FN (gdiplus_lib, GdipImageGetFrameDimensionsCount); | 98 | fn_GdiplusShutdown = (GdiplusShutdown_Proc) |
| 80 | LOAD_DLL_FN (gdiplus_lib, GdipImageGetFrameDimensionsList); | 99 | get_proc_addr (gdiplus_lib, "GdiplusShutdown"); |
| 81 | LOAD_DLL_FN (gdiplus_lib, GdipImageGetFrameCount); | 100 | if (!fn_GdiplusShutdown) |
| 82 | LOAD_DLL_FN (gdiplus_lib, GdipImageSelectActiveFrame); | 101 | return false; |
| 83 | LOAD_DLL_FN (gdiplus_lib, GdipCreateBitmapFromFile); | 102 | fn_GdipGetPropertyItemSize = (GdipGetPropertyItemSize_Proc) |
| 84 | LOAD_DLL_FN (gdiplus_lib, GdipCreateBitmapFromStream); | 103 | get_proc_addr (gdiplus_lib, "GdipGetPropertyItemSize"); |
| 85 | LOAD_DLL_FN (gdiplus_lib, GdipCreateHBITMAPFromBitmap); | 104 | if (!fn_GdipGetPropertyItemSize) |
| 86 | LOAD_DLL_FN (gdiplus_lib, GdipDisposeImage); | 105 | return false; |
| 87 | LOAD_DLL_FN (gdiplus_lib, GdipGetImageHeight); | 106 | fn_GdipGetPropertyItem = (GdipGetPropertyItem_Proc) |
| 88 | LOAD_DLL_FN (gdiplus_lib, GdipGetImageWidth); | 107 | get_proc_addr (gdiplus_lib, "GdipGetPropertyItem"); |
| 108 | if (!fn_GdipGetPropertyItem) | ||
| 109 | return false; | ||
| 110 | fn_GdipImageGetFrameDimensionsCount = (GdipImageGetFrameDimensionsCount_Proc) | ||
| 111 | get_proc_addr (gdiplus_lib, "GdipImageGetFrameDimensionsCount"); | ||
| 112 | if (!fn_GdipImageGetFrameDimensionsCount) | ||
| 113 | return false; | ||
| 114 | fn_GdipImageGetFrameDimensionsList = (GdipImageGetFrameDimensionsList_Proc) | ||
| 115 | get_proc_addr (gdiplus_lib, "GdipImageGetFrameDimensionsList"); | ||
| 116 | if (!fn_GdipImageGetFrameDimensionsList) | ||
| 117 | return false; | ||
| 118 | fn_GdipImageGetFrameCount = (GdipImageGetFrameCount_Proc) | ||
| 119 | get_proc_addr (gdiplus_lib, "GdipImageGetFrameCount"); | ||
| 120 | if (!fn_GdipImageGetFrameCount) | ||
| 121 | return false; | ||
| 122 | fn_GdipImageSelectActiveFrame = (GdipImageSelectActiveFrame_Proc) | ||
| 123 | get_proc_addr (gdiplus_lib, "GdipImageSelectActiveFrame"); | ||
| 124 | if (!fn_GdipImageSelectActiveFrame) | ||
| 125 | return false; | ||
| 126 | fn_GdipCreateBitmapFromFile = (GdipCreateBitmapFromFile_Proc) | ||
| 127 | get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromFile"); | ||
| 128 | if (!fn_GdipCreateBitmapFromFile) | ||
| 129 | return false; | ||
| 130 | fn_GdipCreateBitmapFromStream = (GdipCreateBitmapFromStream_Proc) | ||
| 131 | get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromStream"); | ||
| 132 | if (!fn_GdipCreateBitmapFromStream) | ||
| 133 | return false; | ||
| 134 | fn_GdipCreateHBITMAPFromBitmap = (GdipCreateHBITMAPFromBitmap_Proc) | ||
| 135 | get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap"); | ||
| 136 | if (!fn_GdipCreateHBITMAPFromBitmap) | ||
| 137 | return false; | ||
| 138 | fn_GdipDisposeImage = (GdipDisposeImage_Proc) | ||
| 139 | get_proc_addr (gdiplus_lib, "GdipDisposeImage"); | ||
| 140 | if (!fn_GdipDisposeImage) | ||
| 141 | return false; | ||
| 142 | fn_GdipGetImageHeight = (GdipGetImageHeight_Proc) | ||
| 143 | get_proc_addr (gdiplus_lib, "GdipGetImageHeight"); | ||
| 144 | if (!fn_GdipGetImageHeight) | ||
| 145 | return false; | ||
| 146 | fn_GdipGetImageWidth = (GdipGetImageWidth_Proc) | ||
| 147 | get_proc_addr (gdiplus_lib, "GdipGetImageWidth"); | ||
| 148 | if (!fn_GdipGetImageWidth) | ||
| 149 | return false; | ||
| 89 | /* LOAD_DLL_FN (shlwapi_lib, SHCreateMemStream); */ | 150 | /* LOAD_DLL_FN (shlwapi_lib, SHCreateMemStream); */ |
| 90 | 151 | ||
| 91 | /* The following terrible kludge is required to use native image API | 152 | /* The following terrible kludge is required to use native image API |
| 92 | on Windows before Vista, because SHCreateMemStream was not | 153 | on Windows before Vista, because SHCreateMemStream was not |
| 93 | exported by name in those versions, only by ordinal number. */ | 154 | exported by name in those versions, only by ordinal number. */ |
| 94 | fn_SHCreateMemStream = | 155 | fn_SHCreateMemStream = (SHCreateMemStream_Proc) |
| 95 | (W32_PFN_SHCreateMemStream) get_proc_addr (shlwapi_lib, | 156 | get_proc_addr (shlwapi_lib, "SHCreateMemStream"); |
| 96 | "SHCreateMemStream"); | ||
| 97 | if (!fn_SHCreateMemStream) | 157 | if (!fn_SHCreateMemStream) |
| 98 | { | 158 | { |
| 99 | fn_SHCreateMemStream = | 159 | fn_SHCreateMemStream = (SHCreateMemStream_Proc) |
| 100 | (W32_PFN_SHCreateMemStream) get_proc_addr (shlwapi_lib, | 160 | get_proc_addr (shlwapi_lib, MAKEINTRESOURCEA (12)); |
| 101 | MAKEINTRESOURCEA (12)); | ||
| 102 | if (!fn_SHCreateMemStream) | 161 | if (!fn_SHCreateMemStream) |
| 103 | return false; | 162 | return false; |
| 104 | } | 163 | } |
| @@ -293,7 +352,7 @@ w32_select_active_frame (GpBitmap *pBitmap, int frame, int *nframes, | |||
| 293 | 352 | ||
| 294 | status = GdipImageGetFrameDimensionsCount (pBitmap, &count); | 353 | status = GdipImageGetFrameDimensionsCount (pBitmap, &count); |
| 295 | frameCount = *nframes = 0; | 354 | frameCount = *nframes = 0; |
| 296 | *delay = 0.0; | 355 | *delay = -1.0; |
| 297 | if (count) | 356 | if (count) |
| 298 | { | 357 | { |
| 299 | /* The following call will fill pDimensionIDs[0] with the | 358 | /* The following call will fill pDimensionIDs[0] with the |