Home | History | Annotate | Download | only in win32
      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