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 <crtdbg.h> 11 12 #include "core/include/fxcodec/fx_codec.h" 13 #include "core/include/fxge/fx_freetype.h" 14 #include "core/include/fxge/fx_ge_win32.h" 15 #include "core/src/fxge/agg/include/fx_agg_driver.h" 16 #include "core/src/fxge/dib/dib_int.h" 17 #include "core/src/fxge/ge/text_int.h" 18 #include "dwrite_int.h" 19 #include "win32_int.h" 20 21 class CFX_Win32FallbackFontInfo final : public CFX_FolderFontInfo { 22 public: 23 void* MapFont(int weight, 24 FX_BOOL bItalic, 25 int charset, 26 int pitch_family, 27 const FX_CHAR* family, 28 int& iExact) override; 29 }; 30 class CFX_Win32FontInfo final : public IFX_SystemFontInfo { 31 public: 32 CFX_Win32FontInfo(); 33 ~CFX_Win32FontInfo() override; 34 35 // IFX_SystemFontInfo 36 void Release() override; 37 FX_BOOL EnumFontList(CFX_FontMapper* pMapper) override; 38 void* MapFont(int weight, 39 FX_BOOL bItalic, 40 int charset, 41 int pitch_family, 42 const FX_CHAR* face, 43 int& iExact) override; 44 void* GetFont(const FX_CHAR* face) override { return NULL; } 45 FX_DWORD GetFontData(void* hFont, 46 FX_DWORD table, 47 uint8_t* buffer, 48 FX_DWORD size) override; 49 FX_BOOL GetFaceName(void* hFont, CFX_ByteString& name) override; 50 FX_BOOL GetFontCharset(void* hFont, int& charset) override; 51 void DeleteFont(void* hFont) override; 52 53 FX_BOOL IsOpenTypeFromDiv(const LOGFONTA* plf); 54 FX_BOOL IsSupportFontFormDiv(const LOGFONTA* plf); 55 void AddInstalledFont(const LOGFONTA* plf, FX_DWORD FontType); 56 void GetGBPreference(CFX_ByteString& face, int weight, int picth_family); 57 void GetJapanesePreference(CFX_ByteString& face, 58 int weight, 59 int picth_family); 60 CFX_ByteString FindFont(const CFX_ByteString& name); 61 HDC m_hDC; 62 CFX_FontMapper* m_pMapper; 63 CFX_ByteString m_LastFamily; 64 CFX_ByteString m_KaiTi, m_FangSong; 65 }; 66 67 CFX_Win32FontInfo::CFX_Win32FontInfo() { 68 m_hDC = CreateCompatibleDC(NULL); 69 } 70 CFX_Win32FontInfo::~CFX_Win32FontInfo() { 71 m_pMapper = NULL; 72 } 73 void CFX_Win32FontInfo::Release() { 74 DeleteDC(m_hDC); 75 delete this; 76 } 77 #define TT_MAKE_TAG(x1, x2, x3, x4) \ 78 (((FX_DWORD)x1 << 24) | ((FX_DWORD)x2 << 16) | ((FX_DWORD)x3 << 8) | \ 79 (FX_DWORD)x4) 80 FX_BOOL CFX_Win32FontInfo::IsOpenTypeFromDiv(const LOGFONTA* plf) { 81 HFONT hFont = CreateFontIndirectA(plf); 82 FX_BOOL ret = FALSE; 83 FX_DWORD font_size = GetFontData(hFont, 0, NULL, 0); 84 if (font_size != GDI_ERROR && font_size >= sizeof(FX_DWORD)) { 85 FX_DWORD lVersion = 0; 86 GetFontData(hFont, 0, (uint8_t*)(&lVersion), sizeof(FX_DWORD)); 87 lVersion = (((FX_DWORD)(uint8_t)(lVersion)) << 24) | 88 ((FX_DWORD)((uint8_t)(lVersion >> 8))) << 16 | 89 ((FX_DWORD)((uint8_t)(lVersion >> 16))) << 8 | 90 ((uint8_t)(lVersion >> 24)); 91 if (lVersion == TT_MAKE_TAG('O', 'T', 'T', 'O') || lVersion == 0x00010000 || 92 lVersion == TT_MAKE_TAG('t', 't', 'c', 'f') || 93 lVersion == TT_MAKE_TAG('t', 'r', 'u', 'e') || lVersion == 0x00020000) { 94 ret = TRUE; 95 } 96 } 97 DeleteFont(hFont); 98 return ret; 99 } 100 FX_BOOL CFX_Win32FontInfo::IsSupportFontFormDiv(const LOGFONTA* plf) { 101 HFONT hFont = CreateFontIndirectA(plf); 102 FX_BOOL ret = FALSE; 103 FX_DWORD font_size = GetFontData(hFont, 0, NULL, 0); 104 if (font_size != GDI_ERROR && font_size >= sizeof(FX_DWORD)) { 105 FX_DWORD lVersion = 0; 106 GetFontData(hFont, 0, (uint8_t*)(&lVersion), sizeof(FX_DWORD)); 107 lVersion = (((FX_DWORD)(uint8_t)(lVersion)) << 24) | 108 ((FX_DWORD)((uint8_t)(lVersion >> 8))) << 16 | 109 ((FX_DWORD)((uint8_t)(lVersion >> 16))) << 8 | 110 ((uint8_t)(lVersion >> 24)); 111 if (lVersion == TT_MAKE_TAG('O', 'T', 'T', 'O') || lVersion == 0x00010000 || 112 lVersion == TT_MAKE_TAG('t', 't', 'c', 'f') || 113 lVersion == TT_MAKE_TAG('t', 'r', 'u', 'e') || lVersion == 0x00020000) { 114 ret = TRUE; 115 } else if ((lVersion & 0xFFFF0000) == TT_MAKE_TAG(0x80, 0x01, 0x00, 0x00) || 116 (lVersion & 0xFFFF0000) == TT_MAKE_TAG('%', '!', 0, 0)) { 117 ret = TRUE; 118 } 119 } 120 DeleteFont(hFont); 121 return ret; 122 } 123 void CFX_Win32FontInfo::AddInstalledFont(const LOGFONTA* plf, 124 FX_DWORD FontType) { 125 CFX_ByteString name(plf->lfFaceName); 126 if (name[0] == '@') { 127 return; 128 } 129 if (name == m_LastFamily) { 130 m_pMapper->AddInstalledFont(name, plf->lfCharSet); 131 return; 132 } 133 if (!(FontType & TRUETYPE_FONTTYPE) && !(FontType & DEVICE_FONTTYPE)) { 134 return; 135 } 136 if (!(FontType & TRUETYPE_FONTTYPE)) { 137 if (!IsSupportFontFormDiv(plf)) { 138 return; 139 } 140 } 141 m_pMapper->AddInstalledFont(name, plf->lfCharSet); 142 m_LastFamily = name; 143 } 144 static int CALLBACK FontEnumProc(const LOGFONTA* plf, 145 const TEXTMETRICA* lpntme, 146 FX_DWORD FontType, 147 LPARAM lParam) { 148 CFX_Win32FontInfo* pFontInfo = (CFX_Win32FontInfo*)lParam; 149 if (pFontInfo->m_pMapper->GetFontEnumerator()) { 150 pFontInfo->m_pMapper->GetFontEnumerator()->HitFont(); 151 } 152 pFontInfo->AddInstalledFont(plf, FontType); 153 return 1; 154 } 155 FX_BOOL CFX_Win32FontInfo::EnumFontList(CFX_FontMapper* pMapper) { 156 m_pMapper = pMapper; 157 LOGFONTA lf; 158 FXSYS_memset(&lf, 0, sizeof(LOGFONTA)); 159 lf.lfCharSet = DEFAULT_CHARSET; 160 lf.lfFaceName[0] = 0; 161 lf.lfPitchAndFamily = 0; 162 EnumFontFamiliesExA(m_hDC, &lf, (FONTENUMPROCA)FontEnumProc, (uintptr_t) this, 163 0); 164 if (pMapper->GetFontEnumerator()) { 165 pMapper->GetFontEnumerator()->Finish(); 166 } 167 return TRUE; 168 } 169 static const struct { 170 const FX_CHAR* m_pFaceName; 171 const FX_CHAR* m_pVariantName; 172 } VariantNames[] = { 173 {"DFKai-SB", "\x19\x6A\x77\x69\xD4\x9A"}, 174 }; 175 static const struct { 176 const FX_CHAR* m_pName; 177 const FX_CHAR* m_pWinName; 178 FX_BOOL m_bBold; 179 FX_BOOL m_bItalic; 180 } Base14Substs[] = { 181 {"Courier", "Courier New", FALSE, FALSE}, 182 {"Courier-Bold", "Courier New", TRUE, FALSE}, 183 {"Courier-BoldOblique", "Courier New", TRUE, TRUE}, 184 {"Courier-Oblique", "Courier New", FALSE, TRUE}, 185 {"Helvetica", "Arial", FALSE, FALSE}, 186 {"Helvetica-Bold", "Arial", TRUE, FALSE}, 187 {"Helvetica-BoldOblique", "Arial", TRUE, TRUE}, 188 {"Helvetica-Oblique", "Arial", FALSE, TRUE}, 189 {"Times-Roman", "Times New Roman", FALSE, FALSE}, 190 {"Times-Bold", "Times New Roman", TRUE, FALSE}, 191 {"Times-BoldItalic", "Times New Roman", TRUE, TRUE}, 192 {"Times-Italic", "Times New Roman", FALSE, TRUE}, 193 }; 194 CFX_ByteString CFX_Win32FontInfo::FindFont(const CFX_ByteString& name) { 195 if (!m_pMapper) { 196 return name; 197 } 198 int nFonts = m_pMapper->m_InstalledTTFonts.GetSize(); 199 for (int i = 0; i < nFonts; i++) { 200 CFX_ByteString thisname = m_pMapper->m_InstalledTTFonts[i]; 201 if (thisname[0] == ' ') { 202 if (thisname.Mid(1, name.GetLength()) == name) { 203 return m_pMapper->m_InstalledTTFonts[i + 1]; 204 } 205 } else if (thisname.Left(name.GetLength()) == name) { 206 return m_pMapper->m_InstalledTTFonts[i]; 207 } 208 } 209 return CFX_ByteString(); 210 } 211 void* CFX_Win32FallbackFontInfo::MapFont(int weight, 212 FX_BOOL bItalic, 213 int charset, 214 int pitch_family, 215 const FX_CHAR* cstr_face, 216 int& iExact) { 217 void* font = GetSubstFont(cstr_face); 218 if (font) { 219 iExact = 1; 220 return font; 221 } 222 FX_BOOL bCJK = TRUE; 223 switch (charset) { 224 case FXFONT_SHIFTJIS_CHARSET: 225 case FXFONT_GB2312_CHARSET: 226 case FXFONT_CHINESEBIG5_CHARSET: 227 case FXFONT_HANGEUL_CHARSET: 228 default: 229 bCJK = FALSE; 230 break; 231 } 232 return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); 233 } 234 struct _FontNameMap { 235 const FX_CHAR* m_pSubFontName; 236 const FX_CHAR* m_pSrcFontName; 237 }; 238 const _FontNameMap g_JpFontNameMap[] = { 239 {"MS Mincho", "Heiseimin-W3"}, 240 {"MS Gothic", "Jun101-Light"}, 241 }; 242 extern "C" { 243 static int compareString(const void* key, const void* element) { 244 return FXSYS_stricmp((const FX_CHAR*)key, 245 ((_FontNameMap*)element)->m_pSrcFontName); 246 } 247 } 248 FX_BOOL _GetSubFontName(CFX_ByteString& name) { 249 int size = sizeof g_JpFontNameMap; 250 void* pFontnameMap = (void*)g_JpFontNameMap; 251 _FontNameMap* found = (_FontNameMap*)FXSYS_bsearch( 252 name.c_str(), pFontnameMap, size / sizeof(_FontNameMap), 253 sizeof(_FontNameMap), compareString); 254 if (!found) { 255 return FALSE; 256 } 257 name = found->m_pSubFontName; 258 return TRUE; 259 } 260 void CFX_Win32FontInfo::GetGBPreference(CFX_ByteString& face, 261 int weight, 262 int picth_family) { 263 if (face.Find("KaiTi") >= 0 || face.Find("\xbf\xac") >= 0) { 264 if (m_KaiTi.IsEmpty()) { 265 m_KaiTi = FindFont("KaiTi"); 266 if (m_KaiTi.IsEmpty()) { 267 m_KaiTi = "SimSun"; 268 } 269 } 270 face = m_KaiTi; 271 } else if (face.Find("FangSong") >= 0 || face.Find("\xb7\xc2\xcb\xce") >= 0) { 272 if (m_FangSong.IsEmpty()) { 273 m_FangSong = FindFont("FangSong"); 274 if (m_FangSong.IsEmpty()) { 275 m_FangSong = "SimSun"; 276 } 277 } 278 face = m_FangSong; 279 } else if (face.Find("SimSun") >= 0 || face.Find("\xcb\xce") >= 0) { 280 face = "SimSun"; 281 } else if (face.Find("SimHei") >= 0 || face.Find("\xba\xda") >= 0) { 282 face = "SimHei"; 283 } else if (!(picth_family & FF_ROMAN) && weight > 550) { 284 face = "SimHei"; 285 } else { 286 face = "SimSun"; 287 } 288 } 289 void CFX_Win32FontInfo::GetJapanesePreference(CFX_ByteString& face, 290 int weight, 291 int picth_family) { 292 if (face.Find("Gothic") >= 0 || 293 face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { 294 if (face.Find("PGothic") >= 0 || 295 face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { 296 face = "MS PGothic"; 297 } else if (face.Find("UI Gothic") >= 0) { 298 face = "MS UI Gothic"; 299 } else { 300 if (face.Find("HGSGothicM") >= 0 || face.Find("HGMaruGothicMPRO") >= 0) { 301 face = "MS PGothic"; 302 } else { 303 face = "MS Gothic"; 304 } 305 } 306 return; 307 } 308 if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { 309 if (face.Find("PMincho") >= 0 || 310 face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { 311 face = "MS PMincho"; 312 } else { 313 face = "MS Mincho"; 314 } 315 return; 316 } 317 if (_GetSubFontName(face)) { 318 return; 319 } 320 if (!(picth_family & FF_ROMAN) && weight > 400) { 321 face = "MS PGothic"; 322 } else { 323 face = "MS PMincho"; 324 } 325 } 326 void* CFX_Win32FontInfo::MapFont(int weight, 327 FX_BOOL bItalic, 328 int charset, 329 int pitch_family, 330 const FX_CHAR* cstr_face, 331 int& iExact) { 332 CFX_ByteString face = cstr_face; 333 int iBaseFont; 334 for (iBaseFont = 0; iBaseFont < 12; iBaseFont++) 335 if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) { 336 face = Base14Substs[iBaseFont].m_pWinName; 337 weight = Base14Substs[iBaseFont].m_bBold ? FW_BOLD : FW_NORMAL; 338 bItalic = Base14Substs[iBaseFont].m_bItalic; 339 iExact = TRUE; 340 break; 341 } 342 if (charset == ANSI_CHARSET || charset == SYMBOL_CHARSET) { 343 charset = DEFAULT_CHARSET; 344 } 345 int subst_pitch_family = pitch_family; 346 switch (charset) { 347 case SHIFTJIS_CHARSET: 348 subst_pitch_family = FF_ROMAN; 349 break; 350 case CHINESEBIG5_CHARSET: 351 case HANGUL_CHARSET: 352 case GB2312_CHARSET: 353 subst_pitch_family = 0; 354 break; 355 } 356 HFONT hFont = 357 ::CreateFontA(-10, 0, 0, 0, weight, bItalic, 0, 0, charset, 358 OUT_TT_ONLY_PRECIS, 0, 0, subst_pitch_family, face); 359 char facebuf[100]; 360 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, hFont); 361 ::GetTextFaceA(m_hDC, 100, facebuf); 362 ::SelectObject(m_hDC, hOldFont); 363 if (face.EqualNoCase(facebuf)) { 364 return hFont; 365 } 366 int iCount = sizeof(VariantNames) / sizeof(VariantNames[0]); 367 for (int i = 0; i < iCount; ++i) { 368 if (face == VariantNames[i].m_pFaceName) { 369 CFX_WideString wsFace = CFX_WideString::FromLocal(facebuf); 370 const unsigned short* pName = 371 (const unsigned short*)VariantNames[i].m_pVariantName; 372 FX_STRSIZE len = CFX_WideString::WStringLength(pName); 373 CFX_WideString wsName = CFX_WideString::FromUTF16LE(pName, len); 374 if (wsFace == wsName) { 375 return hFont; 376 } 377 } 378 } 379 ::DeleteObject(hFont); 380 if (charset == DEFAULT_CHARSET) { 381 return NULL; 382 } 383 switch (charset) { 384 case SHIFTJIS_CHARSET: 385 GetJapanesePreference(face, weight, pitch_family); 386 break; 387 case GB2312_CHARSET: 388 GetGBPreference(face, weight, pitch_family); 389 break; 390 case HANGUL_CHARSET: 391 face = "Gulim"; 392 break; 393 case CHINESEBIG5_CHARSET: 394 if (face.Find("MSung") >= 0) { 395 face = "MingLiU"; 396 } else { 397 face = "PMingLiU"; 398 } 399 break; 400 } 401 hFont = ::CreateFontA(-10, 0, 0, 0, weight, bItalic, 0, 0, charset, 402 OUT_TT_ONLY_PRECIS, 0, 0, subst_pitch_family, face); 403 return hFont; 404 } 405 void CFX_Win32FontInfo::DeleteFont(void* hFont) { 406 ::DeleteObject(hFont); 407 } 408 FX_DWORD CFX_Win32FontInfo::GetFontData(void* hFont, 409 FX_DWORD table, 410 uint8_t* buffer, 411 FX_DWORD size) { 412 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont); 413 table = FXDWORD_FROM_MSBFIRST(table); 414 size = ::GetFontData(m_hDC, table, 0, buffer, size); 415 ::SelectObject(m_hDC, hOldFont); 416 if (size == GDI_ERROR) { 417 return 0; 418 } 419 return size; 420 } 421 FX_BOOL CFX_Win32FontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { 422 char facebuf[100]; 423 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont); 424 int ret = ::GetTextFaceA(m_hDC, 100, facebuf); 425 ::SelectObject(m_hDC, hOldFont); 426 if (ret == 0) { 427 return FALSE; 428 } 429 name = facebuf; 430 return TRUE; 431 } 432 FX_BOOL CFX_Win32FontInfo::GetFontCharset(void* hFont, int& charset) { 433 TEXTMETRIC tm; 434 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont); 435 ::GetTextMetrics(m_hDC, &tm); 436 ::SelectObject(m_hDC, hOldFont); 437 charset = tm.tmCharSet; 438 return TRUE; 439 } 440 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) { 441 HDC hdc = ::GetDC(NULL); 442 if (hdc) { 443 ::ReleaseDC(NULL, hdc); 444 return new CFX_Win32FontInfo; 445 } 446 // If GDI is disabled then GetDC for the desktop will fail. Select the 447 // fallback font information class if GDI is disabled. 448 CFX_Win32FallbackFontInfo* pInfoFallback = new CFX_Win32FallbackFontInfo; 449 // Construct the font path manually, SHGetKnownFolderPath won't work under 450 // a restrictive sandbox. 451 CHAR windows_path[MAX_PATH] = {}; 452 DWORD path_len = ::GetWindowsDirectoryA(windows_path, MAX_PATH); 453 if (path_len > 0 && path_len < MAX_PATH) { 454 CFX_ByteString fonts_path(windows_path); 455 fonts_path += "\\Fonts"; 456 pInfoFallback->AddPath(fonts_path); 457 } 458 return pInfoFallback; 459 } 460 void CFX_GEModule::InitPlatform() { 461 CWin32Platform* pPlatformData = new CWin32Platform; 462 OSVERSIONINFO ver; 463 ver.dwOSVersionInfoSize = sizeof(ver); 464 GetVersionEx(&ver); 465 pPlatformData->m_bHalfTone = ver.dwMajorVersion >= 5; 466 pPlatformData->m_GdiplusExt.Load(); 467 m_pPlatformData = pPlatformData; 468 m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault(nullptr)); 469 } 470 void CFX_GEModule::DestroyPlatform() { 471 delete (CWin32Platform*)m_pPlatformData; 472 m_pPlatformData = NULL; 473 } 474 CGdiDeviceDriver::CGdiDeviceDriver(HDC hDC, int device_class) { 475 m_hDC = hDC; 476 m_DeviceClass = device_class; 477 CWin32Platform* pPlatform = 478 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 479 SetStretchBltMode(hDC, pPlatform->m_bHalfTone ? HALFTONE : COLORONCOLOR); 480 if (GetObjectType(m_hDC) == OBJ_MEMDC) { 481 HBITMAP hBitmap = CreateBitmap(1, 1, 1, 1, NULL); 482 hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap); 483 BITMAP bitmap; 484 GetObject(hBitmap, sizeof bitmap, &bitmap); 485 m_nBitsPerPixel = bitmap.bmBitsPixel; 486 m_Width = bitmap.bmWidth; 487 m_Height = abs(bitmap.bmHeight); 488 hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap); 489 DeleteObject(hBitmap); 490 } else { 491 m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL); 492 m_Width = ::GetDeviceCaps(m_hDC, HORZRES); 493 m_Height = ::GetDeviceCaps(m_hDC, VERTRES); 494 } 495 if (m_DeviceClass != FXDC_DISPLAY) { 496 m_RenderCaps = FXRC_BIT_MASK; 497 } else { 498 m_RenderCaps = FXRC_GET_BITS | FXRC_BIT_MASK; 499 } 500 } 501 int CGdiDeviceDriver::GetDeviceCaps(int caps_id) { 502 switch (caps_id) { 503 case FXDC_DEVICE_CLASS: 504 return m_DeviceClass; 505 case FXDC_PIXEL_WIDTH: 506 return m_Width; 507 case FXDC_PIXEL_HEIGHT: 508 return m_Height; 509 case FXDC_BITS_PIXEL: 510 return m_nBitsPerPixel; 511 case FXDC_RENDER_CAPS: 512 return m_RenderCaps; 513 } 514 return 0; 515 } 516 void* CGdiDeviceDriver::GetClipRgn() { 517 HRGN hClipRgn = CreateRectRgn(0, 0, 1, 1); 518 if (::GetClipRgn(m_hDC, hClipRgn) == 0) { 519 DeleteObject(hClipRgn); 520 hClipRgn = NULL; 521 } 522 return (void*)hClipRgn; 523 } 524 FX_BOOL CGdiDeviceDriver::GDI_SetDIBits(const CFX_DIBitmap* pBitmap1, 525 const FX_RECT* pSrcRect, 526 int left, 527 int top, 528 void* pIccTransform) { 529 if (m_DeviceClass == FXDC_PRINTER) { 530 CFX_DIBitmap* pBitmap = pBitmap1->FlipImage(FALSE, TRUE); 531 if (!pBitmap) { 532 return FALSE; 533 } 534 if ((pBitmap->IsCmykImage() || pIccTransform) && 535 !pBitmap->ConvertFormat(FXDIB_Rgb, pIccTransform)) { 536 return FALSE; 537 } 538 int width = pSrcRect->Width(), height = pSrcRect->Height(); 539 LPBYTE pBuffer = pBitmap->GetBuffer(); 540 CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); 541 ((BITMAPINFOHEADER*)info.c_str())->biHeight *= -1; 542 FX_RECT dst_rect(0, 0, width, height); 543 dst_rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); 544 int dst_width = dst_rect.Width(); 545 int dst_height = dst_rect.Height(); 546 ::StretchDIBits(m_hDC, left, top, dst_width, dst_height, 0, 0, dst_width, 547 dst_height, pBuffer, (BITMAPINFO*)info.c_str(), 548 DIB_RGB_COLORS, SRCCOPY); 549 delete pBitmap; 550 } else { 551 CFX_DIBitmap* pBitmap = (CFX_DIBitmap*)pBitmap1; 552 if ((pBitmap->IsCmykImage() || pIccTransform) && 553 (pBitmap = pBitmap->CloneConvert(FXDIB_Rgb, NULL, pIccTransform)) == 554 NULL) { 555 return FALSE; 556 } 557 int width = pSrcRect->Width(), height = pSrcRect->Height(); 558 LPBYTE pBuffer = pBitmap->GetBuffer(); 559 CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); 560 ::SetDIBitsToDevice(m_hDC, left, top, width, height, pSrcRect->left, 561 pBitmap->GetHeight() - pSrcRect->bottom, 0, 562 pBitmap->GetHeight(), pBuffer, 563 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); 564 if (pBitmap != pBitmap1) { 565 delete pBitmap; 566 } 567 } 568 return TRUE; 569 } 570 FX_BOOL CGdiDeviceDriver::GDI_StretchDIBits(const CFX_DIBitmap* pBitmap1, 571 int dest_left, 572 int dest_top, 573 int dest_width, 574 int dest_height, 575 FX_DWORD flags, 576 void* pIccTransform) { 577 CFX_DIBitmap* pBitmap = (CFX_DIBitmap*)pBitmap1; 578 if (!pBitmap || dest_width == 0 || dest_height == 0) { 579 return FALSE; 580 } 581 if ((pBitmap->IsCmykImage() || pIccTransform) && 582 !pBitmap->ConvertFormat(FXDIB_Rgb, pIccTransform)) { 583 return FALSE; 584 } 585 CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap); 586 if ((int64_t)abs(dest_width) * abs(dest_height) < 587 (int64_t)pBitmap1->GetWidth() * pBitmap1->GetHeight() * 4 || 588 (flags & FXDIB_INTERPOL) || (flags & FXDIB_BICUBIC_INTERPOL)) { 589 SetStretchBltMode(m_hDC, HALFTONE); 590 } else { 591 SetStretchBltMode(m_hDC, COLORONCOLOR); 592 } 593 CFX_DIBitmap* pToStrechBitmap = pBitmap; 594 bool del = false; 595 if (m_DeviceClass == FXDC_PRINTER && 596 ((int64_t)pBitmap->GetWidth() * pBitmap->GetHeight() > 597 (int64_t)abs(dest_width) * abs(dest_height))) { 598 pToStrechBitmap = pBitmap->StretchTo(dest_width, dest_height); 599 del = true; 600 } 601 CFX_ByteString toStrechBitmapInfo = 602 CFX_WindowsDIB::GetBitmapInfo(pToStrechBitmap); 603 ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0, 604 pToStrechBitmap->GetWidth(), pToStrechBitmap->GetHeight(), 605 pToStrechBitmap->GetBuffer(), 606 (BITMAPINFO*)toStrechBitmapInfo.c_str(), DIB_RGB_COLORS, 607 SRCCOPY); 608 if (del) { 609 delete pToStrechBitmap; 610 } 611 return TRUE; 612 } 613 FX_BOOL CGdiDeviceDriver::GDI_StretchBitMask(const CFX_DIBitmap* pBitmap1, 614 int dest_left, 615 int dest_top, 616 int dest_width, 617 int dest_height, 618 FX_DWORD bitmap_color, 619 FX_DWORD flags, 620 int alpha_flag, 621 void* pIccTransform) { 622 CFX_DIBitmap* pBitmap = (CFX_DIBitmap*)pBitmap1; 623 if (!pBitmap || dest_width == 0 || dest_height == 0) { 624 return FALSE; 625 } 626 _Color2Argb(bitmap_color, bitmap_color, alpha_flag | (1 << 24), 627 pIccTransform); 628 int width = pBitmap->GetWidth(), height = pBitmap->GetHeight(); 629 struct { 630 BITMAPINFOHEADER bmiHeader; 631 FX_DWORD bmiColors[2]; 632 } bmi; 633 FXSYS_memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER)); 634 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 635 bmi.bmiHeader.biBitCount = 1; 636 bmi.bmiHeader.biCompression = BI_RGB; 637 bmi.bmiHeader.biHeight = -height; 638 bmi.bmiHeader.biPlanes = 1; 639 bmi.bmiHeader.biWidth = width; 640 if (m_nBitsPerPixel != 1) { 641 SetStretchBltMode(m_hDC, HALFTONE); 642 } 643 bmi.bmiColors[0] = 0xffffff; 644 bmi.bmiColors[1] = 0; 645 646 HBRUSH hPattern = CreateSolidBrush(bitmap_color & 0xffffff); 647 HBRUSH hOld = (HBRUSH)SelectObject(m_hDC, hPattern); 648 649 // In PDF, when image mask is 1, use device bitmap; when mask is 0, use brush 650 // bitmap. 651 // A complete list of the boolen operations is as follows: 652 653 /* P(bitmap_color) S(ImageMask) D(DeviceBitmap) Result 654 * 0 0 0 0 655 * 0 0 1 0 656 * 0 1 0 0 657 * 0 1 1 1 658 * 1 0 0 1 659 * 1 0 1 1 660 * 1 1 0 0 661 * 1 1 1 1 662 */ 663 // The boolen codes is B8. Based on 664 // http://msdn.microsoft.com/en-us/library/aa932106.aspx, the ROP3 code is 665 // 0xB8074A 666 667 ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0, 668 width, height, pBitmap->GetBuffer(), (BITMAPINFO*)&bmi, 669 DIB_RGB_COLORS, 0xB8074A); 670 671 SelectObject(m_hDC, hOld); 672 DeleteObject(hPattern); 673 674 return TRUE; 675 } 676 FX_BOOL CGdiDeviceDriver::GetClipBox(FX_RECT* pRect) { 677 return ::GetClipBox(m_hDC, (RECT*)pRect); 678 } 679 FX_BOOL CGdiDeviceDriver::SetClipRgn(void* hRgn) { 680 ::SelectClipRgn(m_hDC, (HRGN)hRgn); 681 return TRUE; 682 } 683 static HPEN _CreatePen(const CFX_GraphStateData* pGraphState, 684 const CFX_Matrix* pMatrix, 685 FX_DWORD argb) { 686 FX_FLOAT width; 687 FX_FLOAT scale = 1.f; 688 if (pMatrix) 689 scale = FXSYS_fabs(pMatrix->a) > FXSYS_fabs(pMatrix->b) 690 ? FXSYS_fabs(pMatrix->a) 691 : FXSYS_fabs(pMatrix->b); 692 if (pGraphState) { 693 width = scale * pGraphState->m_LineWidth; 694 } else { 695 width = 1.0f; 696 } 697 FX_DWORD PenStyle = PS_GEOMETRIC; 698 if (width < 1) { 699 width = 1; 700 } 701 if (pGraphState->m_DashCount) { 702 PenStyle |= PS_USERSTYLE; 703 } else { 704 PenStyle |= PS_SOLID; 705 } 706 switch (pGraphState->m_LineCap) { 707 case 0: 708 PenStyle |= PS_ENDCAP_FLAT; 709 break; 710 case 1: 711 PenStyle |= PS_ENDCAP_ROUND; 712 break; 713 case 2: 714 PenStyle |= PS_ENDCAP_SQUARE; 715 break; 716 } 717 switch (pGraphState->m_LineJoin) { 718 case 0: 719 PenStyle |= PS_JOIN_MITER; 720 break; 721 case 1: 722 PenStyle |= PS_JOIN_ROUND; 723 break; 724 case 2: 725 PenStyle |= PS_JOIN_BEVEL; 726 break; 727 } 728 int a; 729 FX_COLORREF rgb; 730 ArgbDecode(argb, a, rgb); 731 LOGBRUSH lb; 732 lb.lbColor = rgb; 733 lb.lbStyle = BS_SOLID; 734 lb.lbHatch = 0; 735 FX_DWORD* pDash = NULL; 736 if (pGraphState->m_DashCount) { 737 pDash = FX_Alloc(FX_DWORD, pGraphState->m_DashCount); 738 for (int i = 0; i < pGraphState->m_DashCount; i++) { 739 pDash[i] = FXSYS_round( 740 pMatrix ? pMatrix->TransformDistance(pGraphState->m_DashArray[i]) 741 : pGraphState->m_DashArray[i]); 742 if (pDash[i] < 1) { 743 pDash[i] = 1; 744 } 745 } 746 } 747 HPEN hPen = ExtCreatePen(PenStyle, (DWORD)FXSYS_ceil(width), &lb, 748 pGraphState->m_DashCount, (const DWORD*)pDash); 749 FX_Free(pDash); 750 return hPen; 751 } 752 static HBRUSH _CreateBrush(FX_DWORD argb) { 753 int a; 754 FX_COLORREF rgb; 755 ArgbDecode(argb, a, rgb); 756 return CreateSolidBrush(rgb); 757 } 758 static void _SetPathToDC(HDC hDC, 759 const CFX_PathData* pPathData, 760 const CFX_Matrix* pMatrix) { 761 BeginPath(hDC); 762 int nPoints = pPathData->GetPointCount(); 763 FX_PATHPOINT* pPoints = pPathData->GetPoints(); 764 for (int i = 0; i < nPoints; i++) { 765 FX_FLOAT posx = pPoints[i].m_PointX, posy = pPoints[i].m_PointY; 766 if (pMatrix) { 767 pMatrix->Transform(posx, posy); 768 } 769 int screen_x = FXSYS_round(posx), screen_y = FXSYS_round(posy); 770 int point_type = pPoints[i].m_Flag & FXPT_TYPE; 771 if (point_type == PT_MOVETO) { 772 MoveToEx(hDC, screen_x, screen_y, NULL); 773 } else if (point_type == PT_LINETO) { 774 if (pPoints[i].m_PointY == pPoints[i - 1].m_PointY && 775 pPoints[i].m_PointX == pPoints[i - 1].m_PointX) { 776 screen_x++; 777 } 778 LineTo(hDC, screen_x, screen_y); 779 } else if (point_type == PT_BEZIERTO) { 780 POINT lppt[3]; 781 lppt[0].x = screen_x; 782 lppt[0].y = screen_y; 783 posx = pPoints[i + 1].m_PointX; 784 posy = pPoints[i + 1].m_PointY; 785 if (pMatrix) { 786 pMatrix->Transform(posx, posy); 787 } 788 lppt[1].x = FXSYS_round(posx); 789 lppt[1].y = FXSYS_round(posy); 790 posx = pPoints[i + 2].m_PointX; 791 posy = pPoints[i + 2].m_PointY; 792 if (pMatrix) { 793 pMatrix->Transform(posx, posy); 794 } 795 lppt[2].x = FXSYS_round(posx); 796 lppt[2].y = FXSYS_round(posy); 797 PolyBezierTo(hDC, lppt, 3); 798 i += 2; 799 } 800 if (pPoints[i].m_Flag & PT_CLOSEFIGURE) { 801 CloseFigure(hDC); 802 } 803 } 804 EndPath(hDC); 805 } 806 void CGdiDeviceDriver::DrawLine(FX_FLOAT x1, 807 FX_FLOAT y1, 808 FX_FLOAT x2, 809 FX_FLOAT y2) { 810 int flag1 = (x1 < 0) | ((x1 > m_Width) << 1) | ((y1 < 0) << 2) | 811 ((y1 > m_Height) << 3); 812 int flag2 = (x2 < 0) | ((x2 > m_Width) << 1) | ((y2 < 0) << 2) | 813 ((y2 > m_Height) << 3); 814 if (flag1 & flag2) { 815 return; 816 } 817 if (flag1 || flag2) { 818 agg::rect_base<FX_FLOAT> rect(0.0f, 0.0f, (FX_FLOAT)(m_Width), 819 (FX_FLOAT)(m_Height)); 820 FX_FLOAT x[2], y[2]; 821 int np = agg::clip_liang_barsky<FX_FLOAT>(x1, y1, x2, y2, rect, x, y); 822 if (np == 0) { 823 return; 824 } 825 if (np == 1) { 826 x2 = x[0]; 827 y2 = y[0]; 828 } else { 829 x1 = x[0]; 830 y1 = y[0]; 831 x2 = x[np - 1]; 832 y2 = y[np - 1]; 833 } 834 } 835 MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), NULL); 836 LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2)); 837 } 838 static FX_BOOL _MatrixNoScaled(const CFX_Matrix* pMatrix) { 839 return pMatrix->GetA() == 1.0f && pMatrix->GetB() == 0 && 840 pMatrix->GetC() == 0 && pMatrix->GetD() == 1.0f; 841 } 842 FX_BOOL CGdiDeviceDriver::DrawPath(const CFX_PathData* pPathData, 843 const CFX_Matrix* pMatrix, 844 const CFX_GraphStateData* pGraphState, 845 FX_DWORD fill_color, 846 FX_DWORD stroke_color, 847 int fill_mode, 848 int alpha_flag, 849 void* pIccTransform, 850 int blend_type) { 851 if (blend_type != FXDIB_BLEND_NORMAL) { 852 return FALSE; 853 } 854 _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform); 855 _Color2Argb(stroke_color, stroke_color, alpha_flag, pIccTransform); 856 CWin32Platform* pPlatform = 857 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 858 if (!(pGraphState || stroke_color == 0) && 859 !pPlatform->m_GdiplusExt.IsAvailable()) { 860 CFX_FloatRect bbox_f = pPathData->GetBoundingBox(); 861 if (pMatrix) { 862 bbox_f.Transform(pMatrix); 863 } 864 FX_RECT bbox = bbox_f.GetInnerRect(); 865 if (bbox.Width() <= 0) { 866 return DrawCosmeticLine((FX_FLOAT)(bbox.left), (FX_FLOAT)(bbox.top), 867 (FX_FLOAT)(bbox.left), 868 (FX_FLOAT)(bbox.bottom + 1), fill_color, 869 alpha_flag, pIccTransform, FXDIB_BLEND_NORMAL); 870 } else if (bbox.Height() <= 0) { 871 return DrawCosmeticLine((FX_FLOAT)(bbox.left), (FX_FLOAT)(bbox.top), 872 (FX_FLOAT)(bbox.right + 1), (FX_FLOAT)(bbox.top), 873 fill_color, alpha_flag, pIccTransform, 874 FXDIB_BLEND_NORMAL); 875 } 876 } 877 int fill_alpha = FXARGB_A(fill_color); 878 int stroke_alpha = FXARGB_A(stroke_color); 879 FX_BOOL bDrawAlpha = (fill_alpha > 0 && fill_alpha < 255) || 880 (stroke_alpha > 0 && stroke_alpha < 255 && pGraphState); 881 if (!pPlatform->m_GdiplusExt.IsAvailable() && bDrawAlpha) { 882 return FALSE; 883 } 884 if (pPlatform->m_GdiplusExt.IsAvailable()) { 885 if (bDrawAlpha || 886 ((m_DeviceClass != FXDC_PRINTER && !(fill_mode & FXFILL_FULLCOVER)) || 887 (pGraphState && pGraphState->m_DashCount))) { 888 if (!((NULL == pMatrix || _MatrixNoScaled(pMatrix)) && pGraphState && 889 pGraphState->m_LineWidth == 1.f && 890 (pPathData->GetPointCount() == 5 || 891 pPathData->GetPointCount() == 4) && 892 pPathData->IsRect())) { 893 if (pPlatform->m_GdiplusExt.DrawPath(m_hDC, pPathData, pMatrix, 894 pGraphState, fill_color, 895 stroke_color, fill_mode)) { 896 return TRUE; 897 } 898 } 899 } 900 } 901 int old_fill_mode = fill_mode; 902 fill_mode &= 3; 903 HPEN hPen = NULL; 904 HBRUSH hBrush = NULL; 905 if (pGraphState && stroke_alpha) { 906 SetMiterLimit(m_hDC, pGraphState->m_MiterLimit, NULL); 907 hPen = _CreatePen(pGraphState, pMatrix, stroke_color); 908 hPen = (HPEN)SelectObject(m_hDC, hPen); 909 } 910 if (fill_mode && fill_alpha) { 911 SetPolyFillMode(m_hDC, fill_mode); 912 hBrush = _CreateBrush(fill_color); 913 hBrush = (HBRUSH)SelectObject(m_hDC, hBrush); 914 } 915 if (pPathData->GetPointCount() == 2 && pGraphState && 916 pGraphState->m_DashCount) { 917 FX_FLOAT x1 = pPathData->GetPointX(0), y1 = pPathData->GetPointY(0); 918 if (pMatrix) { 919 pMatrix->Transform(x1, y1); 920 } 921 FX_FLOAT x2 = pPathData->GetPointX(1), y2 = pPathData->GetPointY(1); 922 if (pMatrix) { 923 pMatrix->Transform(x2, y2); 924 } 925 DrawLine(x1, y1, x2, y2); 926 } else { 927 _SetPathToDC(m_hDC, pPathData, pMatrix); 928 if (pGraphState && stroke_alpha) { 929 if (fill_mode && fill_alpha) { 930 if (old_fill_mode & FX_FILL_TEXT_MODE) { 931 StrokeAndFillPath(m_hDC); 932 } else { 933 FillPath(m_hDC); 934 _SetPathToDC(m_hDC, pPathData, pMatrix); 935 StrokePath(m_hDC); 936 } 937 } else { 938 StrokePath(m_hDC); 939 } 940 } else if (fill_mode && fill_alpha) { 941 FillPath(m_hDC); 942 } 943 } 944 if (hPen) { 945 hPen = (HPEN)SelectObject(m_hDC, hPen); 946 DeleteObject(hPen); 947 } 948 if (hBrush) { 949 hBrush = (HBRUSH)SelectObject(m_hDC, hBrush); 950 DeleteObject(hBrush); 951 } 952 return TRUE; 953 } 954 FX_BOOL CGdiDeviceDriver::FillRect(const FX_RECT* pRect, 955 FX_DWORD fill_color, 956 int alpha_flag, 957 void* pIccTransform, 958 int blend_type) { 959 if (blend_type != FXDIB_BLEND_NORMAL) { 960 return FALSE; 961 } 962 _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform); 963 int alpha; 964 FX_COLORREF rgb; 965 ArgbDecode(fill_color, alpha, rgb); 966 if (alpha == 0) { 967 return TRUE; 968 } 969 if (alpha < 255) { 970 return FALSE; 971 } 972 HBRUSH hBrush = CreateSolidBrush(rgb); 973 ::FillRect(m_hDC, (RECT*)pRect, hBrush); 974 DeleteObject(hBrush); 975 return TRUE; 976 } 977 FX_BOOL CGdiDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData, 978 const CFX_Matrix* pMatrix, 979 int fill_mode) { 980 if (pPathData->GetPointCount() == 5) { 981 CFX_FloatRect rectf; 982 if (pPathData->IsRect(pMatrix, &rectf)) { 983 FX_RECT rect = rectf.GetOutterRect(); 984 IntersectClipRect(m_hDC, rect.left, rect.top, rect.right, rect.bottom); 985 return TRUE; 986 } 987 } 988 _SetPathToDC(m_hDC, pPathData, pMatrix); 989 SetPolyFillMode(m_hDC, fill_mode & 3); 990 SelectClipPath(m_hDC, RGN_AND); 991 return TRUE; 992 } 993 FX_BOOL CGdiDeviceDriver::SetClip_PathStroke( 994 const CFX_PathData* pPathData, 995 const CFX_Matrix* pMatrix, 996 const CFX_GraphStateData* pGraphState) { 997 HPEN hPen = _CreatePen(pGraphState, pMatrix, 0xff000000); 998 hPen = (HPEN)SelectObject(m_hDC, hPen); 999 _SetPathToDC(m_hDC, pPathData, pMatrix); 1000 WidenPath(m_hDC); 1001 SetPolyFillMode(m_hDC, WINDING); 1002 FX_BOOL ret = SelectClipPath(m_hDC, RGN_AND); 1003 hPen = (HPEN)SelectObject(m_hDC, hPen); 1004 DeleteObject(hPen); 1005 return ret; 1006 } 1007 FX_BOOL CGdiDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, 1008 FX_FLOAT y1, 1009 FX_FLOAT x2, 1010 FX_FLOAT y2, 1011 FX_DWORD color, 1012 int alpha_flag, 1013 void* pIccTransform, 1014 int blend_type) { 1015 if (blend_type != FXDIB_BLEND_NORMAL) { 1016 return FALSE; 1017 } 1018 _Color2Argb(color, color, alpha_flag | (1 << 24), pIccTransform); 1019 int a; 1020 FX_COLORREF rgb; 1021 ArgbDecode(color, a, rgb); 1022 if (a == 0) { 1023 return TRUE; 1024 } 1025 HPEN hPen = CreatePen(PS_SOLID, 1, rgb); 1026 hPen = (HPEN)SelectObject(m_hDC, hPen); 1027 MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), NULL); 1028 LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2)); 1029 hPen = (HPEN)SelectObject(m_hDC, hPen); 1030 DeleteObject(hPen); 1031 return TRUE; 1032 } 1033 FX_BOOL CGdiDeviceDriver::DeleteDeviceRgn(void* pRgn) { 1034 DeleteObject((HGDIOBJ)pRgn); 1035 return TRUE; 1036 } 1037 CGdiDisplayDriver::CGdiDisplayDriver(HDC hDC) 1038 : CGdiDeviceDriver(hDC, FXDC_DISPLAY) { 1039 CWin32Platform* pPlatform = 1040 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 1041 if (pPlatform->m_GdiplusExt.IsAvailable()) { 1042 m_RenderCaps |= FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE; 1043 } 1044 } 1045 FX_BOOL CGdiDisplayDriver::GetDIBits(CFX_DIBitmap* pBitmap, 1046 int left, 1047 int top, 1048 void* pIccTransform, 1049 FX_BOOL bDEdge) { 1050 FX_BOOL ret = FALSE; 1051 int width = pBitmap->GetWidth(); 1052 int height = pBitmap->GetHeight(); 1053 HBITMAP hbmp = CreateCompatibleBitmap(m_hDC, width, height); 1054 HDC hDCMemory = CreateCompatibleDC(m_hDC); 1055 HBITMAP holdbmp = (HBITMAP)SelectObject(hDCMemory, hbmp); 1056 BitBlt(hDCMemory, 0, 0, width, height, m_hDC, left, top, SRCCOPY); 1057 SelectObject(hDCMemory, holdbmp); 1058 BITMAPINFO bmi; 1059 FXSYS_memset(&bmi, 0, sizeof bmi); 1060 bmi.bmiHeader.biSize = sizeof bmi.bmiHeader; 1061 bmi.bmiHeader.biBitCount = pBitmap->GetBPP(); 1062 bmi.bmiHeader.biHeight = -height; 1063 bmi.bmiHeader.biPlanes = 1; 1064 bmi.bmiHeader.biWidth = width; 1065 if (!CFX_GEModule::Get()->GetCodecModule() || 1066 !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { 1067 pIccTransform = NULL; 1068 } 1069 if (pBitmap->GetBPP() > 8 && !pBitmap->IsCmykImage() && !pIccTransform) { 1070 ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer(), &bmi, 1071 DIB_RGB_COLORS) == height; 1072 } else { 1073 CFX_DIBitmap bitmap; 1074 if (bitmap.Create(width, height, FXDIB_Rgb)) { 1075 bmi.bmiHeader.biBitCount = 24; 1076 ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap.GetBuffer(), &bmi, 1077 DIB_RGB_COLORS); 1078 ret = pBitmap->TransferBitmap(0, 0, width, height, &bitmap, 0, 0, 1079 pIccTransform); 1080 } else { 1081 ret = FALSE; 1082 } 1083 } 1084 if (pBitmap->HasAlpha() && ret) { 1085 pBitmap->LoadChannel(FXDIB_Alpha, 0xff); 1086 } 1087 DeleteObject(hbmp); 1088 DeleteObject(hDCMemory); 1089 return ret; 1090 } 1091 FX_BOOL CGdiDisplayDriver::SetDIBits(const CFX_DIBSource* pSource, 1092 FX_DWORD color, 1093 const FX_RECT* pSrcRect, 1094 int left, 1095 int top, 1096 int blend_type, 1097 int alpha_flag, 1098 void* pIccTransform) { 1099 ASSERT(blend_type == FXDIB_BLEND_NORMAL); 1100 if (pSource->IsAlphaMask()) { 1101 int width = pSource->GetWidth(), height = pSource->GetHeight(); 1102 int alpha = FXGETFLAG_COLORTYPE(alpha_flag) 1103 ? FXGETFLAG_ALPHA_FILL(alpha_flag) 1104 : FXARGB_A(color); 1105 FX_BOOL bGDI = pSource->GetBPP() == 1 && alpha == 255; 1106 if (!bGDI) { 1107 CFX_DIBitmap background; 1108 if (!background.Create(width, height, FXDIB_Rgb32) || 1109 !GetDIBits(&background, left, top, NULL) || 1110 !background.CompositeMask(0, 0, width, height, pSource, color, 0, 0, 1111 FXDIB_BLEND_NORMAL, NULL, FALSE, alpha_flag, 1112 pIccTransform)) { 1113 return FALSE; 1114 } 1115 FX_RECT src_rect(0, 0, width, height); 1116 return SetDIBits(&background, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL, 1117 0, NULL); 1118 } 1119 FX_RECT clip_rect(left, top, left + pSrcRect->Width(), 1120 top + pSrcRect->Height()); 1121 return StretchDIBits(pSource, color, left - pSrcRect->left, 1122 top - pSrcRect->top, width, height, &clip_rect, 0, 1123 alpha_flag, pIccTransform, FXDIB_BLEND_NORMAL); 1124 } 1125 int width = pSrcRect->Width(), height = pSrcRect->Height(); 1126 if (pSource->HasAlpha()) { 1127 CFX_DIBitmap bitmap; 1128 if (!bitmap.Create(width, height, FXDIB_Rgb) || 1129 !GetDIBits(&bitmap, left, top, NULL) || 1130 !bitmap.CompositeBitmap(0, 0, width, height, pSource, pSrcRect->left, 1131 pSrcRect->top, FXDIB_BLEND_NORMAL, NULL, FALSE, 1132 pIccTransform)) { 1133 return FALSE; 1134 } 1135 FX_RECT src_rect(0, 0, width, height); 1136 return SetDIBits(&bitmap, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL, 0, 1137 NULL); 1138 } 1139 CFX_DIBExtractor temp(pSource); 1140 CFX_DIBitmap* pBitmap = temp; 1141 if (pBitmap) { 1142 return GDI_SetDIBits(pBitmap, pSrcRect, left, top, pIccTransform); 1143 } 1144 return FALSE; 1145 } 1146 FX_BOOL CGdiDisplayDriver::UseFoxitStretchEngine(const CFX_DIBSource* pSource, 1147 FX_DWORD color, 1148 int dest_left, 1149 int dest_top, 1150 int dest_width, 1151 int dest_height, 1152 const FX_RECT* pClipRect, 1153 int render_flags, 1154 int alpha_flag, 1155 void* pIccTransform, 1156 int blend_type) { 1157 FX_RECT bitmap_clip = *pClipRect; 1158 if (dest_width < 0) { 1159 dest_left += dest_width; 1160 } 1161 if (dest_height < 0) { 1162 dest_top += dest_height; 1163 } 1164 bitmap_clip.Offset(-dest_left, -dest_top); 1165 CFX_DIBitmap* pStretched = 1166 pSource->StretchTo(dest_width, dest_height, render_flags, &bitmap_clip); 1167 if (!pStretched) { 1168 return TRUE; 1169 } 1170 FX_RECT src_rect(0, 0, pStretched->GetWidth(), pStretched->GetHeight()); 1171 FX_BOOL ret = 1172 SetDIBits(pStretched, color, &src_rect, pClipRect->left, pClipRect->top, 1173 FXDIB_BLEND_NORMAL, alpha_flag, pIccTransform); 1174 delete pStretched; 1175 return ret; 1176 } 1177 FX_BOOL CGdiDisplayDriver::StretchDIBits(const CFX_DIBSource* pSource, 1178 FX_DWORD color, 1179 int dest_left, 1180 int dest_top, 1181 int dest_width, 1182 int dest_height, 1183 const FX_RECT* pClipRect, 1184 FX_DWORD flags, 1185 int alpha_flag, 1186 void* pIccTransform, 1187 int blend_type) { 1188 ASSERT(pSource && pClipRect); 1189 if (flags || dest_width > 10000 || dest_width < -10000 || 1190 dest_height > 10000 || dest_height < -10000) { 1191 return UseFoxitStretchEngine(pSource, color, dest_left, dest_top, 1192 dest_width, dest_height, pClipRect, flags, 1193 alpha_flag, pIccTransform, blend_type); 1194 } 1195 if (pSource->IsAlphaMask()) { 1196 FX_RECT image_rect; 1197 image_rect.left = dest_width > 0 ? dest_left : dest_left + dest_width; 1198 image_rect.right = dest_width > 0 ? dest_left + dest_width : dest_left; 1199 image_rect.top = dest_height > 0 ? dest_top : dest_top + dest_height; 1200 image_rect.bottom = dest_height > 0 ? dest_top + dest_height : dest_top; 1201 FX_RECT clip_rect = image_rect; 1202 clip_rect.Intersect(*pClipRect); 1203 clip_rect.Offset(-image_rect.left, -image_rect.top); 1204 int clip_width = clip_rect.Width(), clip_height = clip_rect.Height(); 1205 CFX_DIBitmap* pStretched = 1206 pSource->StretchTo(dest_width, dest_height, flags, &clip_rect); 1207 if (!pStretched) { 1208 return TRUE; 1209 } 1210 CFX_DIBitmap background; 1211 if (!background.Create(clip_width, clip_height, FXDIB_Rgb32) || 1212 !GetDIBits(&background, image_rect.left + clip_rect.left, 1213 image_rect.top + clip_rect.top, NULL) || 1214 !background.CompositeMask(0, 0, clip_width, clip_height, pStretched, 1215 color, 0, 0, FXDIB_BLEND_NORMAL, NULL, FALSE, 1216 alpha_flag, pIccTransform)) { 1217 delete pStretched; 1218 return FALSE; 1219 } 1220 FX_RECT src_rect(0, 0, clip_width, clip_height); 1221 FX_BOOL ret = 1222 SetDIBits(&background, 0, &src_rect, image_rect.left + clip_rect.left, 1223 image_rect.top + clip_rect.top, FXDIB_BLEND_NORMAL, 0, NULL); 1224 delete pStretched; 1225 return ret; 1226 } 1227 if (pSource->HasAlpha()) { 1228 CWin32Platform* pPlatform = 1229 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 1230 if (pPlatform->m_GdiplusExt.IsAvailable() && !pIccTransform && 1231 !pSource->IsCmykImage()) { 1232 CFX_DIBExtractor temp(pSource); 1233 CFX_DIBitmap* pBitmap = temp; 1234 if (!pBitmap) { 1235 return FALSE; 1236 } 1237 return pPlatform->m_GdiplusExt.StretchDIBits( 1238 m_hDC, pBitmap, dest_left, dest_top, dest_width, dest_height, 1239 pClipRect, flags); 1240 } 1241 return UseFoxitStretchEngine(pSource, color, dest_left, dest_top, 1242 dest_width, dest_height, pClipRect, flags, 1243 alpha_flag, pIccTransform, blend_type); 1244 } 1245 CFX_DIBExtractor temp(pSource); 1246 CFX_DIBitmap* pBitmap = temp; 1247 if (pBitmap) { 1248 return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width, 1249 dest_height, flags, pIccTransform); 1250 } 1251 return FALSE; 1252 } 1253 #define GET_PS_FEATURESETTING 4121 1254 #define FEATURESETTING_PSLEVEL 2 1255 int GetPSLevel(HDC hDC) { 1256 int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY); 1257 if (device_type != DT_RASPRINTER) { 1258 return 0; 1259 } 1260 FX_DWORD esc = GET_PS_FEATURESETTING; 1261 if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL)) { 1262 int param = FEATURESETTING_PSLEVEL; 1263 if (ExtEscape(hDC, GET_PS_FEATURESETTING, sizeof(int), (char*)¶m, 1264 sizeof(int), (char*)¶m) > 0) { 1265 return param; 1266 } 1267 } 1268 esc = POSTSCRIPT_IDENTIFY; 1269 if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL) == 0) { 1270 esc = POSTSCRIPT_DATA; 1271 if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL)) { 1272 return 2; 1273 } 1274 return 0; 1275 } 1276 esc = PSIDENT_GDICENTRIC; 1277 if (ExtEscape(hDC, POSTSCRIPT_IDENTIFY, sizeof(FX_DWORD), (char*)&esc, 0, 1278 NULL) <= 0) { 1279 return 2; 1280 } 1281 esc = GET_PS_FEATURESETTING; 1282 if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL)) { 1283 int param = FEATURESETTING_PSLEVEL; 1284 if (ExtEscape(hDC, GET_PS_FEATURESETTING, sizeof(int), (char*)¶m, 1285 sizeof(int), (char*)¶m) > 0) { 1286 return param; 1287 } 1288 } 1289 return 2; 1290 } 1291 int CFX_WindowsDevice::m_psLevel = 2; 1292 CFX_WindowsDevice::CFX_WindowsDevice(HDC hDC, 1293 FX_BOOL bCmykOutput, 1294 FX_BOOL bForcePSOutput, 1295 int psLevel) { 1296 m_bForcePSOutput = bForcePSOutput; 1297 m_psLevel = psLevel; 1298 if (bForcePSOutput) { 1299 IFX_RenderDeviceDriver* pDriver = new CPSPrinterDriver; 1300 ((CPSPrinterDriver*)pDriver)->Init(hDC, psLevel, bCmykOutput); 1301 SetDeviceDriver(pDriver); 1302 return; 1303 } 1304 SetDeviceDriver(CreateDriver(hDC, bCmykOutput)); 1305 } 1306 HDC CFX_WindowsDevice::GetDC() const { 1307 IFX_RenderDeviceDriver* pRDD = GetDeviceDriver(); 1308 if (!pRDD) { 1309 return NULL; 1310 } 1311 return (HDC)pRDD->GetPlatformSurface(); 1312 } 1313 IFX_RenderDeviceDriver* CFX_WindowsDevice::CreateDriver(HDC hDC, 1314 FX_BOOL bCmykOutput) { 1315 int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY); 1316 int obj_type = ::GetObjectType(hDC); 1317 int device_class; 1318 if (device_type == DT_RASPRINTER || device_type == DT_PLOTTER || 1319 obj_type == OBJ_ENHMETADC) { 1320 device_class = FXDC_PRINTER; 1321 } else { 1322 device_class = FXDC_DISPLAY; 1323 } 1324 if (device_class == FXDC_PRINTER) { 1325 return new CGdiPrinterDriver(hDC); 1326 } 1327 return new CGdiDisplayDriver(hDC); 1328 } 1329 CFX_WinBitmapDevice::CFX_WinBitmapDevice(int width, 1330 int height, 1331 FXDIB_Format format) { 1332 BITMAPINFOHEADER bmih; 1333 FXSYS_memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); 1334 bmih.biSize = sizeof(BITMAPINFOHEADER); 1335 bmih.biBitCount = format & 0xff; 1336 bmih.biHeight = -height; 1337 bmih.biPlanes = 1; 1338 bmih.biWidth = width; 1339 uint8_t* pBuffer; 1340 m_hBitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, 1341 (void**)&pBuffer, NULL, 0); 1342 if (!m_hBitmap) { 1343 return; 1344 } 1345 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; 1346 pBitmap->Create(width, height, format, pBuffer); 1347 SetBitmap(pBitmap); 1348 m_hDC = ::CreateCompatibleDC(NULL); 1349 m_hOldBitmap = (HBITMAP)SelectObject(m_hDC, m_hBitmap); 1350 IFX_RenderDeviceDriver* pDriver = new CGdiDisplayDriver(m_hDC); 1351 SetDeviceDriver(pDriver); 1352 } 1353 CFX_WinBitmapDevice::~CFX_WinBitmapDevice() { 1354 if (m_hDC) { 1355 SelectObject(m_hDC, m_hOldBitmap); 1356 DeleteDC(m_hDC); 1357 } 1358 if (m_hBitmap) { 1359 DeleteObject(m_hBitmap); 1360 } 1361 delete GetBitmap(); 1362 } 1363 1364 #endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_ 1365