OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "core/include/fxge/fx_ge.h" | |
8 | |
9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ | |
10 #include <windows.h> | |
11 #include <algorithm> | |
12 | |
13 namespace Gdiplus { | |
14 using std::min; | |
15 using std::max; | |
16 } // namespace Gdiplus | |
17 | |
18 #include <gdiplus.h> | |
19 | |
20 #include "core/include/fxge/fx_ge_win32.h" | |
21 #include "core/src/fxge/win32/win32_int.h" | |
22 | |
23 using namespace Gdiplus; // NOLINT | |
24 using namespace Gdiplus::DllExports; // NOLINT | |
25 | |
26 #define GdiFillType2Gdip(fill_type) \ | |
27 (fill_type == ALTERNATE ? FillModeAlternate : FillModeWinding) | |
28 | |
29 enum { | |
30 FuncId_GdipCreatePath2, | |
31 FuncId_GdipSetPenDashStyle, | |
32 FuncId_GdipSetPenDashArray, | |
33 FuncId_GdipSetPenDashCap197819, | |
34 FuncId_GdipSetPenLineJoin, | |
35 FuncId_GdipSetPenWidth, | |
36 FuncId_GdipCreateFromHDC, | |
37 FuncId_GdipSetPageUnit, | |
38 FuncId_GdipSetSmoothingMode, | |
39 FuncId_GdipCreateSolidFill, | |
40 FuncId_GdipFillPath, | |
41 FuncId_GdipDeleteBrush, | |
42 FuncId_GdipCreatePen1, | |
43 FuncId_GdipSetPenMiterLimit, | |
44 FuncId_GdipDrawPath, | |
45 FuncId_GdipDeletePen, | |
46 FuncId_GdipDeletePath, | |
47 FuncId_GdipDeleteGraphics, | |
48 FuncId_GdipCreateBitmapFromFileICM, | |
49 FuncId_GdipCreateBitmapFromStreamICM, | |
50 FuncId_GdipGetImageHeight, | |
51 FuncId_GdipGetImageWidth, | |
52 FuncId_GdipGetImagePixelFormat, | |
53 FuncId_GdipBitmapLockBits, | |
54 FuncId_GdipGetImagePaletteSize, | |
55 FuncId_GdipGetImagePalette, | |
56 FuncId_GdipBitmapUnlockBits, | |
57 FuncId_GdipDisposeImage, | |
58 FuncId_GdipFillRectangle, | |
59 FuncId_GdipCreateBitmapFromScan0, | |
60 FuncId_GdipSetImagePalette, | |
61 FuncId_GdipSetInterpolationMode, | |
62 FuncId_GdipDrawImagePointsI, | |
63 FuncId_GdipCreateBitmapFromGdiDib, | |
64 FuncId_GdiplusStartup, | |
65 FuncId_GdipDrawLineI, | |
66 FuncId_GdipResetClip, | |
67 FuncId_GdipCreatePath, | |
68 FuncId_GdipAddPathPath, | |
69 FuncId_GdipSetPathFillMode, | |
70 FuncId_GdipSetClipPath, | |
71 FuncId_GdipGetClip, | |
72 FuncId_GdipCreateRegion, | |
73 FuncId_GdipGetClipBoundsI, | |
74 FuncId_GdipSetClipRegion, | |
75 FuncId_GdipWidenPath, | |
76 FuncId_GdipAddPathLine, | |
77 FuncId_GdipAddPathRectangle, | |
78 FuncId_GdipDeleteRegion, | |
79 FuncId_GdipGetDC, | |
80 FuncId_GdipReleaseDC, | |
81 FuncId_GdipSetPenLineCap197819, | |
82 FuncId_GdipSetPenDashOffset, | |
83 FuncId_GdipResetPath, | |
84 FuncId_GdipCreateRegionPath, | |
85 FuncId_GdipCreateFont, | |
86 FuncId_GdipGetFontSize, | |
87 FuncId_GdipCreateFontFamilyFromName, | |
88 FuncId_GdipSetTextRenderingHint, | |
89 FuncId_GdipDrawDriverString, | |
90 FuncId_GdipCreateMatrix2, | |
91 FuncId_GdipDeleteMatrix, | |
92 FuncId_GdipSetWorldTransform, | |
93 FuncId_GdipResetWorldTransform, | |
94 FuncId_GdipDeleteFontFamily, | |
95 FuncId_GdipDeleteFont, | |
96 FuncId_GdipNewPrivateFontCollection, | |
97 FuncId_GdipDeletePrivateFontCollection, | |
98 FuncId_GdipPrivateAddMemoryFont, | |
99 FuncId_GdipGetFontCollectionFamilyList, | |
100 FuncId_GdipGetFontCollectionFamilyCount, | |
101 FuncId_GdipSetTextContrast, | |
102 FuncId_GdipSetPixelOffsetMode, | |
103 FuncId_GdipGetImageGraphicsContext, | |
104 FuncId_GdipDrawImageI, | |
105 FuncId_GdipDrawImageRectI, | |
106 FuncId_GdipDrawString, | |
107 FuncId_GdipSetPenTransform, | |
108 }; | |
109 static LPCSTR g_GdipFuncNames[] = { | |
110 "GdipCreatePath2", | |
111 "GdipSetPenDashStyle", | |
112 "GdipSetPenDashArray", | |
113 "GdipSetPenDashCap197819", | |
114 "GdipSetPenLineJoin", | |
115 "GdipSetPenWidth", | |
116 "GdipCreateFromHDC", | |
117 "GdipSetPageUnit", | |
118 "GdipSetSmoothingMode", | |
119 "GdipCreateSolidFill", | |
120 "GdipFillPath", | |
121 "GdipDeleteBrush", | |
122 "GdipCreatePen1", | |
123 "GdipSetPenMiterLimit", | |
124 "GdipDrawPath", | |
125 "GdipDeletePen", | |
126 "GdipDeletePath", | |
127 "GdipDeleteGraphics", | |
128 "GdipCreateBitmapFromFileICM", | |
129 "GdipCreateBitmapFromStreamICM", | |
130 "GdipGetImageHeight", | |
131 "GdipGetImageWidth", | |
132 "GdipGetImagePixelFormat", | |
133 "GdipBitmapLockBits", | |
134 "GdipGetImagePaletteSize", | |
135 "GdipGetImagePalette", | |
136 "GdipBitmapUnlockBits", | |
137 "GdipDisposeImage", | |
138 "GdipFillRectangle", | |
139 "GdipCreateBitmapFromScan0", | |
140 "GdipSetImagePalette", | |
141 "GdipSetInterpolationMode", | |
142 "GdipDrawImagePointsI", | |
143 "GdipCreateBitmapFromGdiDib", | |
144 "GdiplusStartup", | |
145 "GdipDrawLineI", | |
146 "GdipResetClip", | |
147 "GdipCreatePath", | |
148 "GdipAddPathPath", | |
149 "GdipSetPathFillMode", | |
150 "GdipSetClipPath", | |
151 "GdipGetClip", | |
152 "GdipCreateRegion", | |
153 "GdipGetClipBoundsI", | |
154 "GdipSetClipRegion", | |
155 "GdipWidenPath", | |
156 "GdipAddPathLine", | |
157 "GdipAddPathRectangle", | |
158 "GdipDeleteRegion", | |
159 "GdipGetDC", | |
160 "GdipReleaseDC", | |
161 "GdipSetPenLineCap197819", | |
162 "GdipSetPenDashOffset", | |
163 "GdipResetPath", | |
164 "GdipCreateRegionPath", | |
165 "GdipCreateFont", | |
166 "GdipGetFontSize", | |
167 "GdipCreateFontFamilyFromName", | |
168 "GdipSetTextRenderingHint", | |
169 "GdipDrawDriverString", | |
170 "GdipCreateMatrix2", | |
171 "GdipDeleteMatrix", | |
172 "GdipSetWorldTransform", | |
173 "GdipResetWorldTransform", | |
174 "GdipDeleteFontFamily", | |
175 "GdipDeleteFont", | |
176 "GdipNewPrivateFontCollection", | |
177 "GdipDeletePrivateFontCollection", | |
178 "GdipPrivateAddMemoryFont", | |
179 "GdipGetFontCollectionFamilyList", | |
180 "GdipGetFontCollectionFamilyCount", | |
181 "GdipSetTextContrast", | |
182 "GdipSetPixelOffsetMode", | |
183 "GdipGetImageGraphicsContext", | |
184 "GdipDrawImageI", | |
185 "GdipDrawImageRectI", | |
186 "GdipDrawString", | |
187 "GdipSetPenTransform", | |
188 }; | |
189 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePath2)(GDIPCONST GpPointF*, | |
190 GDIPCONST BYTE*, | |
191 INT, | |
192 GpFillMode, | |
193 GpPath** path); | |
194 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashStyle)( | |
195 GpPen* pen, | |
196 GpDashStyle dashstyle); | |
197 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashArray)(GpPen* pen, | |
198 GDIPCONST REAL* dash, | |
199 INT count); | |
200 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashCap197819)( | |
201 GpPen* pen, | |
202 GpDashCap dashCap); | |
203 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenLineJoin)(GpPen* pen, | |
204 GpLineJoin lineJoin); | |
205 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenWidth)(GpPen* pen, REAL width); | |
206 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFromHDC)(HDC hdc, | |
207 GpGraphics** graphics); | |
208 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPageUnit)(GpGraphics* graphics, | |
209 GpUnit unit); | |
210 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetSmoothingMode)( | |
211 GpGraphics* graphics, | |
212 SmoothingMode smoothingMode); | |
213 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateSolidFill)(ARGB color, | |
214 GpSolidFill** brush); | |
215 typedef GpStatus(WINGDIPAPI* FuncType_GdipFillPath)(GpGraphics* graphics, | |
216 GpBrush* brush, | |
217 GpPath* path); | |
218 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteBrush)(GpBrush* brush); | |
219 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePen1)(ARGB color, | |
220 REAL width, | |
221 GpUnit unit, | |
222 GpPen** pen); | |
223 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenMiterLimit)(GpPen* pen, | |
224 REAL miterLimit); | |
225 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawPath)(GpGraphics* graphics, | |
226 GpPen* pen, | |
227 GpPath* path); | |
228 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeletePen)(GpPen* pen); | |
229 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeletePath)(GpPath* path); | |
230 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteGraphics)(GpGraphics* graphics); | |
231 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromFileICM)( | |
232 GDIPCONST WCHAR* filename, | |
233 GpBitmap** bitmap); | |
234 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromStreamICM)( | |
235 IStream* stream, | |
236 GpBitmap** bitmap); | |
237 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageWidth)(GpImage* image, | |
238 UINT* width); | |
239 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageHeight)(GpImage* image, | |
240 UINT* height); | |
241 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePixelFormat)( | |
242 GpImage* image, | |
243 PixelFormat* format); | |
244 typedef GpStatus(WINGDIPAPI* FuncType_GdipBitmapLockBits)( | |
245 GpBitmap* bitmap, | |
246 GDIPCONST GpRect* rect, | |
247 UINT flags, | |
248 PixelFormat format, | |
249 BitmapData* lockedBitmapData); | |
250 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePalette)( | |
251 GpImage* image, | |
252 ColorPalette* palette, | |
253 INT size); | |
254 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePaletteSize)(GpImage* image, | |
255 INT* size); | |
256 typedef GpStatus(WINGDIPAPI* FuncType_GdipBitmapUnlockBits)( | |
257 GpBitmap* bitmap, | |
258 BitmapData* lockedBitmapData); | |
259 typedef GpStatus(WINGDIPAPI* FuncType_GdipDisposeImage)(GpImage* image); | |
260 typedef GpStatus(WINGDIPAPI* FuncType_GdipFillRectangle)(GpGraphics* graphics, | |
261 GpBrush* brush, | |
262 REAL x, | |
263 REAL y, | |
264 REAL width, | |
265 REAL height); | |
266 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromScan0)( | |
267 INT width, | |
268 INT height, | |
269 INT stride, | |
270 PixelFormat format, | |
271 BYTE* scan0, | |
272 GpBitmap** bitmap); | |
273 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetImagePalette)( | |
274 GpImage* image, | |
275 GDIPCONST ColorPalette* palette); | |
276 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetInterpolationMode)( | |
277 GpGraphics* graphics, | |
278 InterpolationMode interpolationMode); | |
279 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawImagePointsI)( | |
280 GpGraphics* graphics, | |
281 GpImage* image, | |
282 GDIPCONST GpPoint* dstpoints, | |
283 INT count); | |
284 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromGdiDib)( | |
285 GDIPCONST BITMAPINFO* gdiBitmapInfo, | |
286 VOID* gdiBitmapData, | |
287 GpBitmap** bitmap); | |
288 typedef Status(WINAPI* FuncType_GdiplusStartup)( | |
289 OUT uintptr_t* token, | |
290 const GdiplusStartupInput* input, | |
291 OUT GdiplusStartupOutput* output); | |
292 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawLineI)(GpGraphics* graphics, | |
293 GpPen* pen, | |
294 int x1, | |
295 int y1, | |
296 int x2, | |
297 int y2); | |
298 typedef GpStatus(WINGDIPAPI* FuncType_GdipResetClip)(GpGraphics* graphics); | |
299 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePath)(GpFillMode brushMode, | |
300 GpPath** path); | |
301 typedef GpStatus(WINGDIPAPI* FuncType_GdipAddPathPath)( | |
302 GpPath* path, | |
303 GDIPCONST GpPath* addingPath, | |
304 BOOL connect); | |
305 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPathFillMode)(GpPath* path, | |
306 GpFillMode fillmode); | |
307 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetClipPath)(GpGraphics* graphics, | |
308 GpPath* path, | |
309 CombineMode combineMode); | |
310 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetClip)(GpGraphics* graphics, | |
311 GpRegion* region); | |
312 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateRegion)(GpRegion** region); | |
313 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetClipBoundsI)(GpGraphics* graphics, | |
314 GpRect* rect); | |
315 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetClipRegion)( | |
316 GpGraphics* graphics, | |
317 GpRegion* region, | |
318 CombineMode combineMode); | |
319 typedef GpStatus(WINGDIPAPI* FuncType_GdipWidenPath)(GpPath* nativePath, | |
320 GpPen* pen, | |
321 GpMatrix* matrix, | |
322 REAL flatness); | |
323 typedef GpStatus(WINGDIPAPI* FuncType_GdipAddPathLine)(GpPath* path, | |
324 REAL x1, | |
325 REAL y1, | |
326 REAL x2, | |
327 REAL y2); | |
328 typedef GpStatus(WINGDIPAPI* FuncType_GdipAddPathRectangle)(GpPath* path, | |
329 REAL x, | |
330 REAL y, | |
331 REAL width, | |
332 REAL height); | |
333 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteRegion)(GpRegion* region); | |
334 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetDC)(GpGraphics* graphics, | |
335 HDC* hdc); | |
336 typedef GpStatus(WINGDIPAPI* FuncType_GdipReleaseDC)(GpGraphics* graphics, | |
337 HDC hdc); | |
338 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenLineCap197819)( | |
339 GpPen* pen, | |
340 GpLineCap startCap, | |
341 GpLineCap endCap, | |
342 GpDashCap dashCap); | |
343 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashOffset)(GpPen* pen, | |
344 REAL offset); | |
345 typedef GpStatus(WINGDIPAPI* FuncType_GdipResetPath)(GpPath* path); | |
346 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateRegionPath)(GpPath* path, | |
347 GpRegion** region); | |
348 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFont)( | |
349 GDIPCONST GpFontFamily* fontFamily, | |
350 REAL emSize, | |
351 INT style, | |
352 Unit unit, | |
353 GpFont** font); | |
354 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontSize)(GpFont* font, | |
355 REAL* size); | |
356 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFontFamilyFromName)( | |
357 GDIPCONST WCHAR* name, | |
358 GpFontCollection* fontCollection, | |
359 GpFontFamily** FontFamily); | |
360 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetTextRenderingHint)( | |
361 GpGraphics* graphics, | |
362 TextRenderingHint mode); | |
363 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawDriverString)( | |
364 GpGraphics* graphics, | |
365 GDIPCONST UINT16* text, | |
366 INT length, | |
367 GDIPCONST GpFont* font, | |
368 GDIPCONST GpBrush* brush, | |
369 GDIPCONST PointF* positions, | |
370 INT flags, | |
371 GDIPCONST GpMatrix* matrix); | |
372 typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateMatrix2)(REAL m11, | |
373 REAL m12, | |
374 REAL m21, | |
375 REAL m22, | |
376 REAL dx, | |
377 REAL dy, | |
378 GpMatrix** matrix); | |
379 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteMatrix)(GpMatrix* matrix); | |
380 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetWorldTransform)( | |
381 GpGraphics* graphics, | |
382 GpMatrix* matrix); | |
383 typedef GpStatus(WINGDIPAPI* FuncType_GdipResetWorldTransform)( | |
384 GpGraphics* graphics); | |
385 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteFontFamily)( | |
386 GpFontFamily* FontFamily); | |
387 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteFont)(GpFont* font); | |
388 typedef GpStatus(WINGDIPAPI* FuncType_GdipNewPrivateFontCollection)( | |
389 GpFontCollection** fontCollection); | |
390 typedef GpStatus(WINGDIPAPI* FuncType_GdipDeletePrivateFontCollection)( | |
391 GpFontCollection** fontCollection); | |
392 typedef GpStatus(WINGDIPAPI* FuncType_GdipPrivateAddMemoryFont)( | |
393 GpFontCollection* fontCollection, | |
394 GDIPCONST void* memory, | |
395 INT length); | |
396 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontCollectionFamilyList)( | |
397 GpFontCollection* fontCollection, | |
398 INT numSought, | |
399 GpFontFamily* gpfamilies[], | |
400 INT* numFound); | |
401 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontCollectionFamilyCount)( | |
402 GpFontCollection* fontCollection, | |
403 INT* numFound); | |
404 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetTextContrast)(GpGraphics* graphics, | |
405 UINT contrast); | |
406 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPixelOffsetMode)( | |
407 GpGraphics* graphics, | |
408 PixelOffsetMode pixelOffsetMode); | |
409 typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageGraphicsContext)( | |
410 GpImage* image, | |
411 GpGraphics** graphics); | |
412 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawImageI)(GpGraphics* graphics, | |
413 GpImage* image, | |
414 INT x, | |
415 INT y); | |
416 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawImageRectI)(GpGraphics* graphics, | |
417 GpImage* image, | |
418 INT x, | |
419 INT y, | |
420 INT width, | |
421 INT height); | |
422 typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawString)( | |
423 GpGraphics* graphics, | |
424 GDIPCONST WCHAR* str, | |
425 INT length, | |
426 GDIPCONST GpFont* font, | |
427 GDIPCONST RectF* layoutRect, | |
428 GDIPCONST GpStringFormat* stringFormat, | |
429 GDIPCONST GpBrush* brush); | |
430 typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenTransform)(GpPen* pen, | |
431 GpMatrix* matrix); | |
432 #define CallFunc(funcname) \ | |
433 ((FuncType_##funcname)GdiplusExt.m_Functions[FuncId_##funcname]) | |
434 typedef HANDLE(__stdcall* FuncType_GdiAddFontMemResourceEx)(PVOID pbFont, | |
435 DWORD cbFont, | |
436 PVOID pdv, | |
437 DWORD* pcFonts); | |
438 typedef BOOL(__stdcall* FuncType_GdiRemoveFontMemResourceEx)(HANDLE handle); | |
439 void* CGdiplusExt::GdiAddFontMemResourceEx(void* pFontdata, | |
440 FX_DWORD size, | |
441 void* pdv, | |
442 FX_DWORD* num_face) { | |
443 if (m_pGdiAddFontMemResourceEx) { | |
444 return ((FuncType_GdiAddFontMemResourceEx)m_pGdiAddFontMemResourceEx)( | |
445 (PVOID)pFontdata, (DWORD)size, (PVOID)pdv, (DWORD*)num_face); | |
446 } | |
447 return NULL; | |
448 } | |
449 FX_BOOL CGdiplusExt::GdiRemoveFontMemResourceEx(void* handle) { | |
450 if (m_pGdiRemoveFontMemResourseEx) { | |
451 return ((FuncType_GdiRemoveFontMemResourceEx)m_pGdiRemoveFontMemResourseEx)( | |
452 (HANDLE)handle); | |
453 } | |
454 return FALSE; | |
455 } | |
456 static GpBrush* _GdipCreateBrush(DWORD argb) { | |
457 CGdiplusExt& GdiplusExt = | |
458 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
459 GpSolidFill* solidBrush = NULL; | |
460 CallFunc(GdipCreateSolidFill)((ARGB)argb, &solidBrush); | |
461 return solidBrush; | |
462 } | |
463 static CFX_DIBitmap* _StretchMonoToGray(int dest_width, | |
464 int dest_height, | |
465 const CFX_DIBitmap* pSource, | |
466 FX_RECT* pClipRect) { | |
467 FX_BOOL bFlipX = dest_width < 0; | |
468 if (bFlipX) { | |
469 dest_width = -dest_width; | |
470 } | |
471 FX_BOOL bFlipY = dest_height < 0; | |
472 if (bFlipY) { | |
473 dest_height = -dest_height; | |
474 } | |
475 int result_width = pClipRect->Width(); | |
476 int result_height = pClipRect->Height(); | |
477 int result_pitch = (result_width + 3) / 4 * 4; | |
478 CFX_DIBitmap* pStretched = new CFX_DIBitmap; | |
479 if (!pStretched->Create(result_width, result_height, FXDIB_8bppRgb)) { | |
480 delete pStretched; | |
481 return NULL; | |
482 } | |
483 LPBYTE dest_buf = pStretched->GetBuffer(); | |
484 int src_width = pSource->GetWidth(); | |
485 int src_height = pSource->GetHeight(); | |
486 int y_unit = src_height / dest_height; | |
487 int x_unit = src_width / dest_width; | |
488 int area_unit = y_unit * x_unit; | |
489 LPBYTE src_buf = pSource->GetBuffer(); | |
490 int src_pitch = pSource->GetPitch(); | |
491 for (int dest_y = 0; dest_y < result_height; dest_y++) { | |
492 LPBYTE dest_scan = dest_buf + dest_y * result_pitch; | |
493 int src_y_start = bFlipY ? (dest_height - 1 - dest_y - pClipRect->top) | |
494 : (dest_y + pClipRect->top); | |
495 src_y_start = src_y_start * src_height / dest_height; | |
496 LPBYTE src_scan = src_buf + src_y_start * src_pitch; | |
497 for (int dest_x = 0; dest_x < result_width; dest_x++) { | |
498 int sum = 0; | |
499 int src_x_start = bFlipX ? (dest_width - 1 - dest_x - pClipRect->left) | |
500 : (dest_x + pClipRect->left); | |
501 src_x_start = src_x_start * src_width / dest_width; | |
502 int src_x_end = src_x_start + x_unit; | |
503 LPBYTE src_line = src_scan; | |
504 for (int src_y = 0; src_y < y_unit; src_y++) { | |
505 for (int src_x = src_x_start; src_x < src_x_end; src_x++) { | |
506 if (!(src_line[src_x / 8] & (1 << (7 - src_x % 8)))) { | |
507 sum += 255; | |
508 } | |
509 } | |
510 src_line += src_pitch; | |
511 } | |
512 dest_scan[dest_x] = 255 - sum / area_unit; | |
513 } | |
514 } | |
515 return pStretched; | |
516 } | |
517 static void OutputImageMask(GpGraphics* pGraphics, | |
518 BOOL bMonoDevice, | |
519 const CFX_DIBitmap* pBitmap, | |
520 int dest_left, | |
521 int dest_top, | |
522 int dest_width, | |
523 int dest_height, | |
524 FX_ARGB argb, | |
525 const FX_RECT* pClipRect) { | |
526 ASSERT(pBitmap->GetBPP() == 1); | |
527 CGdiplusExt& GdiplusExt = | |
528 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
529 int src_width = pBitmap->GetWidth(), src_height = pBitmap->GetHeight(); | |
530 int src_pitch = pBitmap->GetPitch(); | |
531 uint8_t* scan0 = pBitmap->GetBuffer(); | |
532 if (src_width == 1 && src_height == 1) { | |
533 if ((scan0[0] & 0x80) == 0) { | |
534 return; | |
535 } | |
536 GpSolidFill* solidBrush; | |
537 CallFunc(GdipCreateSolidFill)((ARGB)argb, &solidBrush); | |
538 if (dest_width < 0) { | |
539 dest_width = -dest_width; | |
540 dest_left -= dest_width; | |
541 } | |
542 if (dest_height < 0) { | |
543 dest_height = -dest_height; | |
544 dest_top -= dest_height; | |
545 } | |
546 CallFunc(GdipFillRectangle)(pGraphics, solidBrush, (float)dest_left, | |
547 (float)dest_top, (float)dest_width, | |
548 (float)dest_height); | |
549 CallFunc(GdipDeleteBrush)(solidBrush); | |
550 return; | |
551 } | |
552 if (!bMonoDevice && abs(dest_width) < src_width && | |
553 abs(dest_height) < src_height) { | |
554 FX_RECT image_rect(dest_left, dest_top, dest_left + dest_width, | |
555 dest_top + dest_height); | |
556 image_rect.Normalize(); | |
557 FX_RECT image_clip = image_rect; | |
558 image_clip.Intersect(*pClipRect); | |
559 if (image_clip.IsEmpty()) { | |
560 return; | |
561 } | |
562 image_clip.Offset(-image_rect.left, -image_rect.top); | |
563 CFX_DIBitmap* pStretched = NULL; | |
564 if (src_width * src_height > 10000) { | |
565 pStretched = | |
566 _StretchMonoToGray(dest_width, dest_height, pBitmap, &image_clip); | |
567 } else { | |
568 pStretched = | |
569 pBitmap->StretchTo(dest_width, dest_height, FALSE, &image_clip); | |
570 } | |
571 GpBitmap* bitmap; | |
572 CallFunc(GdipCreateBitmapFromScan0)(image_clip.Width(), image_clip.Height(), | |
573 (image_clip.Width() + 3) / 4 * 4, | |
574 PixelFormat8bppIndexed, | |
575 pStretched->GetBuffer(), &bitmap); | |
576 int a, r, g, b; | |
577 ArgbDecode(argb, a, r, g, b); | |
578 UINT pal[258]; | |
579 pal[0] = 0; | |
580 pal[1] = 256; | |
581 for (int i = 0; i < 256; i++) { | |
582 pal[i + 2] = ArgbEncode(i * a / 255, r, g, b); | |
583 } | |
584 CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)pal); | |
585 CallFunc(GdipDrawImageI)(pGraphics, bitmap, | |
586 image_rect.left + image_clip.left, | |
587 image_rect.top + image_clip.top); | |
588 CallFunc(GdipDisposeImage)(bitmap); | |
589 delete pStretched; | |
590 return; | |
591 } | |
592 GpBitmap* bitmap; | |
593 CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, | |
594 PixelFormat1bppIndexed, scan0, &bitmap); | |
595 UINT palette[4] = {PaletteFlagsHasAlpha, 2, 0, argb}; | |
596 CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)palette); | |
597 Point destinationPoints[] = {Point(dest_left, dest_top), | |
598 Point(dest_left + dest_width, dest_top), | |
599 Point(dest_left, dest_top + dest_height)}; | |
600 CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); | |
601 CallFunc(GdipDisposeImage)(bitmap); | |
602 } | |
603 static void OutputImage(GpGraphics* pGraphics, | |
604 const CFX_DIBitmap* pBitmap, | |
605 const FX_RECT* pSrcRect, | |
606 int dest_left, | |
607 int dest_top, | |
608 int dest_width, | |
609 int dest_height) { | |
610 int src_width = pSrcRect->Width(), src_height = pSrcRect->Height(); | |
611 CGdiplusExt& GdiplusExt = | |
612 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
613 if (pBitmap->GetBPP() == 1 && (pSrcRect->left % 8)) { | |
614 FX_RECT new_rect(0, 0, src_width, src_height); | |
615 CFX_DIBitmap* pCloned = pBitmap->Clone(pSrcRect); | |
616 if (!pCloned) { | |
617 return; | |
618 } | |
619 OutputImage(pGraphics, pCloned, &new_rect, dest_left, dest_top, dest_width, | |
620 dest_height); | |
621 delete pCloned; | |
622 return; | |
623 } | |
624 int src_pitch = pBitmap->GetPitch(); | |
625 uint8_t* scan0 = pBitmap->GetBuffer() + pSrcRect->top * src_pitch + | |
626 pBitmap->GetBPP() * pSrcRect->left / 8; | |
627 GpBitmap* bitmap = NULL; | |
628 switch (pBitmap->GetFormat()) { | |
629 case FXDIB_Argb: | |
630 CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, | |
631 PixelFormat32bppARGB, scan0, &bitmap); | |
632 break; | |
633 case FXDIB_Rgb32: | |
634 CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, | |
635 PixelFormat32bppRGB, scan0, &bitmap); | |
636 break; | |
637 case FXDIB_Rgb: | |
638 CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, | |
639 PixelFormat24bppRGB, scan0, &bitmap); | |
640 break; | |
641 case FXDIB_8bppRgb: { | |
642 CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, | |
643 PixelFormat8bppIndexed, scan0, | |
644 &bitmap); | |
645 UINT pal[258]; | |
646 pal[0] = 0; | |
647 pal[1] = 256; | |
648 for (int i = 0; i < 256; i++) { | |
649 pal[i + 2] = pBitmap->GetPaletteEntry(i); | |
650 } | |
651 CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)pal); | |
652 break; | |
653 } | |
654 case FXDIB_1bppRgb: { | |
655 CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, | |
656 PixelFormat1bppIndexed, scan0, | |
657 &bitmap); | |
658 break; | |
659 } | |
660 } | |
661 if (dest_height < 0) { | |
662 dest_height--; | |
663 } | |
664 if (dest_width < 0) { | |
665 dest_width--; | |
666 } | |
667 Point destinationPoints[] = {Point(dest_left, dest_top), | |
668 Point(dest_left + dest_width, dest_top), | |
669 Point(dest_left, dest_top + dest_height)}; | |
670 CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); | |
671 CallFunc(GdipDisposeImage)(bitmap); | |
672 } | |
673 CGdiplusExt::CGdiplusExt() { | |
674 m_hModule = NULL; | |
675 m_GdiModule = NULL; | |
676 for (int i = 0; i < sizeof g_GdipFuncNames / sizeof(LPCSTR); i++) { | |
677 m_Functions[i] = NULL; | |
678 } | |
679 m_pGdiAddFontMemResourceEx = NULL; | |
680 m_pGdiRemoveFontMemResourseEx = NULL; | |
681 } | |
682 void CGdiplusExt::Load() { | |
683 CFX_ByteString strPlusPath = ""; | |
684 FX_CHAR buf[MAX_PATH]; | |
685 GetSystemDirectoryA(buf, MAX_PATH); | |
686 strPlusPath += buf; | |
687 strPlusPath += "\\"; | |
688 strPlusPath += "GDIPLUS.DLL"; | |
689 m_hModule = LoadLibraryA(strPlusPath); | |
690 if (!m_hModule) { | |
691 return; | |
692 } | |
693 for (int i = 0; i < sizeof g_GdipFuncNames / sizeof(LPCSTR); i++) { | |
694 m_Functions[i] = GetProcAddress(m_hModule, g_GdipFuncNames[i]); | |
695 if (!m_Functions[i]) { | |
696 m_hModule = NULL; | |
697 return; | |
698 } | |
699 } | |
700 uintptr_t gdiplusToken; | |
701 GdiplusStartupInput gdiplusStartupInput; | |
702 ((FuncType_GdiplusStartup)m_Functions[FuncId_GdiplusStartup])( | |
703 &gdiplusToken, &gdiplusStartupInput, NULL); | |
704 m_GdiModule = LoadLibraryA("GDI32.DLL"); | |
705 if (!m_GdiModule) { | |
706 return; | |
707 } | |
708 m_pGdiAddFontMemResourceEx = | |
709 GetProcAddress(m_GdiModule, "AddFontMemResourceEx"); | |
710 m_pGdiRemoveFontMemResourseEx = | |
711 GetProcAddress(m_GdiModule, "RemoveFontMemResourceEx"); | |
712 } | |
713 CGdiplusExt::~CGdiplusExt() {} | |
714 LPVOID CGdiplusExt::LoadMemFont(LPBYTE pData, FX_DWORD size) { | |
715 GpFontCollection* pCollection = NULL; | |
716 CGdiplusExt& GdiplusExt = | |
717 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
718 CallFunc(GdipNewPrivateFontCollection)(&pCollection); | |
719 GpStatus status = | |
720 CallFunc(GdipPrivateAddMemoryFont)(pCollection, pData, size); | |
721 if (status == Ok) { | |
722 return pCollection; | |
723 } | |
724 CallFunc(GdipDeletePrivateFontCollection)(&pCollection); | |
725 return NULL; | |
726 } | |
727 void CGdiplusExt::DeleteMemFont(LPVOID pCollection) { | |
728 CGdiplusExt& GdiplusExt = | |
729 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
730 CallFunc(GdipDeletePrivateFontCollection)((GpFontCollection**)&pCollection); | |
731 } | |
732 FX_BOOL CGdiplusExt::GdipCreateBitmap(CFX_DIBitmap* pBitmap, void** bitmap) { | |
733 CGdiplusExt& GdiplusExt = | |
734 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
735 PixelFormat format; | |
736 switch (pBitmap->GetFormat()) { | |
737 case FXDIB_Rgb: | |
738 format = PixelFormat24bppRGB; | |
739 break; | |
740 case FXDIB_Rgb32: | |
741 format = PixelFormat32bppRGB; | |
742 break; | |
743 case FXDIB_Argb: | |
744 format = PixelFormat32bppARGB; | |
745 break; | |
746 default: | |
747 return FALSE; | |
748 } | |
749 GpStatus status = CallFunc(GdipCreateBitmapFromScan0)( | |
750 pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap->GetPitch(), format, | |
751 pBitmap->GetBuffer(), (GpBitmap**)bitmap); | |
752 if (status == Ok) { | |
753 return TRUE; | |
754 } | |
755 return FALSE; | |
756 } | |
757 FX_BOOL CGdiplusExt::GdipCreateFromImage(void* bitmap, void** graphics) { | |
758 CGdiplusExt& GdiplusExt = | |
759 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
760 GpStatus status = CallFunc(GdipGetImageGraphicsContext)( | |
761 (GpBitmap*)bitmap, (GpGraphics**)graphics); | |
762 if (status == Ok) { | |
763 return TRUE; | |
764 } | |
765 return FALSE; | |
766 } | |
767 FX_BOOL CGdiplusExt::GdipCreateFontFamilyFromName(const FX_WCHAR* name, | |
768 void* pFontCollection, | |
769 void** pFamily) { | |
770 CGdiplusExt& GdiplusExt = | |
771 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
772 GpStatus status = CallFunc(GdipCreateFontFamilyFromName)( | |
773 (GDIPCONST WCHAR*)name, (GpFontCollection*)pFontCollection, | |
774 (GpFontFamily**)pFamily); | |
775 if (status == Ok) { | |
776 return TRUE; | |
777 } | |
778 return FALSE; | |
779 } | |
780 FX_BOOL CGdiplusExt::GdipCreateFontFromFamily(void* pFamily, | |
781 FX_FLOAT font_size, | |
782 int fontstyle, | |
783 int flag, | |
784 void** pFont) { | |
785 CGdiplusExt& GdiplusExt = | |
786 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
787 GpStatus status = | |
788 CallFunc(GdipCreateFont)((GpFontFamily*)pFamily, font_size, fontstyle, | |
789 Unit(flag), (GpFont**)pFont); | |
790 if (status == Ok) { | |
791 return TRUE; | |
792 } | |
793 return FALSE; | |
794 } | |
795 void CGdiplusExt::GdipGetFontSize(void* pFont, FX_FLOAT* size) { | |
796 REAL get_size; | |
797 CGdiplusExt& GdiplusExt = | |
798 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
799 GpStatus status = CallFunc(GdipGetFontSize)((GpFont*)pFont, (REAL*)&get_size); | |
800 if (status == Ok) { | |
801 *size = (FX_FLOAT)get_size; | |
802 } else { | |
803 *size = 0; | |
804 } | |
805 } | |
806 void CGdiplusExt::GdipSetTextRenderingHint(void* graphics, int mode) { | |
807 CGdiplusExt& GdiplusExt = | |
808 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
809 CallFunc(GdipSetTextRenderingHint)((GpGraphics*)graphics, | |
810 (TextRenderingHint)mode); | |
811 } | |
812 void CGdiplusExt::GdipSetPageUnit(void* graphics, FX_DWORD unit) { | |
813 CGdiplusExt& GdiplusExt = | |
814 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
815 CallFunc(GdipSetPageUnit)((GpGraphics*)graphics, (GpUnit)unit); | |
816 } | |
817 FX_BOOL CGdiplusExt::GdipDrawDriverString(void* graphics, | |
818 unsigned short* text, | |
819 int length, | |
820 void* font, | |
821 void* brush, | |
822 void* positions, | |
823 int flags, | |
824 const void* matrix) { | |
825 CGdiplusExt& GdiplusExt = | |
826 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
827 GpStatus status = CallFunc(GdipDrawDriverString)( | |
828 (GpGraphics*)graphics, (GDIPCONST UINT16*)text, (INT)length, | |
829 (GDIPCONST GpFont*)font, (GDIPCONST GpBrush*)brush, | |
830 (GDIPCONST PointF*)positions, (INT)flags, (GDIPCONST GpMatrix*)matrix); | |
831 if (status == Ok) { | |
832 return TRUE; | |
833 } | |
834 return FALSE; | |
835 } | |
836 void CGdiplusExt::GdipCreateBrush(FX_DWORD fill_argb, void** pBrush) { | |
837 CGdiplusExt& GdiplusExt = | |
838 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
839 CallFunc(GdipCreateSolidFill)((ARGB)fill_argb, (GpSolidFill**)pBrush); | |
840 } | |
841 void CGdiplusExt::GdipDeleteBrush(void* pBrush) { | |
842 CGdiplusExt& GdiplusExt = | |
843 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
844 CallFunc(GdipDeleteBrush)((GpSolidFill*)pBrush); | |
845 } | |
846 void* CGdiplusExt::GdipCreateFontFromCollection(void* pFontCollection, | |
847 FX_FLOAT font_size, | |
848 int fontstyle) { | |
849 CGdiplusExt& GdiplusExt = | |
850 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
851 int numFamilies = 0; | |
852 GpStatus status = CallFunc(GdipGetFontCollectionFamilyCount)( | |
853 (GpFontCollection*)pFontCollection, &numFamilies); | |
854 if (status != Ok) { | |
855 return NULL; | |
856 } | |
857 GpFontFamily* family_list[1]; | |
858 status = CallFunc(GdipGetFontCollectionFamilyList)( | |
859 (GpFontCollection*)pFontCollection, 1, family_list, &numFamilies); | |
860 if (status != Ok) { | |
861 return NULL; | |
862 } | |
863 GpFont* pFont = NULL; | |
864 status = CallFunc(GdipCreateFont)(family_list[0], font_size, fontstyle, | |
865 UnitPixel, &pFont); | |
866 if (status != Ok) { | |
867 return NULL; | |
868 } | |
869 return pFont; | |
870 } | |
871 void CGdiplusExt::GdipCreateMatrix(FX_FLOAT a, | |
872 FX_FLOAT b, | |
873 FX_FLOAT c, | |
874 FX_FLOAT d, | |
875 FX_FLOAT e, | |
876 FX_FLOAT f, | |
877 void** matrix) { | |
878 CGdiplusExt& GdiplusExt = | |
879 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
880 CallFunc(GdipCreateMatrix2)(a, b, c, d, e, f, (GpMatrix**)matrix); | |
881 } | |
882 void CGdiplusExt::GdipDeleteMatrix(void* matrix) { | |
883 CGdiplusExt& GdiplusExt = | |
884 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
885 CallFunc(GdipDeleteMatrix)((GpMatrix*)matrix); | |
886 } | |
887 void CGdiplusExt::GdipDeleteFontFamily(void* pFamily) { | |
888 CGdiplusExt& GdiplusExt = | |
889 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
890 CallFunc(GdipDeleteFontFamily)((GpFontFamily*)pFamily); | |
891 } | |
892 void CGdiplusExt::GdipDeleteFont(void* pFont) { | |
893 CGdiplusExt& GdiplusExt = | |
894 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
895 CallFunc(GdipDeleteFont)((GpFont*)pFont); | |
896 } | |
897 void CGdiplusExt::GdipSetWorldTransform(void* graphics, void* pMatrix) { | |
898 CGdiplusExt& GdiplusExt = | |
899 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
900 CallFunc(GdipSetWorldTransform)((GpGraphics*)graphics, (GpMatrix*)pMatrix); | |
901 } | |
902 void CGdiplusExt::GdipDisposeImage(void* bitmap) { | |
903 CGdiplusExt& GdiplusExt = | |
904 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
905 CallFunc(GdipDisposeImage)((GpBitmap*)bitmap); | |
906 } | |
907 void CGdiplusExt::GdipDeleteGraphics(void* graphics) { | |
908 CGdiplusExt& GdiplusExt = | |
909 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
910 CallFunc(GdipDeleteGraphics)((GpGraphics*)graphics); | |
911 } | |
912 FX_BOOL CGdiplusExt::StretchBitMask(HDC hDC, | |
913 BOOL bMonoDevice, | |
914 const CFX_DIBitmap* pBitmap, | |
915 int dest_left, | |
916 int dest_top, | |
917 int dest_width, | |
918 int dest_height, | |
919 FX_DWORD argb, | |
920 const FX_RECT* pClipRect, | |
921 int flags) { | |
922 ASSERT(pBitmap->GetBPP() == 1); | |
923 CGdiplusExt& GdiplusExt = | |
924 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
925 GpGraphics* pGraphics = NULL; | |
926 CallFunc(GdipCreateFromHDC)(hDC, &pGraphics); | |
927 CallFunc(GdipSetPageUnit)(pGraphics, UnitPixel); | |
928 if (flags & FXDIB_NOSMOOTH) { | |
929 CallFunc(GdipSetInterpolationMode)(pGraphics, | |
930 InterpolationModeNearestNeighbor); | |
931 } else { | |
932 CallFunc(GdipSetInterpolationMode)(pGraphics, InterpolationModeHighQuality); | |
933 } | |
934 OutputImageMask(pGraphics, bMonoDevice, pBitmap, dest_left, dest_top, | |
935 dest_width, dest_height, argb, pClipRect); | |
936 CallFunc(GdipDeleteGraphics)(pGraphics); | |
937 return TRUE; | |
938 } | |
939 FX_BOOL CGdiplusExt::StretchDIBits(HDC hDC, | |
940 const CFX_DIBitmap* pBitmap, | |
941 int dest_left, | |
942 int dest_top, | |
943 int dest_width, | |
944 int dest_height, | |
945 const FX_RECT* pClipRect, | |
946 int flags) { | |
947 GpGraphics* pGraphics; | |
948 CGdiplusExt& GdiplusExt = | |
949 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
950 CallFunc(GdipCreateFromHDC)(hDC, &pGraphics); | |
951 CallFunc(GdipSetPageUnit)(pGraphics, UnitPixel); | |
952 if (flags & FXDIB_NOSMOOTH) { | |
953 CallFunc(GdipSetInterpolationMode)(pGraphics, | |
954 InterpolationModeNearestNeighbor); | |
955 } else if (pBitmap->GetWidth() > abs(dest_width) / 2 || | |
956 pBitmap->GetHeight() > abs(dest_height) / 2) { | |
957 CallFunc(GdipSetInterpolationMode)(pGraphics, InterpolationModeHighQuality); | |
958 } else { | |
959 CallFunc(GdipSetInterpolationMode)(pGraphics, InterpolationModeBilinear); | |
960 } | |
961 FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); | |
962 OutputImage(pGraphics, pBitmap, &src_rect, dest_left, dest_top, dest_width, | |
963 dest_height); | |
964 CallFunc(GdipDeleteGraphics)(pGraphics); | |
965 CallFunc(GdipDeleteGraphics)(pGraphics); | |
966 return TRUE; | |
967 } | |
968 static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, | |
969 const CFX_Matrix* pMatrix, | |
970 DWORD argb, | |
971 FX_BOOL bTextMode = FALSE) { | |
972 CGdiplusExt& GdiplusExt = | |
973 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
974 FX_FLOAT width = pGraphState ? pGraphState->m_LineWidth : 1.0f; | |
975 if (!bTextMode) { | |
976 FX_FLOAT unit = | |
977 pMatrix ? 1.0f / ((pMatrix->GetXUnit() + pMatrix->GetYUnit()) / 2) | |
978 : 1.0f; | |
979 if (width < unit) { | |
980 width = unit; | |
981 } | |
982 } | |
983 GpPen* pPen = NULL; | |
984 CallFunc(GdipCreatePen1)((ARGB)argb, width, UnitWorld, &pPen); | |
985 LineCap lineCap; | |
986 DashCap dashCap = DashCapFlat; | |
987 FX_BOOL bDashExtend = FALSE; | |
988 switch (pGraphState->m_LineCap) { | |
989 case CFX_GraphStateData::LineCapButt: | |
990 lineCap = LineCapFlat; | |
991 break; | |
992 case CFX_GraphStateData::LineCapRound: | |
993 lineCap = LineCapRound; | |
994 dashCap = DashCapRound; | |
995 bDashExtend = TRUE; | |
996 break; | |
997 case CFX_GraphStateData::LineCapSquare: | |
998 lineCap = LineCapSquare; | |
999 bDashExtend = TRUE; | |
1000 break; | |
1001 } | |
1002 CallFunc(GdipSetPenLineCap197819)(pPen, lineCap, lineCap, dashCap); | |
1003 LineJoin lineJoin; | |
1004 switch (pGraphState->m_LineJoin) { | |
1005 case CFX_GraphStateData::LineJoinMiter: | |
1006 lineJoin = LineJoinMiterClipped; | |
1007 break; | |
1008 case CFX_GraphStateData::LineJoinRound: | |
1009 lineJoin = LineJoinRound; | |
1010 break; | |
1011 case CFX_GraphStateData::LineJoinBevel: | |
1012 lineJoin = LineJoinBevel; | |
1013 break; | |
1014 } | |
1015 CallFunc(GdipSetPenLineJoin)(pPen, lineJoin); | |
1016 if (pGraphState->m_DashCount) { | |
1017 FX_FLOAT* pDashArray = FX_Alloc( | |
1018 FX_FLOAT, pGraphState->m_DashCount + pGraphState->m_DashCount % 2); | |
1019 int nCount = 0; | |
1020 FX_FLOAT on_leftover = 0, off_leftover = 0; | |
1021 for (int i = 0; i < pGraphState->m_DashCount; i += 2) { | |
1022 FX_FLOAT on_phase = pGraphState->m_DashArray[i]; | |
1023 FX_FLOAT off_phase; | |
1024 if (i == pGraphState->m_DashCount - 1) { | |
1025 off_phase = on_phase; | |
1026 } else { | |
1027 off_phase = pGraphState->m_DashArray[i + 1]; | |
1028 } | |
1029 on_phase /= width; | |
1030 off_phase /= width; | |
1031 if (on_phase + off_phase <= 0.00002f) { | |
1032 on_phase = 1.0f / 10; | |
1033 off_phase = 1.0f / 10; | |
1034 } | |
1035 if (bDashExtend) { | |
1036 if (off_phase < 1) { | |
1037 off_phase = 0; | |
1038 } else { | |
1039 off_phase -= 1; | |
1040 } | |
1041 on_phase += 1; | |
1042 } | |
1043 if (on_phase == 0 || off_phase == 0) { | |
1044 if (nCount == 0) { | |
1045 on_leftover += on_phase; | |
1046 off_leftover += off_phase; | |
1047 } else { | |
1048 pDashArray[nCount - 2] += on_phase; | |
1049 pDashArray[nCount - 1] += off_phase; | |
1050 } | |
1051 } else { | |
1052 pDashArray[nCount++] = on_phase + on_leftover; | |
1053 on_leftover = 0; | |
1054 pDashArray[nCount++] = off_phase + off_leftover; | |
1055 off_leftover = 0; | |
1056 } | |
1057 } | |
1058 CallFunc(GdipSetPenDashArray)(pPen, pDashArray, nCount); | |
1059 FX_FLOAT phase = pGraphState->m_DashPhase; | |
1060 if (bDashExtend) { | |
1061 if (phase < 0.5f) { | |
1062 phase = 0; | |
1063 } else { | |
1064 phase -= 0.5f; | |
1065 } | |
1066 } | |
1067 CallFunc(GdipSetPenDashOffset)(pPen, phase); | |
1068 FX_Free(pDashArray); | |
1069 pDashArray = NULL; | |
1070 } | |
1071 CallFunc(GdipSetPenMiterLimit)(pPen, pGraphState->m_MiterLimit); | |
1072 return pPen; | |
1073 } | |
1074 static FX_BOOL IsSmallTriangle(PointF* points, | |
1075 const CFX_Matrix* pMatrix, | |
1076 int& v1, | |
1077 int& v2) { | |
1078 int pairs[] = {1, 2, 0, 2, 0, 1}; | |
1079 for (int i = 0; i < 3; i++) { | |
1080 int pair1 = pairs[i * 2]; | |
1081 int pair2 = pairs[i * 2 + 1]; | |
1082 FX_FLOAT x1 = points[pair1].X, x2 = points[pair2].X; | |
1083 FX_FLOAT y1 = points[pair1].Y, y2 = points[pair2].Y; | |
1084 if (pMatrix) { | |
1085 pMatrix->Transform(x1, y1); | |
1086 pMatrix->Transform(x2, y2); | |
1087 } | |
1088 FX_FLOAT dx = x1 - x2; | |
1089 FX_FLOAT dy = y1 - y2; | |
1090 FX_FLOAT distance_square = (dx * dx) + (dy * dy); | |
1091 if (distance_square < (1.0f * 2 + 1.0f / 4)) { | |
1092 v1 = i; | |
1093 v2 = pair1; | |
1094 return TRUE; | |
1095 } | |
1096 } | |
1097 return FALSE; | |
1098 } | |
1099 FX_BOOL CGdiplusExt::DrawPath(HDC hDC, | |
1100 const CFX_PathData* pPathData, | |
1101 const CFX_Matrix* pObject2Device, | |
1102 const CFX_GraphStateData* pGraphState, | |
1103 FX_DWORD fill_argb, | |
1104 FX_DWORD stroke_argb, | |
1105 int fill_mode) { | |
1106 int nPoints = pPathData->GetPointCount(); | |
1107 if (nPoints == 0) { | |
1108 return TRUE; | |
1109 } | |
1110 FX_PATHPOINT* pPoints = pPathData->GetPoints(); | |
1111 GpGraphics* pGraphics = NULL; | |
1112 CGdiplusExt& GdiplusExt = | |
1113 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
1114 CallFunc(GdipCreateFromHDC)(hDC, &pGraphics); | |
1115 CallFunc(GdipSetPageUnit)(pGraphics, UnitPixel); | |
1116 CallFunc(GdipSetPixelOffsetMode)(pGraphics, PixelOffsetModeHalf); | |
1117 GpMatrix* pMatrix = NULL; | |
1118 if (pObject2Device) { | |
1119 CallFunc(GdipCreateMatrix2)(pObject2Device->a, pObject2Device->b, | |
1120 pObject2Device->c, pObject2Device->d, | |
1121 pObject2Device->e, pObject2Device->f, &pMatrix); | |
1122 CallFunc(GdipSetWorldTransform)(pGraphics, pMatrix); | |
1123 } | |
1124 PointF* points = FX_Alloc(PointF, nPoints); | |
1125 BYTE* types = FX_Alloc(BYTE, nPoints); | |
1126 int nSubPathes = 0; | |
1127 FX_BOOL bSubClose = FALSE; | |
1128 int pos_subclose = 0; | |
1129 FX_BOOL bSmooth = FALSE; | |
1130 int startpoint = 0; | |
1131 for (int i = 0; i < nPoints; i++) { | |
1132 points[i].X = pPoints[i].m_PointX; | |
1133 points[i].Y = pPoints[i].m_PointY; | |
1134 FX_FLOAT x, y; | |
1135 if (pObject2Device) { | |
1136 pObject2Device->Transform(pPoints[i].m_PointX, pPoints[i].m_PointY, x, y); | |
1137 } else { | |
1138 x = pPoints[i].m_PointX; | |
1139 y = pPoints[i].m_PointY; | |
1140 } | |
1141 if (x > 50000 * 1.0f) { | |
1142 points[i].X = 50000 * 1.0f; | |
1143 } | |
1144 if (x < -50000 * 1.0f) { | |
1145 points[i].X = -50000 * 1.0f; | |
1146 } | |
1147 if (y > 50000 * 1.0f) { | |
1148 points[i].Y = 50000 * 1.0f; | |
1149 } | |
1150 if (y < -50000 * 1.0f) { | |
1151 points[i].Y = -50000 * 1.0f; | |
1152 } | |
1153 int point_type = pPoints[i].m_Flag & FXPT_TYPE; | |
1154 if (point_type == FXPT_MOVETO) { | |
1155 types[i] = PathPointTypeStart; | |
1156 nSubPathes++; | |
1157 bSubClose = FALSE; | |
1158 startpoint = i; | |
1159 } else if (point_type == FXPT_LINETO) { | |
1160 types[i] = PathPointTypeLine; | |
1161 if (pPoints[i - 1].m_Flag == FXPT_MOVETO && | |
1162 (i == nPoints - 1 || pPoints[i + 1].m_Flag == FXPT_MOVETO) && | |
1163 points[i].Y == points[i - 1].Y && points[i].X == points[i - 1].X) { | |
1164 points[i].X += 0.01f; | |
1165 continue; | |
1166 } | |
1167 if (!bSmooth && points[i].X != points[i - 1].X && | |
1168 points[i].Y != points[i - 1].Y) { | |
1169 bSmooth = TRUE; | |
1170 } | |
1171 } else if (point_type == FXPT_BEZIERTO) { | |
1172 types[i] = PathPointTypeBezier; | |
1173 bSmooth = TRUE; | |
1174 } | |
1175 if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE) { | |
1176 if (bSubClose) { | |
1177 types[pos_subclose] &= ~PathPointTypeCloseSubpath; | |
1178 } else { | |
1179 bSubClose = TRUE; | |
1180 } | |
1181 pos_subclose = i; | |
1182 types[i] |= PathPointTypeCloseSubpath; | |
1183 if (!bSmooth && points[i].X != points[startpoint].X && | |
1184 points[i].Y != points[startpoint].Y) { | |
1185 bSmooth = TRUE; | |
1186 } | |
1187 } | |
1188 } | |
1189 if (fill_mode & FXFILL_NOPATHSMOOTH) { | |
1190 bSmooth = FALSE; | |
1191 CallFunc(GdipSetSmoothingMode)(pGraphics, SmoothingModeNone); | |
1192 } else if (!(fill_mode & FXFILL_FULLCOVER)) { | |
1193 if (!bSmooth && (fill_mode & 3)) { | |
1194 bSmooth = TRUE; | |
1195 } | |
1196 if (bSmooth || (pGraphState && pGraphState->m_LineWidth > 2)) { | |
1197 CallFunc(GdipSetSmoothingMode)(pGraphics, SmoothingModeAntiAlias); | |
1198 } | |
1199 } | |
1200 int new_fill_mode = fill_mode & 3; | |
1201 if (nPoints == 4 && !pGraphState) { | |
1202 int v1, v2; | |
1203 if (IsSmallTriangle(points, pObject2Device, v1, v2)) { | |
1204 GpPen* pPen = NULL; | |
1205 CallFunc(GdipCreatePen1)(fill_argb, 1.0f, UnitPixel, &pPen); | |
1206 CallFunc(GdipDrawLineI)( | |
1207 pGraphics, pPen, FXSYS_round(points[v1].X), FXSYS_round(points[v1].Y), | |
1208 FXSYS_round(points[v2].X), FXSYS_round(points[v2].Y)); | |
1209 CallFunc(GdipDeletePen)(pPen); | |
1210 return TRUE; | |
1211 } | |
1212 } | |
1213 GpPath* pGpPath = NULL; | |
1214 CallFunc(GdipCreatePath2)(points, types, nPoints, | |
1215 GdiFillType2Gdip(new_fill_mode), &pGpPath); | |
1216 if (!pGpPath) { | |
1217 if (pMatrix) { | |
1218 CallFunc(GdipDeleteMatrix)(pMatrix); | |
1219 } | |
1220 FX_Free(points); | |
1221 FX_Free(types); | |
1222 CallFunc(GdipDeleteGraphics)(pGraphics); | |
1223 return FALSE; | |
1224 } | |
1225 if (new_fill_mode) { | |
1226 GpBrush* pBrush = _GdipCreateBrush(fill_argb); | |
1227 CallFunc(GdipSetPathFillMode)(pGpPath, GdiFillType2Gdip(new_fill_mode)); | |
1228 CallFunc(GdipFillPath)(pGraphics, pBrush, pGpPath); | |
1229 CallFunc(GdipDeleteBrush)(pBrush); | |
1230 } | |
1231 if (pGraphState && stroke_argb) { | |
1232 GpPen* pPen = _GdipCreatePen(pGraphState, pObject2Device, stroke_argb, | |
1233 fill_mode & FX_STROKE_TEXT_MODE); | |
1234 if (nSubPathes == 1) { | |
1235 CallFunc(GdipDrawPath)(pGraphics, pPen, pGpPath); | |
1236 } else { | |
1237 int iStart = 0; | |
1238 for (int i = 0; i < nPoints; i++) { | |
1239 if (i == nPoints - 1 || types[i + 1] == PathPointTypeStart) { | |
1240 GpPath* pSubPath; | |
1241 CallFunc(GdipCreatePath2)(points + iStart, types + iStart, | |
1242 i - iStart + 1, | |
1243 GdiFillType2Gdip(new_fill_mode), &pSubPath); | |
1244 iStart = i + 1; | |
1245 CallFunc(GdipDrawPath)(pGraphics, pPen, pSubPath); | |
1246 CallFunc(GdipDeletePath)(pSubPath); | |
1247 } | |
1248 } | |
1249 } | |
1250 CallFunc(GdipDeletePen)(pPen); | |
1251 } | |
1252 if (pMatrix) { | |
1253 CallFunc(GdipDeleteMatrix)(pMatrix); | |
1254 } | |
1255 FX_Free(points); | |
1256 FX_Free(types); | |
1257 CallFunc(GdipDeletePath)(pGpPath); | |
1258 CallFunc(GdipDeleteGraphics)(pGraphics); | |
1259 return TRUE; | |
1260 } | |
1261 class GpStream final : public IStream { | |
1262 LONG m_RefCount; | |
1263 int m_ReadPos; | |
1264 CFX_ByteTextBuf m_InterStream; | |
1265 | |
1266 public: | |
1267 GpStream() { | |
1268 m_RefCount = 1; | |
1269 m_ReadPos = 0; | |
1270 } | |
1271 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, | |
1272 void** ppvObject) { | |
1273 if (iid == __uuidof(IUnknown) || iid == __uuidof(IStream) || | |
1274 iid == __uuidof(ISequentialStream)) { | |
1275 *ppvObject = static_cast<IStream*>(this); | |
1276 AddRef(); | |
1277 return S_OK; | |
1278 } | |
1279 return E_NOINTERFACE; | |
1280 } | |
1281 virtual ULONG STDMETHODCALLTYPE AddRef(void) { | |
1282 return (ULONG)InterlockedIncrement(&m_RefCount); | |
1283 } | |
1284 virtual ULONG STDMETHODCALLTYPE Release(void) { | |
1285 ULONG res = (ULONG)InterlockedDecrement(&m_RefCount); | |
1286 if (res == 0) { | |
1287 delete this; | |
1288 } | |
1289 return res; | |
1290 } | |
1291 | |
1292 public: | |
1293 virtual HRESULT STDMETHODCALLTYPE Read(void* Output, | |
1294 ULONG cb, | |
1295 ULONG* pcbRead) { | |
1296 size_t bytes_left; | |
1297 size_t bytes_out; | |
1298 if (pcbRead) { | |
1299 *pcbRead = 0; | |
1300 } | |
1301 if (m_ReadPos == m_InterStream.GetLength()) { | |
1302 return HRESULT_FROM_WIN32(ERROR_END_OF_MEDIA); | |
1303 } | |
1304 bytes_left = m_InterStream.GetLength() - m_ReadPos; | |
1305 bytes_out = std::min(pdfium::base::checked_cast<size_t>(cb), bytes_left); | |
1306 FXSYS_memcpy(Output, m_InterStream.GetBuffer() + m_ReadPos, bytes_out); | |
1307 m_ReadPos += (int32_t)bytes_out; | |
1308 if (pcbRead) { | |
1309 *pcbRead = (ULONG)bytes_out; | |
1310 } | |
1311 return S_OK; | |
1312 } | |
1313 virtual HRESULT STDMETHODCALLTYPE Write(void const* Input, | |
1314 ULONG cb, | |
1315 ULONG* pcbWritten) { | |
1316 if (cb <= 0) { | |
1317 if (pcbWritten) { | |
1318 *pcbWritten = 0; | |
1319 } | |
1320 return S_OK; | |
1321 } | |
1322 m_InterStream.InsertBlock(m_InterStream.GetLength(), Input, cb); | |
1323 if (pcbWritten) { | |
1324 *pcbWritten = cb; | |
1325 } | |
1326 return S_OK; | |
1327 } | |
1328 | |
1329 public: | |
1330 virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) { | |
1331 return E_NOTIMPL; | |
1332 } | |
1333 virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, | |
1334 ULARGE_INTEGER, | |
1335 ULARGE_INTEGER*, | |
1336 ULARGE_INTEGER*) { | |
1337 return E_NOTIMPL; | |
1338 } | |
1339 virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) { return E_NOTIMPL; } | |
1340 virtual HRESULT STDMETHODCALLTYPE Revert(void) { return E_NOTIMPL; } | |
1341 virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, | |
1342 ULARGE_INTEGER, | |
1343 DWORD) { | |
1344 return E_NOTIMPL; | |
1345 } | |
1346 virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, | |
1347 ULARGE_INTEGER, | |
1348 DWORD) { | |
1349 return E_NOTIMPL; | |
1350 } | |
1351 virtual HRESULT STDMETHODCALLTYPE Clone(IStream** stream) { | |
1352 return E_NOTIMPL; | |
1353 } | |
1354 virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, | |
1355 DWORD dwOrigin, | |
1356 ULARGE_INTEGER* lpNewFilePointer) { | |
1357 long start = 0; | |
1358 long new_read_position; | |
1359 switch (dwOrigin) { | |
1360 case STREAM_SEEK_SET: | |
1361 start = 0; | |
1362 break; | |
1363 case STREAM_SEEK_CUR: | |
1364 start = m_ReadPos; | |
1365 break; | |
1366 case STREAM_SEEK_END: | |
1367 start = m_InterStream.GetLength(); | |
1368 break; | |
1369 default: | |
1370 return STG_E_INVALIDFUNCTION; | |
1371 break; | |
1372 } | |
1373 new_read_position = start + (long)liDistanceToMove.QuadPart; | |
1374 if (new_read_position < 0 || | |
1375 new_read_position > m_InterStream.GetLength()) { | |
1376 return STG_E_SEEKERROR; | |
1377 } | |
1378 m_ReadPos = new_read_position; | |
1379 if (lpNewFilePointer) { | |
1380 lpNewFilePointer->QuadPart = m_ReadPos; | |
1381 } | |
1382 return S_OK; | |
1383 } | |
1384 virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag) { | |
1385 if (!pStatstg) { | |
1386 return STG_E_INVALIDFUNCTION; | |
1387 } | |
1388 ZeroMemory(pStatstg, sizeof(STATSTG)); | |
1389 pStatstg->cbSize.QuadPart = m_InterStream.GetLength(); | |
1390 return S_OK; | |
1391 } | |
1392 }; | |
1393 typedef struct { | |
1394 BITMAPINFO* pbmi; | |
1395 int Stride; | |
1396 LPBYTE pScan0; | |
1397 GpBitmap* pBitmap; | |
1398 BitmapData* pBitmapData; | |
1399 GpStream* pStream; | |
1400 } PREVIEW3_DIBITMAP; | |
1401 static PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { | |
1402 GpBitmap* pBitmap; | |
1403 GpStream* pStream = NULL; | |
1404 CGdiplusExt& GdiplusExt = | |
1405 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
1406 Status status = Ok; | |
1407 if (args.flags == WINDIB_OPEN_PATHNAME) { | |
1408 status = CallFunc(GdipCreateBitmapFromFileICM)((wchar_t*)args.path_name, | |
1409 &pBitmap); | |
1410 } else { | |
1411 if (args.memory_size == 0 || !args.memory_base) { | |
1412 return NULL; | |
1413 } | |
1414 pStream = new GpStream; | |
1415 pStream->Write(args.memory_base, (ULONG)args.memory_size, NULL); | |
1416 status = CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap); | |
1417 } | |
1418 if (status != Ok) { | |
1419 if (pStream) { | |
1420 pStream->Release(); | |
1421 } | |
1422 return NULL; | |
1423 } | |
1424 UINT height, width; | |
1425 CallFunc(GdipGetImageHeight)(pBitmap, &height); | |
1426 CallFunc(GdipGetImageWidth)(pBitmap, &width); | |
1427 PixelFormat pixel_format; | |
1428 CallFunc(GdipGetImagePixelFormat)(pBitmap, &pixel_format); | |
1429 int info_size = sizeof(BITMAPINFOHEADER); | |
1430 int bpp = 24; | |
1431 int dest_pixel_format = PixelFormat24bppRGB; | |
1432 if (pixel_format == PixelFormat1bppIndexed) { | |
1433 info_size += 8; | |
1434 bpp = 1; | |
1435 dest_pixel_format = PixelFormat1bppIndexed; | |
1436 } else if (pixel_format == PixelFormat8bppIndexed) { | |
1437 info_size += 1024; | |
1438 bpp = 8; | |
1439 dest_pixel_format = PixelFormat8bppIndexed; | |
1440 } else if (pixel_format == PixelFormat32bppARGB) { | |
1441 bpp = 32; | |
1442 dest_pixel_format = PixelFormat32bppARGB; | |
1443 } | |
1444 LPBYTE buf = FX_Alloc(BYTE, info_size); | |
1445 BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)buf; | |
1446 pbmih->biBitCount = bpp; | |
1447 pbmih->biCompression = BI_RGB; | |
1448 pbmih->biHeight = -(int)height; | |
1449 pbmih->biPlanes = 1; | |
1450 pbmih->biWidth = width; | |
1451 Rect rect(0, 0, width, height); | |
1452 BitmapData* pBitmapData = FX_Alloc(BitmapData, 1); | |
1453 CallFunc(GdipBitmapLockBits)(pBitmap, &rect, ImageLockModeRead, | |
1454 dest_pixel_format, pBitmapData); | |
1455 if (pixel_format == PixelFormat1bppIndexed || | |
1456 pixel_format == PixelFormat8bppIndexed) { | |
1457 DWORD* ppal = (DWORD*)(buf + sizeof(BITMAPINFOHEADER)); | |
1458 struct { | |
1459 UINT flags; | |
1460 UINT Count; | |
1461 DWORD Entries[256]; | |
1462 } pal; | |
1463 int size = 0; | |
1464 CallFunc(GdipGetImagePaletteSize)(pBitmap, &size); | |
1465 CallFunc(GdipGetImagePalette)(pBitmap, (ColorPalette*)&pal, size); | |
1466 int entries = pixel_format == PixelFormat1bppIndexed ? 2 : 256; | |
1467 for (int i = 0; i < entries; i++) { | |
1468 ppal[i] = pal.Entries[i] & 0x00ffffff; | |
1469 } | |
1470 } | |
1471 PREVIEW3_DIBITMAP* pInfo = FX_Alloc(PREVIEW3_DIBITMAP, 1); | |
1472 pInfo->pbmi = (BITMAPINFO*)buf; | |
1473 pInfo->pScan0 = (LPBYTE)pBitmapData->Scan0; | |
1474 pInfo->Stride = pBitmapData->Stride; | |
1475 pInfo->pBitmap = pBitmap; | |
1476 pInfo->pBitmapData = pBitmapData; | |
1477 pInfo->pStream = pStream; | |
1478 return pInfo; | |
1479 } | |
1480 static void FreeDIBitmap(PREVIEW3_DIBITMAP* pInfo) { | |
1481 CGdiplusExt& GdiplusExt = | |
1482 ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; | |
1483 CallFunc(GdipBitmapUnlockBits)(pInfo->pBitmap, pInfo->pBitmapData); | |
1484 CallFunc(GdipDisposeImage)(pInfo->pBitmap); | |
1485 FX_Free(pInfo->pBitmapData); | |
1486 FX_Free((LPBYTE)pInfo->pbmi); | |
1487 if (pInfo->pStream) { | |
1488 pInfo->pStream->Release(); | |
1489 } | |
1490 FX_Free(pInfo); | |
1491 } | |
1492 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, | |
1493 LPVOID pData, | |
1494 FX_BOOL bAlpha); | |
1495 CFX_DIBitmap* CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) { | |
1496 PREVIEW3_DIBITMAP* pInfo = ::LoadDIBitmap(args); | |
1497 if (!pInfo) { | |
1498 return NULL; | |
1499 } | |
1500 int height = abs(pInfo->pbmi->bmiHeader.biHeight); | |
1501 int width = pInfo->pbmi->bmiHeader.biWidth; | |
1502 int dest_pitch = (width * pInfo->pbmi->bmiHeader.biBitCount + 31) / 32 * 4; | |
1503 LPBYTE pData = FX_Alloc2D(BYTE, dest_pitch, height); | |
1504 if (dest_pitch == pInfo->Stride) { | |
1505 FXSYS_memcpy(pData, pInfo->pScan0, dest_pitch * height); | |
1506 } else { | |
1507 for (int i = 0; i < height; i++) { | |
1508 FXSYS_memcpy(pData + dest_pitch * i, pInfo->pScan0 + pInfo->Stride * i, | |
1509 dest_pitch); | |
1510 } | |
1511 } | |
1512 CFX_DIBitmap* pDIBitmap = _FX_WindowsDIB_LoadFromBuf( | |
1513 pInfo->pbmi, pData, pInfo->pbmi->bmiHeader.biBitCount == 32); | |
1514 FX_Free(pData); | |
1515 FreeDIBitmap(pInfo); | |
1516 return pDIBitmap; | |
1517 } | |
1518 #endif | |
OLD | NEW |