main
cpp 250 lines 7.33 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 #include "precomp.h"
4
5 using namespace Gdiplus;
6
7
8 // Exit macros
9 #define GdipExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_GDIPUTIL, x, s, __VA_ARGS__)
10 #define GdipExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_GDIPUTIL, x, s, __VA_ARGS__)
11 #define GdipExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_GDIPUTIL, x, s, __VA_ARGS__)
12 #define GdipExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_GDIPUTIL, x, s, __VA_ARGS__)
13 #define GdipExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_GDIPUTIL, x, s, __VA_ARGS__)
14 #define GdipExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_GDIPUTIL, x, s, __VA_ARGS__)
15 #define GdipExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_GDIPUTIL, p, x, e, s, __VA_ARGS__)
16 #define GdipExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_GDIPUTIL, p, x, s, __VA_ARGS__)
17 #define GdipExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_GDIPUTIL, p, x, e, s, __VA_ARGS__)
18 #define GdipExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_GDIPUTIL, p, x, s, __VA_ARGS__)
19 #define GdipExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_GDIPUTIL, e, x, s, __VA_ARGS__)
20 #define GdipExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_GDIPUTIL, g, x, s, __VA_ARGS__)
21
22 /********************************************************************
23 GdipInitialize - initializes GDI+.
24
25 Note: pOutput must be non-NULL if pInput->SuppressBackgroundThread
26 is TRUE. See GdiplusStartup() for more information.
27 ********************************************************************/
28 extern "C" HRESULT DAPI GdipInitialize(
29 __in const Gdiplus::GdiplusStartupInput* pInput,
30 __out ULONG_PTR* pToken,
31 __out_opt Gdiplus::GdiplusStartupOutput *pOutput
32 )
33 {
34 AssertSz(!pInput->SuppressBackgroundThread || pOutput, "pOutput required if background thread suppressed.");
35
36 HRESULT hr = S_OK;
37 Status status = Ok;
38
39 status = GdiplusStartup(pToken, pInput, pOutput);
40 GdipExitOnGdipFailure(status, hr, "Failed to initialize GDI+.");
41
42 LExit:
43 return hr;
44 }
45
46 /********************************************************************
47 GdipUninitialize - uninitializes GDI+.
48
49 ********************************************************************/
50 extern "C" void DAPI GdipUninitialize(
51 __in ULONG_PTR token
52 )
53 {
54 GdiplusShutdown(token);
55 }
56
57 /********************************************************************
58 GdipBitmapFromResource - read a GDI+ image out of a resource stream
59 of type RT_RCDATA.
60
61 ********************************************************************/
62 extern "C" HRESULT DAPI GdipBitmapFromResource(
63 __in_opt HINSTANCE hinst,
64 __in_z LPCSTR szId,
65 __out Bitmap **ppBitmap
66 )
67 {
68 HRESULT hr = S_OK;
69 LPVOID pvData = NULL;
70 DWORD cbData = 0;
71 HGLOBAL hGlobal = NULL;
72 LPVOID pv = NULL;
73 IStream *pStream = NULL;
74 Bitmap *pBitmap = NULL;
75 Status gs = Ok;
76
77 // Use ResReadData (RT_RCDATA) instead of Bitmap::FromResource (RT_BITMAP) to support all file formats that GDI+ supports.
78 hr = ResReadData(hinst, szId, &pvData, &cbData);
79 GdipExitOnFailure(hr, "Failed to load GDI+ bitmap from resource.");
80
81 // Have to copy the fixed resource data into moveable (heap) memory
82 // since that's what GDI+ expects.
83 hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, cbData);
84 GdipExitOnNullWithLastError(hGlobal, hr, "Failed to allocate global memory.");
85
86 pv = ::GlobalLock(hGlobal);
87 GdipExitOnNullWithLastError(pv, hr, "Failed to lock global memory.");
88
89 memcpy(pv, pvData, cbData);
90
91 ::GlobalUnlock(pv); // no point taking any more memory than we have already
92 pv = NULL;
93
94 hr = ::CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
95 GdipExitOnFailure(hr, "Failed to allocate stream from global memory.");
96
97 hGlobal = NULL; // we gave the global memory to the stream object so it will close it
98
99 pBitmap = Bitmap::FromStream(pStream);
100 GdipExitOnNull(pBitmap, hr, E_OUTOFMEMORY, "Failed to allocate bitmap from stream.");
101
102 gs = pBitmap->GetLastStatus();
103 GdipExitOnGdipFailure(gs, hr, "Failed to load bitmap from stream.");
104
105 *ppBitmap = pBitmap;
106 pBitmap = NULL;
107
108 LExit:
109 if (pBitmap)
110 {
111 delete pBitmap;
112 }
113
114 ReleaseObject(pStream);
115
116 if (pv)
117 {
118 ::GlobalUnlock(pv);
119 }
120
121 if (hGlobal)
122 {
123 ::GlobalFree(hGlobal);
124 }
125
126 return hr;
127 }
128
129
130 /********************************************************************
131 GdipBitmapFromFile - read a GDI+ image from a file.
132
133 ********************************************************************/
134 extern "C" HRESULT DAPI GdipBitmapFromFile(
135 __in_z LPCWSTR wzFileName,
136 __out Bitmap **ppBitmap
137 )
138 {
139 HRESULT hr = S_OK;
140 Bitmap *pBitmap = NULL;
141 Status gs = Ok;
142
143 GdipExitOnNull(ppBitmap, hr, E_INVALIDARG, "Invalid null wzFileName");
144
145 pBitmap = Bitmap::FromFile(wzFileName);
146 GdipExitOnNull(pBitmap, hr, E_OUTOFMEMORY, "Failed to allocate bitmap from file.");
147
148 gs = pBitmap->GetLastStatus();
149 GdipExitOnGdipFailure(gs, hr, "Failed to load bitmap from file: %ls", wzFileName);
150
151 *ppBitmap = pBitmap;
152 pBitmap = NULL;
153
154 LExit:
155 if (pBitmap)
156 {
157 delete pBitmap;
158 }
159
160 return hr;
161 }
162
163
164 /********************************************************************
165 GdipBitmapToGdiBitmap - convert Gdiplus::Bitmap to HBITMAP.
166
167 ********************************************************************/
168 extern "C" HRESULT DAPI GdipBitmapToGdiBitmap(
169 __in Gdiplus::Bitmap* pBitmap,
170 __out HBITMAP* phBitmap
171 )
172 {
173 HRESULT hr = S_OK;
174 Status gs = Ok;
175 Color black;
176
177 gs = pBitmap->GetHBITMAP(black, phBitmap);
178 GdipExitOnGdipFailure(gs, hr, "Failed to convert GDI+ bitmap into HBITMAP.");
179
180 LExit:
181 return hr;
182 }
183
184
185 HRESULT DAPI GdipHresultFromStatus(
186 __in Gdiplus::Status gs
187 )
188 {
189 switch (gs)
190 {
191 case Ok:
192 return S_OK;
193
194 case GenericError:
195 return E_FAIL;
196
197 case InvalidParameter:
198 return E_INVALIDARG;
199
200 case OutOfMemory:
201 return E_OUTOFMEMORY;
202
203 case ObjectBusy:
204 return HRESULT_FROM_WIN32(ERROR_BUSY);
205
206 case InsufficientBuffer:
207 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
208
209 case NotImplemented:
210 return E_NOTIMPL;
211
212 case Win32Error:
213 return E_FAIL;
214
215 case WrongState:
216 return E_FAIL;
217
218 case Aborted:
219 return E_ABORT;
220
221 case FileNotFound:
222 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
223
224 case ValueOverflow:
225 return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
226
227 case AccessDenied:
228 return E_ACCESSDENIED;
229
230 case UnknownImageFormat:
231 return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
232
233 case FontFamilyNotFound: __fallthrough;
234 case FontStyleNotFound: __fallthrough;
235 case NotTrueTypeFont:
236 return E_UNEXPECTED;
237
238 case UnsupportedGdiplusVersion:
239 return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
240
241 case GdiplusNotInitialized:
242 return E_UNEXPECTED;
243
244 case PropertyNotFound: __fallthrough;
245 case PropertyNotSupported:
246 return E_FAIL;
247 }
248
249 return E_UNEXPECTED;
250 }