aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/gdiputil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dutil/gdiputil.cpp')
-rw-r--r--src/dutil/gdiputil.cpp212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/dutil/gdiputil.cpp b/src/dutil/gdiputil.cpp
new file mode 100644
index 00000000..aef6178f
--- /dev/null
+++ b/src/dutil/gdiputil.cpp
@@ -0,0 +1,212 @@
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
5using namespace Gdiplus;
6
7/********************************************************************
8 GdipInitialize - initializes GDI+.
9
10 Note: pOutput must be non-NULL if pInput->SuppressBackgroundThread
11 is TRUE. See GdiplusStartup() for more information.
12********************************************************************/
13extern "C" HRESULT DAPI GdipInitialize(
14 __in const Gdiplus::GdiplusStartupInput* pInput,
15 __out ULONG_PTR* pToken,
16 __out_opt Gdiplus::GdiplusStartupOutput *pOutput
17 )
18{
19 AssertSz(!pInput->SuppressBackgroundThread || pOutput, "pOutput required if background thread suppressed.");
20
21 HRESULT hr = S_OK;
22 Status status = Ok;
23
24 status = GdiplusStartup(pToken, pInput, pOutput);
25 ExitOnGdipFailure(status, hr, "Failed to initialize GDI+.");
26
27LExit:
28 return hr;
29}
30
31/********************************************************************
32 GdipUninitialize - uninitializes GDI+.
33
34********************************************************************/
35extern "C" void DAPI GdipUninitialize(
36 __in ULONG_PTR token
37 )
38{
39 GdiplusShutdown(token);
40}
41
42/********************************************************************
43 GdipBitmapFromResource - read a GDI+ image out of a resource stream
44
45********************************************************************/
46extern "C" HRESULT DAPI GdipBitmapFromResource(
47 __in_opt HINSTANCE hinst,
48 __in_z LPCSTR szId,
49 __out Bitmap **ppBitmap
50 )
51{
52 HRESULT hr = S_OK;
53 LPVOID pvData = NULL;
54 DWORD cbData = 0;
55 HGLOBAL hGlobal = NULL;;
56 LPVOID pv = NULL;
57 IStream *pStream = NULL;
58 Bitmap *pBitmap = NULL;
59 Status gs = Ok;
60
61 hr = ResReadData(hinst, szId, &pvData, &cbData);
62 ExitOnFailure(hr, "Failed to load GDI+ bitmap from resource.");
63
64 // Have to copy the fixed resource data into moveable (heap) memory
65 // since that's what GDI+ expects.
66 hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, cbData);
67 ExitOnNullWithLastError(hGlobal, hr, "Failed to allocate global memory.");
68
69 pv = ::GlobalLock(hGlobal);
70 ExitOnNullWithLastError(pv, hr, "Failed to lock global memory.");
71
72 memcpy(pv, pvData, cbData);
73
74 ::GlobalUnlock(pv); // no point taking any more memory than we have already
75 pv = NULL;
76
77 hr = ::CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
78 ExitOnFailure(hr, "Failed to allocate stream from global memory.");
79
80 hGlobal = NULL; // we gave the global memory to the stream object so it will close it
81
82 pBitmap = Bitmap::FromStream(pStream);
83 ExitOnNull(pBitmap, hr, E_OUTOFMEMORY, "Failed to allocate bitmap from stream.");
84
85 gs = pBitmap->GetLastStatus();
86 ExitOnGdipFailure(gs, hr, "Failed to load bitmap from stream.");
87
88 *ppBitmap = pBitmap;
89 pBitmap = NULL;
90
91LExit:
92 if (pBitmap)
93 {
94 delete pBitmap;
95 }
96
97 ReleaseObject(pStream);
98
99 if (pv)
100 {
101 ::GlobalUnlock(pv);
102 }
103
104 if (hGlobal)
105 {
106 ::GlobalFree(hGlobal);
107 }
108
109 return hr;
110}
111
112
113/********************************************************************
114 GdipBitmapFromFile - read a GDI+ image from a file.
115
116********************************************************************/
117extern "C" HRESULT DAPI GdipBitmapFromFile(
118 __in_z LPCWSTR wzFileName,
119 __out Bitmap **ppBitmap
120 )
121{
122 HRESULT hr = S_OK;
123 Bitmap *pBitmap = NULL;
124 Status gs = Ok;
125
126 ExitOnNull(ppBitmap, hr, E_INVALIDARG, "Invalid null wzFileName");
127
128 pBitmap = Bitmap::FromFile(wzFileName);
129 ExitOnNull(pBitmap, hr, E_OUTOFMEMORY, "Failed to allocate bitmap from file.");
130
131 gs = pBitmap->GetLastStatus();
132 ExitOnGdipFailure(gs, hr, "Failed to load bitmap from file: %ls", wzFileName);
133
134 *ppBitmap = pBitmap;
135 pBitmap = NULL;
136
137LExit:
138 if (pBitmap)
139 {
140 delete pBitmap;
141 }
142
143 return hr;
144}
145
146
147HRESULT DAPI GdipHresultFromStatus(
148 __in Gdiplus::Status gs
149 )
150{
151 switch (gs)
152 {
153 case Ok:
154 return S_OK;
155
156 case GenericError:
157 return E_FAIL;
158
159 case InvalidParameter:
160 return E_INVALIDARG;
161
162 case OutOfMemory:
163 return E_OUTOFMEMORY;
164
165 case ObjectBusy:
166 return HRESULT_FROM_WIN32(ERROR_BUSY);
167
168 case InsufficientBuffer:
169 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
170
171 case NotImplemented:
172 return E_NOTIMPL;
173
174 case Win32Error:
175 return E_FAIL;
176
177 case WrongState:
178 return E_FAIL;
179
180 case Aborted:
181 return E_ABORT;
182
183 case FileNotFound:
184 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
185
186 case ValueOverflow:
187 return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
188
189 case AccessDenied:
190 return E_ACCESSDENIED;
191
192 case UnknownImageFormat:
193 return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
194
195 case FontFamilyNotFound: __fallthrough;
196 case FontStyleNotFound: __fallthrough;
197 case NotTrueTypeFont:
198 return E_UNEXPECTED;
199
200 case UnsupportedGdiplusVersion:
201 return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
202
203 case GdiplusNotInitialized:
204 return E_UNEXPECTED;
205
206 case PropertyNotFound: __fallthrough;
207 case PropertyNotSupported:
208 return E_FAIL;
209 }
210
211 return E_UNEXPECTED;
212}