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