| 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 |