// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/include/fxge/fx_ge.h"

#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
#include <crtdbg.h>

#include "core/include/fxcodec/fx_codec.h"
#include "core/include/fxge/fx_freetype.h"
#include "core/include/fxge/fx_ge_win32.h"
#include "core/src/fxge/agg/include/fx_agg_driver.h"
#include "core/src/fxge/dib/dib_int.h"
#include "core/src/fxge/ge/fx_text_int.h"
#include "core/src/fxge/win32/dwrite_int.h"
#include "core/src/fxge/win32/win32_int.h"
#include "third_party/base/stl_util.h"

class CFX_Win32FallbackFontInfo final : public CFX_FolderFontInfo {
 public:
  void* MapFont(int weight,
                FX_BOOL bItalic,
                int charset,
                int pitch_family,
                const FX_CHAR* family,
                int& iExact) override;
};
class CFX_Win32FontInfo final : public IFX_SystemFontInfo {
 public:
  CFX_Win32FontInfo();
  ~CFX_Win32FontInfo() override;

  // IFX_SystemFontInfo
  void Release() override;
  FX_BOOL EnumFontList(CFX_FontMapper* pMapper) override;
  void* MapFont(int weight,
                FX_BOOL bItalic,
                int charset,
                int pitch_family,
                const FX_CHAR* face,
                int& iExact) override;
  void* GetFont(const FX_CHAR* face) override { return NULL; }
  FX_DWORD GetFontData(void* hFont,
                       FX_DWORD table,
                       uint8_t* buffer,
                       FX_DWORD size) override;
  FX_BOOL GetFaceName(void* hFont, CFX_ByteString& name) override;
  FX_BOOL GetFontCharset(void* hFont, int& charset) override;
  void DeleteFont(void* hFont) override;

  FX_BOOL IsOpenTypeFromDiv(const LOGFONTA* plf);
  FX_BOOL IsSupportFontFormDiv(const LOGFONTA* plf);
  void AddInstalledFont(const LOGFONTA* plf, FX_DWORD FontType);
  void GetGBPreference(CFX_ByteString& face, int weight, int picth_family);
  void GetJapanesePreference(CFX_ByteString& face,
                             int weight,
                             int picth_family);
  CFX_ByteString FindFont(const CFX_ByteString& name);
  HDC m_hDC;
  CFX_FontMapper* m_pMapper;
  CFX_ByteString m_LastFamily;
  CFX_ByteString m_KaiTi, m_FangSong;
};

CFX_Win32FontInfo::CFX_Win32FontInfo() {
  m_hDC = CreateCompatibleDC(NULL);
}
CFX_Win32FontInfo::~CFX_Win32FontInfo() {
  m_pMapper = NULL;
}
void CFX_Win32FontInfo::Release() {
  DeleteDC(m_hDC);
  delete this;
}
#define TT_MAKE_TAG(x1, x2, x3, x4)                                    \
  (((FX_DWORD)x1 << 24) | ((FX_DWORD)x2 << 16) | ((FX_DWORD)x3 << 8) | \
   (FX_DWORD)x4)
FX_BOOL CFX_Win32FontInfo::IsOpenTypeFromDiv(const LOGFONTA* plf) {
  HFONT hFont = CreateFontIndirectA(plf);
  FX_BOOL ret = FALSE;
  FX_DWORD font_size = GetFontData(hFont, 0, NULL, 0);
  if (font_size != GDI_ERROR && font_size >= sizeof(FX_DWORD)) {
    FX_DWORD lVersion = 0;
    GetFontData(hFont, 0, (uint8_t*)(&lVersion), sizeof(FX_DWORD));
    lVersion = (((FX_DWORD)(uint8_t)(lVersion)) << 24) |
               ((FX_DWORD)((uint8_t)(lVersion >> 8))) << 16 |
               ((FX_DWORD)((uint8_t)(lVersion >> 16))) << 8 |
               ((uint8_t)(lVersion >> 24));
    if (lVersion == TT_MAKE_TAG('O', 'T', 'T', 'O') || lVersion == 0x00010000 ||
        lVersion == TT_MAKE_TAG('t', 't', 'c', 'f') ||
        lVersion == TT_MAKE_TAG('t', 'r', 'u', 'e') || lVersion == 0x00020000) {
      ret = TRUE;
    }
  }
  DeleteFont(hFont);
  return ret;
}
FX_BOOL CFX_Win32FontInfo::IsSupportFontFormDiv(const LOGFONTA* plf) {
  HFONT hFont = CreateFontIndirectA(plf);
  FX_BOOL ret = FALSE;
  FX_DWORD font_size = GetFontData(hFont, 0, NULL, 0);
  if (font_size != GDI_ERROR && font_size >= sizeof(FX_DWORD)) {
    FX_DWORD lVersion = 0;
    GetFontData(hFont, 0, (uint8_t*)(&lVersion), sizeof(FX_DWORD));
    lVersion = (((FX_DWORD)(uint8_t)(lVersion)) << 24) |
               ((FX_DWORD)((uint8_t)(lVersion >> 8))) << 16 |
               ((FX_DWORD)((uint8_t)(lVersion >> 16))) << 8 |
               ((uint8_t)(lVersion >> 24));
    if (lVersion == TT_MAKE_TAG('O', 'T', 'T', 'O') || lVersion == 0x00010000 ||
        lVersion == TT_MAKE_TAG('t', 't', 'c', 'f') ||
        lVersion == TT_MAKE_TAG('t', 'r', 'u', 'e') || lVersion == 0x00020000) {
      ret = TRUE;
    } else if ((lVersion & 0xFFFF0000) == TT_MAKE_TAG(0x80, 0x01, 0x00, 0x00) ||
               (lVersion & 0xFFFF0000) == TT_MAKE_TAG('%', '!', 0, 0)) {
      ret = TRUE;
    }
  }
  DeleteFont(hFont);
  return ret;
}
void CFX_Win32FontInfo::AddInstalledFont(const LOGFONTA* plf,
                                         FX_DWORD FontType) {
  CFX_ByteString name(plf->lfFaceName);
  if (name[0] == '@') {
    return;
  }
  if (name == m_LastFamily) {
    m_pMapper->AddInstalledFont(name, plf->lfCharSet);
    return;
  }
  if (!(FontType & TRUETYPE_FONTTYPE) && !(FontType & DEVICE_FONTTYPE)) {
    return;
  }
  if (!(FontType & TRUETYPE_FONTTYPE)) {
    if (!IsSupportFontFormDiv(plf)) {
      return;
    }
  }
  m_pMapper->AddInstalledFont(name, plf->lfCharSet);
  m_LastFamily = name;
}
static int CALLBACK FontEnumProc(const LOGFONTA* plf,
                                 const TEXTMETRICA* lpntme,
                                 FX_DWORD FontType,
                                 LPARAM lParam) {
  CFX_Win32FontInfo* pFontInfo = (CFX_Win32FontInfo*)lParam;
  if (pFontInfo->m_pMapper->GetFontEnumerator()) {
    pFontInfo->m_pMapper->GetFontEnumerator()->HitFont();
  }
  pFontInfo->AddInstalledFont(plf, FontType);
  return 1;
}
FX_BOOL CFX_Win32FontInfo::EnumFontList(CFX_FontMapper* pMapper) {
  m_pMapper = pMapper;
  LOGFONTA lf;
  FXSYS_memset(&lf, 0, sizeof(LOGFONTA));
  lf.lfCharSet = DEFAULT_CHARSET;
  lf.lfFaceName[0] = 0;
  lf.lfPitchAndFamily = 0;
  EnumFontFamiliesExA(m_hDC, &lf, (FONTENUMPROCA)FontEnumProc, (uintptr_t) this,
                      0);
  if (pMapper->GetFontEnumerator()) {
    pMapper->GetFontEnumerator()->Finish();
  }
  return TRUE;
}
static const struct {
  const FX_CHAR* m_pFaceName;
  const FX_CHAR* m_pVariantName;
} VariantNames[] = {
    {"DFKai-SB", "\x19\x6A\x77\x69\xD4\x9A"},
};
static const struct {
  const FX_CHAR* m_pName;
  const FX_CHAR* m_pWinName;
  FX_BOOL m_bBold;
  FX_BOOL m_bItalic;
} Base14Substs[] = {
    {"Courier", "Courier New", FALSE, FALSE},
    {"Courier-Bold", "Courier New", TRUE, FALSE},
    {"Courier-BoldOblique", "Courier New", TRUE, TRUE},
    {"Courier-Oblique", "Courier New", FALSE, TRUE},
    {"Helvetica", "Arial", FALSE, FALSE},
    {"Helvetica-Bold", "Arial", TRUE, FALSE},
    {"Helvetica-BoldOblique", "Arial", TRUE, TRUE},
    {"Helvetica-Oblique", "Arial", FALSE, TRUE},
    {"Times-Roman", "Times New Roman", FALSE, FALSE},
    {"Times-Bold", "Times New Roman", TRUE, FALSE},
    {"Times-BoldItalic", "Times New Roman", TRUE, TRUE},
    {"Times-Italic", "Times New Roman", FALSE, TRUE},
};
CFX_ByteString CFX_Win32FontInfo::FindFont(const CFX_ByteString& name) {
  if (!m_pMapper) {
    return name;
  }
  int nFonts = pdfium::CollectionSize<int>(m_pMapper->m_InstalledTTFonts);
  for (int i = 0; i < nFonts; i++) {
    CFX_ByteString thisname = m_pMapper->m_InstalledTTFonts[i];
    if (thisname[0] == ' ') {
      if (thisname.Mid(1, name.GetLength()) == name) {
        return m_pMapper->m_InstalledTTFonts[i + 1];
      }
    } else if (thisname.Left(name.GetLength()) == name) {
      return m_pMapper->m_InstalledTTFonts[i];
    }
  }
  return CFX_ByteString();
}
void* CFX_Win32FallbackFontInfo::MapFont(int weight,
                                         FX_BOOL bItalic,
                                         int charset,
                                         int pitch_family,
                                         const FX_CHAR* cstr_face,
                                         int& iExact) {
  void* font = GetSubstFont(cstr_face);
  if (font) {
    iExact = 1;
    return font;
  }
  FX_BOOL bCJK = TRUE;
  switch (charset) {
    case FXFONT_SHIFTJIS_CHARSET:
    case FXFONT_GB2312_CHARSET:
    case FXFONT_CHINESEBIG5_CHARSET:
    case FXFONT_HANGEUL_CHARSET:
    default:
      bCJK = FALSE;
      break;
  }
  return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
}
struct _FontNameMap {
  const FX_CHAR* m_pSubFontName;
  const FX_CHAR* m_pSrcFontName;
};
const _FontNameMap g_JpFontNameMap[] = {
    {"MS Mincho", "Heiseimin-W3"},
    {"MS Gothic", "Jun101-Light"},
};
extern "C" {
static int compareString(const void* key, const void* element) {
  return FXSYS_stricmp((const FX_CHAR*)key,
                       ((_FontNameMap*)element)->m_pSrcFontName);
}
}
FX_BOOL _GetSubFontName(CFX_ByteString& name) {
  int size = sizeof g_JpFontNameMap;
  void* pFontnameMap = (void*)g_JpFontNameMap;
  _FontNameMap* found = (_FontNameMap*)FXSYS_bsearch(
      name.c_str(), pFontnameMap, size / sizeof(_FontNameMap),
      sizeof(_FontNameMap), compareString);
  if (!found) {
    return FALSE;
  }
  name = found->m_pSubFontName;
  return TRUE;
}
void CFX_Win32FontInfo::GetGBPreference(CFX_ByteString& face,
                                        int weight,
                                        int picth_family) {
  if (face.Find("KaiTi") >= 0 || face.Find("\xbf\xac") >= 0) {
    if (m_KaiTi.IsEmpty()) {
      m_KaiTi = FindFont("KaiTi");
      if (m_KaiTi.IsEmpty()) {
        m_KaiTi = "SimSun";
      }
    }
    face = m_KaiTi;
  } else if (face.Find("FangSong") >= 0 || face.Find("\xb7\xc2\xcb\xce") >= 0) {
    if (m_FangSong.IsEmpty()) {
      m_FangSong = FindFont("FangSong");
      if (m_FangSong.IsEmpty()) {
        m_FangSong = "SimSun";
      }
    }
    face = m_FangSong;
  } else if (face.Find("SimSun") >= 0 || face.Find("\xcb\xce") >= 0) {
    face = "SimSun";
  } else if (face.Find("SimHei") >= 0 || face.Find("\xba\xda") >= 0) {
    face = "SimHei";
  } else if (!(picth_family & FF_ROMAN) && weight > 550) {
    face = "SimHei";
  } else {
    face = "SimSun";
  }
}
void CFX_Win32FontInfo::GetJapanesePreference(CFX_ByteString& face,
                                              int weight,
                                              int picth_family) {
  if (face.Find("Gothic") >= 0 ||
      face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
    if (face.Find("PGothic") >= 0 ||
        face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
      face = "MS PGothic";
    } else if (face.Find("UI Gothic") >= 0) {
      face = "MS UI Gothic";
    } else {
      if (face.Find("HGSGothicM") >= 0 || face.Find("HGMaruGothicMPRO") >= 0) {
        face = "MS PGothic";
      } else {
        face = "MS Gothic";
      }
    }
    return;
  }
  if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) {
    if (face.Find("PMincho") >= 0 ||
        face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) {
      face = "MS PMincho";
    } else {
      face = "MS Mincho";
    }
    return;
  }
  if (_GetSubFontName(face)) {
    return;
  }
  if (!(picth_family & FF_ROMAN) && weight > 400) {
    face = "MS PGothic";
  } else {
    face = "MS PMincho";
  }
}
void* CFX_Win32FontInfo::MapFont(int weight,
                                 FX_BOOL bItalic,
                                 int charset,
                                 int pitch_family,
                                 const FX_CHAR* cstr_face,
                                 int& iExact) {
  CFX_ByteString face = cstr_face;
  int iBaseFont;
  for (iBaseFont = 0; iBaseFont < 12; iBaseFont++)
    if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) {
      face = Base14Substs[iBaseFont].m_pWinName;
      weight = Base14Substs[iBaseFont].m_bBold ? FW_BOLD : FW_NORMAL;
      bItalic = Base14Substs[iBaseFont].m_bItalic;
      iExact = TRUE;
      break;
    }
  if (charset == ANSI_CHARSET || charset == SYMBOL_CHARSET) {
    charset = DEFAULT_CHARSET;
  }
  int subst_pitch_family = pitch_family;
  switch (charset) {
    case SHIFTJIS_CHARSET:
      subst_pitch_family = FF_ROMAN;
      break;
    case CHINESEBIG5_CHARSET:
    case HANGUL_CHARSET:
    case GB2312_CHARSET:
      subst_pitch_family = 0;
      break;
  }
  HFONT hFont =
      ::CreateFontA(-10, 0, 0, 0, weight, bItalic, 0, 0, charset,
                    OUT_TT_ONLY_PRECIS, 0, 0, subst_pitch_family, face);
  char facebuf[100];
  HFONT hOldFont = (HFONT)::SelectObject(m_hDC, hFont);
  ::GetTextFaceA(m_hDC, 100, facebuf);
  ::SelectObject(m_hDC, hOldFont);
  if (face.EqualNoCase(facebuf)) {
    return hFont;
  }
  int iCount = sizeof(VariantNames) / sizeof(VariantNames[0]);
  for (int i = 0; i < iCount; ++i) {
    if (face == VariantNames[i].m_pFaceName) {
      CFX_WideString wsFace = CFX_WideString::FromLocal(facebuf);
      const unsigned short* pName =
          (const unsigned short*)VariantNames[i].m_pVariantName;
      FX_STRSIZE len = CFX_WideString::WStringLength(pName);
      CFX_WideString wsName = CFX_WideString::FromUTF16LE(pName, len);
      if (wsFace == wsName) {
        return hFont;
      }
    }
  }
  ::DeleteObject(hFont);
  if (charset == DEFAULT_CHARSET) {
    return NULL;
  }
  switch (charset) {
    case SHIFTJIS_CHARSET:
      GetJapanesePreference(face, weight, pitch_family);
      break;
    case GB2312_CHARSET:
      GetGBPreference(face, weight, pitch_family);
      break;
    case HANGUL_CHARSET:
      face = "Gulim";
      break;
    case CHINESEBIG5_CHARSET:
      if (face.Find("MSung") >= 0) {
        face = "MingLiU";
      } else {
        face = "PMingLiU";
      }
      break;
  }
  hFont = ::CreateFontA(-10, 0, 0, 0, weight, bItalic, 0, 0, charset,
                        OUT_TT_ONLY_PRECIS, 0, 0, subst_pitch_family, face);
  return hFont;
}
void CFX_Win32FontInfo::DeleteFont(void* hFont) {
  ::DeleteObject(hFont);
}
FX_DWORD CFX_Win32FontInfo::GetFontData(void* hFont,
                                        FX_DWORD table,
                                        uint8_t* buffer,
                                        FX_DWORD size) {
  HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont);
  table = FXDWORD_FROM_MSBFIRST(table);
  size = ::GetFontData(m_hDC, table, 0, buffer, size);
  ::SelectObject(m_hDC, hOldFont);
  if (size == GDI_ERROR) {
    return 0;
  }
  return size;
}
FX_BOOL CFX_Win32FontInfo::GetFaceName(void* hFont, CFX_ByteString& name) {
  char facebuf[100];
  HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont);
  int ret = ::GetTextFaceA(m_hDC, 100, facebuf);
  ::SelectObject(m_hDC, hOldFont);
  if (ret == 0) {
    return FALSE;
  }
  name = facebuf;
  return TRUE;
}
FX_BOOL CFX_Win32FontInfo::GetFontCharset(void* hFont, int& charset) {
  TEXTMETRIC tm;
  HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont);
  ::GetTextMetrics(m_hDC, &tm);
  ::SelectObject(m_hDC, hOldFont);
  charset = tm.tmCharSet;
  return TRUE;
}
static FX_BOOL IsGDIEnabled() {
  // If GDI is disabled then GetDC for the desktop will fail.
  HDC hdc = ::GetDC(NULL);
  if (hdc) {
    ::ReleaseDC(NULL, hdc);
    return TRUE;
  }
  return FALSE;
}
IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
  if (IsGDIEnabled()) {
    return new CFX_Win32FontInfo;
  }
  // Select the fallback font information class if GDI is disabled.
  CFX_Win32FallbackFontInfo* pInfoFallback = new CFX_Win32FallbackFontInfo;
  // Construct the font path manually, SHGetKnownFolderPath won't work under
  // a restrictive sandbox.
  CHAR windows_path[MAX_PATH] = {};
  DWORD path_len = ::GetWindowsDirectoryA(windows_path, MAX_PATH);
  if (path_len > 0 && path_len < MAX_PATH) {
    CFX_ByteString fonts_path(windows_path);
    fonts_path += "\\Fonts";
    pInfoFallback->AddPath(fonts_path);
  }
  return pInfoFallback;
}
void CFX_GEModule::InitPlatform() {
  CWin32Platform* pPlatformData = new CWin32Platform;
  OSVERSIONINFO ver;
  ver.dwOSVersionInfoSize = sizeof(ver);
  GetVersionEx(&ver);
  pPlatformData->m_bHalfTone = ver.dwMajorVersion >= 5;
  if (IsGDIEnabled()) {
    pPlatformData->m_GdiplusExt.Load();
  }
  m_pPlatformData = pPlatformData;
  m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault(nullptr));
}
void CFX_GEModule::DestroyPlatform() {
  delete (CWin32Platform*)m_pPlatformData;
  m_pPlatformData = NULL;
}
CGdiDeviceDriver::CGdiDeviceDriver(HDC hDC, int device_class) {
  m_hDC = hDC;
  m_DeviceClass = device_class;
  CWin32Platform* pPlatform =
      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
  SetStretchBltMode(hDC, pPlatform->m_bHalfTone ? HALFTONE : COLORONCOLOR);
  if (GetObjectType(m_hDC) == OBJ_MEMDC) {
    HBITMAP hBitmap = CreateBitmap(1, 1, 1, 1, NULL);
    hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap);
    BITMAP bitmap;
    GetObject(hBitmap, sizeof bitmap, &bitmap);
    m_nBitsPerPixel = bitmap.bmBitsPixel;
    m_Width = bitmap.bmWidth;
    m_Height = abs(bitmap.bmHeight);
    hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap);
    DeleteObject(hBitmap);
  } else {
    m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
    m_Width = ::GetDeviceCaps(m_hDC, HORZRES);
    m_Height = ::GetDeviceCaps(m_hDC, VERTRES);
  }
  if (m_DeviceClass != FXDC_DISPLAY) {
    m_RenderCaps = FXRC_BIT_MASK;
  } else {
    m_RenderCaps = FXRC_GET_BITS | FXRC_BIT_MASK;
  }
}
int CGdiDeviceDriver::GetDeviceCaps(int caps_id) {
  switch (caps_id) {
    case FXDC_DEVICE_CLASS:
      return m_DeviceClass;
    case FXDC_PIXEL_WIDTH:
      return m_Width;
    case FXDC_PIXEL_HEIGHT:
      return m_Height;
    case FXDC_BITS_PIXEL:
      return m_nBitsPerPixel;
    case FXDC_RENDER_CAPS:
      return m_RenderCaps;
  }
  return 0;
}
void* CGdiDeviceDriver::GetClipRgn() {
  HRGN hClipRgn = CreateRectRgn(0, 0, 1, 1);
  if (::GetClipRgn(m_hDC, hClipRgn) == 0) {
    DeleteObject(hClipRgn);
    hClipRgn = NULL;
  }
  return (void*)hClipRgn;
}
FX_BOOL CGdiDeviceDriver::GDI_SetDIBits(const CFX_DIBitmap* pBitmap1,
                                        const FX_RECT* pSrcRect,
                                        int left,
                                        int top,
                                        void* pIccTransform) {
  if (m_DeviceClass == FXDC_PRINTER) {
    CFX_DIBitmap* pBitmap = pBitmap1->FlipImage(FALSE, TRUE);
    if (!pBitmap) {
      return FALSE;
    }
    if ((pBitmap->IsCmykImage() || pIccTransform) &&
        !pBitmap->ConvertFormat(FXDIB_Rgb, pIccTransform)) {
      return FALSE;
    }
    int width = pSrcRect->Width(), height = pSrcRect->Height();
    LPBYTE pBuffer = pBitmap->GetBuffer();
    CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap);
    ((BITMAPINFOHEADER*)info.c_str())->biHeight *= -1;
    FX_RECT dst_rect(0, 0, width, height);
    dst_rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
    int dst_width = dst_rect.Width();
    int dst_height = dst_rect.Height();
    ::StretchDIBits(m_hDC, left, top, dst_width, dst_height, 0, 0, dst_width,
                    dst_height, pBuffer, (BITMAPINFO*)info.c_str(),
                    DIB_RGB_COLORS, SRCCOPY);
    delete pBitmap;
  } else {
    CFX_DIBitmap* pBitmap = (CFX_DIBitmap*)pBitmap1;
    if ((pBitmap->IsCmykImage() || pIccTransform) &&
        (pBitmap = pBitmap->CloneConvert(FXDIB_Rgb, NULL, pIccTransform)) ==
            NULL) {
      return FALSE;
    }
    int width = pSrcRect->Width(), height = pSrcRect->Height();
    LPBYTE pBuffer = pBitmap->GetBuffer();
    CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap);
    ::SetDIBitsToDevice(m_hDC, left, top, width, height, pSrcRect->left,
                        pBitmap->GetHeight() - pSrcRect->bottom, 0,
                        pBitmap->GetHeight(), pBuffer,
                        (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    if (pBitmap != pBitmap1) {
      delete pBitmap;
    }
  }
  return TRUE;
}
FX_BOOL CGdiDeviceDriver::GDI_StretchDIBits(const CFX_DIBitmap* pBitmap1,
                                            int dest_left,
                                            int dest_top,
                                            int dest_width,
                                            int dest_height,
                                            FX_DWORD flags,
                                            void* pIccTransform) {
  CFX_DIBitmap* pBitmap = (CFX_DIBitmap*)pBitmap1;
  if (!pBitmap || dest_width == 0 || dest_height == 0) {
    return FALSE;
  }
  if ((pBitmap->IsCmykImage() || pIccTransform) &&
      !pBitmap->ConvertFormat(FXDIB_Rgb, pIccTransform)) {
    return FALSE;
  }
  CFX_ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap);
  if ((int64_t)abs(dest_width) * abs(dest_height) <
          (int64_t)pBitmap1->GetWidth() * pBitmap1->GetHeight() * 4 ||
      (flags & FXDIB_INTERPOL) || (flags & FXDIB_BICUBIC_INTERPOL)) {
    SetStretchBltMode(m_hDC, HALFTONE);
  } else {
    SetStretchBltMode(m_hDC, COLORONCOLOR);
  }
  CFX_DIBitmap* pToStrechBitmap = pBitmap;
  bool del = false;
  if (m_DeviceClass == FXDC_PRINTER &&
      ((int64_t)pBitmap->GetWidth() * pBitmap->GetHeight() >
       (int64_t)abs(dest_width) * abs(dest_height))) {
    pToStrechBitmap = pBitmap->StretchTo(dest_width, dest_height);
    del = true;
  }
  CFX_ByteString toStrechBitmapInfo =
      CFX_WindowsDIB::GetBitmapInfo(pToStrechBitmap);
  ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
                  pToStrechBitmap->GetWidth(), pToStrechBitmap->GetHeight(),
                  pToStrechBitmap->GetBuffer(),
                  (BITMAPINFO*)toStrechBitmapInfo.c_str(), DIB_RGB_COLORS,
                  SRCCOPY);
  if (del) {
    delete pToStrechBitmap;
  }
  return TRUE;
}
FX_BOOL CGdiDeviceDriver::GDI_StretchBitMask(const CFX_DIBitmap* pBitmap1,
                                             int dest_left,
                                             int dest_top,
                                             int dest_width,
                                             int dest_height,
                                             FX_DWORD bitmap_color,
                                             FX_DWORD flags,
                                             int alpha_flag,
                                             void* pIccTransform) {
  CFX_DIBitmap* pBitmap = (CFX_DIBitmap*)pBitmap1;
  if (!pBitmap || dest_width == 0 || dest_height == 0) {
    return FALSE;
  }
  _Color2Argb(bitmap_color, bitmap_color, alpha_flag | (1 << 24),
              pIccTransform);
  int width = pBitmap->GetWidth(), height = pBitmap->GetHeight();
  struct {
    BITMAPINFOHEADER bmiHeader;
    FX_DWORD bmiColors[2];
  } bmi;
  FXSYS_memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
  bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bmi.bmiHeader.biBitCount = 1;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biHeight = -height;
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biWidth = width;
  if (m_nBitsPerPixel != 1) {
    SetStretchBltMode(m_hDC, HALFTONE);
  }
  bmi.bmiColors[0] = 0xffffff;
  bmi.bmiColors[1] = 0;

  HBRUSH hPattern = CreateSolidBrush(bitmap_color & 0xffffff);
  HBRUSH hOld = (HBRUSH)SelectObject(m_hDC, hPattern);

  // In PDF, when image mask is 1, use device bitmap; when mask is 0, use brush
  // bitmap.
  // A complete list of the boolen operations is as follows:

  /* P(bitmap_color)    S(ImageMask)    D(DeviceBitmap)    Result
   *        0                 0                0              0
   *        0                 0                1              0
   *        0                 1                0              0
   *        0                 1                1              1
   *        1                 0                0              1
   *        1                 0                1              1
   *        1                 1                0              0
   *        1                 1                1              1
   */
  // The boolen codes is B8. Based on
  // http://msdn.microsoft.com/en-us/library/aa932106.aspx, the ROP3 code is
  // 0xB8074A

  ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
                  width, height, pBitmap->GetBuffer(), (BITMAPINFO*)&bmi,
                  DIB_RGB_COLORS, 0xB8074A);

  SelectObject(m_hDC, hOld);
  DeleteObject(hPattern);

  return TRUE;
}
FX_BOOL CGdiDeviceDriver::GetClipBox(FX_RECT* pRect) {
  return ::GetClipBox(m_hDC, (RECT*)pRect);
}
FX_BOOL CGdiDeviceDriver::SetClipRgn(void* hRgn) {
  ::SelectClipRgn(m_hDC, (HRGN)hRgn);
  return TRUE;
}
static HPEN _CreatePen(const CFX_GraphStateData* pGraphState,
                       const CFX_Matrix* pMatrix,
                       FX_DWORD argb) {
  FX_FLOAT width;
  FX_FLOAT scale = 1.f;
  if (pMatrix)
    scale = FXSYS_fabs(pMatrix->a) > FXSYS_fabs(pMatrix->b)
                ? FXSYS_fabs(pMatrix->a)
                : FXSYS_fabs(pMatrix->b);
  if (pGraphState) {
    width = scale * pGraphState->m_LineWidth;
  } else {
    width = 1.0f;
  }
  FX_DWORD PenStyle = PS_GEOMETRIC;
  if (width < 1) {
    width = 1;
  }
  if (pGraphState->m_DashCount) {
    PenStyle |= PS_USERSTYLE;
  } else {
    PenStyle |= PS_SOLID;
  }
  switch (pGraphState->m_LineCap) {
    case 0:
      PenStyle |= PS_ENDCAP_FLAT;
      break;
    case 1:
      PenStyle |= PS_ENDCAP_ROUND;
      break;
    case 2:
      PenStyle |= PS_ENDCAP_SQUARE;
      break;
  }
  switch (pGraphState->m_LineJoin) {
    case 0:
      PenStyle |= PS_JOIN_MITER;
      break;
    case 1:
      PenStyle |= PS_JOIN_ROUND;
      break;
    case 2:
      PenStyle |= PS_JOIN_BEVEL;
      break;
  }
  int a;
  FX_COLORREF rgb;
  ArgbDecode(argb, a, rgb);
  LOGBRUSH lb;
  lb.lbColor = rgb;
  lb.lbStyle = BS_SOLID;
  lb.lbHatch = 0;
  FX_DWORD* pDash = NULL;
  if (pGraphState->m_DashCount) {
    pDash = FX_Alloc(FX_DWORD, pGraphState->m_DashCount);
    for (int i = 0; i < pGraphState->m_DashCount; i++) {
      pDash[i] = FXSYS_round(
          pMatrix ? pMatrix->TransformDistance(pGraphState->m_DashArray[i])
                  : pGraphState->m_DashArray[i]);
      if (pDash[i] < 1) {
        pDash[i] = 1;
      }
    }
  }
  HPEN hPen = ExtCreatePen(PenStyle, (DWORD)FXSYS_ceil(width), &lb,
                           pGraphState->m_DashCount, (const DWORD*)pDash);
  FX_Free(pDash);
  return hPen;
}
static HBRUSH _CreateBrush(FX_DWORD argb) {
  int a;
  FX_COLORREF rgb;
  ArgbDecode(argb, a, rgb);
  return CreateSolidBrush(rgb);
}
static void _SetPathToDC(HDC hDC,
                         const CFX_PathData* pPathData,
                         const CFX_Matrix* pMatrix) {
  BeginPath(hDC);
  int nPoints = pPathData->GetPointCount();
  FX_PATHPOINT* pPoints = pPathData->GetPoints();
  for (int i = 0; i < nPoints; i++) {
    FX_FLOAT posx = pPoints[i].m_PointX, posy = pPoints[i].m_PointY;
    if (pMatrix) {
      pMatrix->Transform(posx, posy);
    }
    int screen_x = FXSYS_round(posx), screen_y = FXSYS_round(posy);
    int point_type = pPoints[i].m_Flag & FXPT_TYPE;
    if (point_type == PT_MOVETO) {
      MoveToEx(hDC, screen_x, screen_y, NULL);
    } else if (point_type == PT_LINETO) {
      if (pPoints[i].m_PointY == pPoints[i - 1].m_PointY &&
          pPoints[i].m_PointX == pPoints[i - 1].m_PointX) {
        screen_x++;
      }
      LineTo(hDC, screen_x, screen_y);
    } else if (point_type == PT_BEZIERTO) {
      POINT lppt[3];
      lppt[0].x = screen_x;
      lppt[0].y = screen_y;
      posx = pPoints[i + 1].m_PointX;
      posy = pPoints[i + 1].m_PointY;
      if (pMatrix) {
        pMatrix->Transform(posx, posy);
      }
      lppt[1].x = FXSYS_round(posx);
      lppt[1].y = FXSYS_round(posy);
      posx = pPoints[i + 2].m_PointX;
      posy = pPoints[i + 2].m_PointY;
      if (pMatrix) {
        pMatrix->Transform(posx, posy);
      }
      lppt[2].x = FXSYS_round(posx);
      lppt[2].y = FXSYS_round(posy);
      PolyBezierTo(hDC, lppt, 3);
      i += 2;
    }
    if (pPoints[i].m_Flag & PT_CLOSEFIGURE) {
      CloseFigure(hDC);
    }
  }
  EndPath(hDC);
}
void CGdiDeviceDriver::DrawLine(FX_FLOAT x1,
                                FX_FLOAT y1,
                                FX_FLOAT x2,
                                FX_FLOAT y2) {
  int flag1 = (x1 < 0) | ((x1 > m_Width) << 1) | ((y1 < 0) << 2) |
              ((y1 > m_Height) << 3);
  int flag2 = (x2 < 0) | ((x2 > m_Width) << 1) | ((y2 < 0) << 2) |
              ((y2 > m_Height) << 3);
  if (flag1 & flag2) {
    return;
  }
  if (flag1 || flag2) {
    agg::rect_base<FX_FLOAT> rect(0.0f, 0.0f, (FX_FLOAT)(m_Width),
                                  (FX_FLOAT)(m_Height));
    FX_FLOAT x[2], y[2];
    int np = agg::clip_liang_barsky<FX_FLOAT>(x1, y1, x2, y2, rect, x, y);
    if (np == 0) {
      return;
    }
    if (np == 1) {
      x2 = x[0];
      y2 = y[0];
    } else {
      x1 = x[0];
      y1 = y[0];
      x2 = x[np - 1];
      y2 = y[np - 1];
    }
  }
  MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), NULL);
  LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2));
}
static FX_BOOL _MatrixNoScaled(const CFX_Matrix* pMatrix) {
  return pMatrix->GetA() == 1.0f && pMatrix->GetB() == 0 &&
         pMatrix->GetC() == 0 && pMatrix->GetD() == 1.0f;
}
FX_BOOL CGdiDeviceDriver::DrawPath(const CFX_PathData* pPathData,
                                   const CFX_Matrix* pMatrix,
                                   const CFX_GraphStateData* pGraphState,
                                   FX_DWORD fill_color,
                                   FX_DWORD stroke_color,
                                   int fill_mode,
                                   int alpha_flag,
                                   void* pIccTransform,
                                   int blend_type) {
  if (blend_type != FXDIB_BLEND_NORMAL) {
    return FALSE;
  }
  _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform);
  _Color2Argb(stroke_color, stroke_color, alpha_flag, pIccTransform);
  CWin32Platform* pPlatform =
      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
  if (!(pGraphState || stroke_color == 0) &&
      !pPlatform->m_GdiplusExt.IsAvailable()) {
    CFX_FloatRect bbox_f = pPathData->GetBoundingBox();
    if (pMatrix) {
      bbox_f.Transform(pMatrix);
    }
    FX_RECT bbox = bbox_f.GetInnerRect();
    if (bbox.Width() <= 0) {
      return DrawCosmeticLine((FX_FLOAT)(bbox.left), (FX_FLOAT)(bbox.top),
                              (FX_FLOAT)(bbox.left),
                              (FX_FLOAT)(bbox.bottom + 1), fill_color,
                              alpha_flag, pIccTransform, FXDIB_BLEND_NORMAL);
    } else if (bbox.Height() <= 0) {
      return DrawCosmeticLine((FX_FLOAT)(bbox.left), (FX_FLOAT)(bbox.top),
                              (FX_FLOAT)(bbox.right + 1), (FX_FLOAT)(bbox.top),
                              fill_color, alpha_flag, pIccTransform,
                              FXDIB_BLEND_NORMAL);
    }
  }
  int fill_alpha = FXARGB_A(fill_color);
  int stroke_alpha = FXARGB_A(stroke_color);
  FX_BOOL bDrawAlpha = (fill_alpha > 0 && fill_alpha < 255) ||
                       (stroke_alpha > 0 && stroke_alpha < 255 && pGraphState);
  if (!pPlatform->m_GdiplusExt.IsAvailable() && bDrawAlpha) {
    return FALSE;
  }
  if (pPlatform->m_GdiplusExt.IsAvailable()) {
    if (bDrawAlpha ||
        ((m_DeviceClass != FXDC_PRINTER && !(fill_mode & FXFILL_FULLCOVER)) ||
         (pGraphState && pGraphState->m_DashCount))) {
      if (!((NULL == pMatrix || _MatrixNoScaled(pMatrix)) && pGraphState &&
            pGraphState->m_LineWidth == 1.f &&
            (pPathData->GetPointCount() == 5 ||
             pPathData->GetPointCount() == 4) &&
            pPathData->IsRect())) {
        if (pPlatform->m_GdiplusExt.DrawPath(m_hDC, pPathData, pMatrix,
                                             pGraphState, fill_color,
                                             stroke_color, fill_mode)) {
          return TRUE;
        }
      }
    }
  }
  int old_fill_mode = fill_mode;
  fill_mode &= 3;
  HPEN hPen = NULL;
  HBRUSH hBrush = NULL;
  if (pGraphState && stroke_alpha) {
    SetMiterLimit(m_hDC, pGraphState->m_MiterLimit, NULL);
    hPen = _CreatePen(pGraphState, pMatrix, stroke_color);
    hPen = (HPEN)SelectObject(m_hDC, hPen);
  }
  if (fill_mode && fill_alpha) {
    SetPolyFillMode(m_hDC, fill_mode);
    hBrush = _CreateBrush(fill_color);
    hBrush = (HBRUSH)SelectObject(m_hDC, hBrush);
  }
  if (pPathData->GetPointCount() == 2 && pGraphState &&
      pGraphState->m_DashCount) {
    FX_FLOAT x1 = pPathData->GetPointX(0), y1 = pPathData->GetPointY(0);
    if (pMatrix) {
      pMatrix->Transform(x1, y1);
    }
    FX_FLOAT x2 = pPathData->GetPointX(1), y2 = pPathData->GetPointY(1);
    if (pMatrix) {
      pMatrix->Transform(x2, y2);
    }
    DrawLine(x1, y1, x2, y2);
  } else {
    _SetPathToDC(m_hDC, pPathData, pMatrix);
    if (pGraphState && stroke_alpha) {
      if (fill_mode && fill_alpha) {
        if (old_fill_mode & FX_FILL_TEXT_MODE) {
          StrokeAndFillPath(m_hDC);
        } else {
          FillPath(m_hDC);
          _SetPathToDC(m_hDC, pPathData, pMatrix);
          StrokePath(m_hDC);
        }
      } else {
        StrokePath(m_hDC);
      }
    } else if (fill_mode && fill_alpha) {
      FillPath(m_hDC);
    }
  }
  if (hPen) {
    hPen = (HPEN)SelectObject(m_hDC, hPen);
    DeleteObject(hPen);
  }
  if (hBrush) {
    hBrush = (HBRUSH)SelectObject(m_hDC, hBrush);
    DeleteObject(hBrush);
  }
  return TRUE;
}
FX_BOOL CGdiDeviceDriver::FillRect(const FX_RECT* pRect,
                                   FX_DWORD fill_color,
                                   int alpha_flag,
                                   void* pIccTransform,
                                   int blend_type) {
  if (blend_type != FXDIB_BLEND_NORMAL) {
    return FALSE;
  }
  _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform);
  int alpha;
  FX_COLORREF rgb;
  ArgbDecode(fill_color, alpha, rgb);
  if (alpha == 0) {
    return TRUE;
  }
  if (alpha < 255) {
    return FALSE;
  }
  HBRUSH hBrush = CreateSolidBrush(rgb);
  ::FillRect(m_hDC, (RECT*)pRect, hBrush);
  DeleteObject(hBrush);
  return TRUE;
}
FX_BOOL CGdiDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
                                           const CFX_Matrix* pMatrix,
                                           int fill_mode) {
  if (pPathData->GetPointCount() == 5) {
    CFX_FloatRect rectf;
    if (pPathData->IsRect(pMatrix, &rectf)) {
      FX_RECT rect = rectf.GetOutterRect();
      IntersectClipRect(m_hDC, rect.left, rect.top, rect.right, rect.bottom);
      return TRUE;
    }
  }
  _SetPathToDC(m_hDC, pPathData, pMatrix);
  SetPolyFillMode(m_hDC, fill_mode & 3);
  SelectClipPath(m_hDC, RGN_AND);
  return TRUE;
}
FX_BOOL CGdiDeviceDriver::SetClip_PathStroke(
    const CFX_PathData* pPathData,
    const CFX_Matrix* pMatrix,
    const CFX_GraphStateData* pGraphState) {
  HPEN hPen = _CreatePen(pGraphState, pMatrix, 0xff000000);
  hPen = (HPEN)SelectObject(m_hDC, hPen);
  _SetPathToDC(m_hDC, pPathData, pMatrix);
  WidenPath(m_hDC);
  SetPolyFillMode(m_hDC, WINDING);
  FX_BOOL ret = SelectClipPath(m_hDC, RGN_AND);
  hPen = (HPEN)SelectObject(m_hDC, hPen);
  DeleteObject(hPen);
  return ret;
}
FX_BOOL CGdiDeviceDriver::DrawCosmeticLine(FX_FLOAT x1,
                                           FX_FLOAT y1,
                                           FX_FLOAT x2,
                                           FX_FLOAT y2,
                                           FX_DWORD color,
                                           int alpha_flag,
                                           void* pIccTransform,
                                           int blend_type) {
  if (blend_type != FXDIB_BLEND_NORMAL) {
    return FALSE;
  }
  _Color2Argb(color, color, alpha_flag | (1 << 24), pIccTransform);
  int a;
  FX_COLORREF rgb;
  ArgbDecode(color, a, rgb);
  if (a == 0) {
    return TRUE;
  }
  HPEN hPen = CreatePen(PS_SOLID, 1, rgb);
  hPen = (HPEN)SelectObject(m_hDC, hPen);
  MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), NULL);
  LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2));
  hPen = (HPEN)SelectObject(m_hDC, hPen);
  DeleteObject(hPen);
  return TRUE;
}
FX_BOOL CGdiDeviceDriver::DeleteDeviceRgn(void* pRgn) {
  DeleteObject((HGDIOBJ)pRgn);
  return TRUE;
}
CGdiDisplayDriver::CGdiDisplayDriver(HDC hDC)
    : CGdiDeviceDriver(hDC, FXDC_DISPLAY) {
  CWin32Platform* pPlatform =
      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
  if (pPlatform->m_GdiplusExt.IsAvailable()) {
    m_RenderCaps |= FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE;
  }
}
FX_BOOL CGdiDisplayDriver::GetDIBits(CFX_DIBitmap* pBitmap,
                                     int left,
                                     int top,
                                     void* pIccTransform,
                                     FX_BOOL bDEdge) {
  FX_BOOL ret = FALSE;
  int width = pBitmap->GetWidth();
  int height = pBitmap->GetHeight();
  HBITMAP hbmp = CreateCompatibleBitmap(m_hDC, width, height);
  HDC hDCMemory = CreateCompatibleDC(m_hDC);
  HBITMAP holdbmp = (HBITMAP)SelectObject(hDCMemory, hbmp);
  BitBlt(hDCMemory, 0, 0, width, height, m_hDC, left, top, SRCCOPY);
  SelectObject(hDCMemory, holdbmp);
  BITMAPINFO bmi;
  FXSYS_memset(&bmi, 0, sizeof bmi);
  bmi.bmiHeader.biSize = sizeof bmi.bmiHeader;
  bmi.bmiHeader.biBitCount = pBitmap->GetBPP();
  bmi.bmiHeader.biHeight = -height;
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biWidth = width;
  if (!CFX_GEModule::Get()->GetCodecModule() ||
      !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
    pIccTransform = NULL;
  }
  if (pBitmap->GetBPP() > 8 && !pBitmap->IsCmykImage() && !pIccTransform) {
    ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer(), &bmi,
                      DIB_RGB_COLORS) == height;
  } else {
    CFX_DIBitmap bitmap;
    if (bitmap.Create(width, height, FXDIB_Rgb)) {
      bmi.bmiHeader.biBitCount = 24;
      ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap.GetBuffer(), &bmi,
                  DIB_RGB_COLORS);
      ret = pBitmap->TransferBitmap(0, 0, width, height, &bitmap, 0, 0,
                                    pIccTransform);
    } else {
      ret = FALSE;
    }
  }
  if (pBitmap->HasAlpha() && ret) {
    pBitmap->LoadChannel(FXDIB_Alpha, 0xff);
  }
  DeleteObject(hbmp);
  DeleteObject(hDCMemory);
  return ret;
}
FX_BOOL CGdiDisplayDriver::SetDIBits(const CFX_DIBSource* pSource,
                                     FX_DWORD color,
                                     const FX_RECT* pSrcRect,
                                     int left,
                                     int top,
                                     int blend_type,
                                     int alpha_flag,
                                     void* pIccTransform) {
  ASSERT(blend_type == FXDIB_BLEND_NORMAL);
  if (pSource->IsAlphaMask()) {
    int width = pSource->GetWidth(), height = pSource->GetHeight();
    int alpha = FXGETFLAG_COLORTYPE(alpha_flag)
                    ? FXGETFLAG_ALPHA_FILL(alpha_flag)
                    : FXARGB_A(color);
    if (pSource->GetBPP() != 1 || alpha != 255) {
      CFX_DIBitmap background;
      if (!background.Create(width, height, FXDIB_Rgb32) ||
          !GetDIBits(&background, left, top, NULL) ||
          !background.CompositeMask(0, 0, width, height, pSource, color, 0, 0,
                                    FXDIB_BLEND_NORMAL, NULL, FALSE, alpha_flag,
                                    pIccTransform)) {
        return FALSE;
      }
      FX_RECT src_rect(0, 0, width, height);
      return SetDIBits(&background, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL,
                       0, NULL);
    }
    FX_RECT clip_rect(left, top, left + pSrcRect->Width(),
                      top + pSrcRect->Height());
    return StretchDIBits(pSource, color, left - pSrcRect->left,
                         top - pSrcRect->top, width, height, &clip_rect, 0,
                         alpha_flag, pIccTransform, FXDIB_BLEND_NORMAL);
  }
  int width = pSrcRect->Width(), height = pSrcRect->Height();
  if (pSource->HasAlpha()) {
    CFX_DIBitmap bitmap;
    if (!bitmap.Create(width, height, FXDIB_Rgb) ||
        !GetDIBits(&bitmap, left, top, NULL) ||
        !bitmap.CompositeBitmap(0, 0, width, height, pSource, pSrcRect->left,
                                pSrcRect->top, FXDIB_BLEND_NORMAL, NULL, FALSE,
                                pIccTransform)) {
      return FALSE;
    }
    FX_RECT src_rect(0, 0, width, height);
    return SetDIBits(&bitmap, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL, 0,
                     NULL);
  }
  CFX_DIBExtractor temp(pSource);
  CFX_DIBitmap* pBitmap = temp;
  if (pBitmap) {
    return GDI_SetDIBits(pBitmap, pSrcRect, left, top, pIccTransform);
  }
  return FALSE;
}
FX_BOOL CGdiDisplayDriver::UseFoxitStretchEngine(const CFX_DIBSource* pSource,
                                                 FX_DWORD color,
                                                 int dest_left,
                                                 int dest_top,
                                                 int dest_width,
                                                 int dest_height,
                                                 const FX_RECT* pClipRect,
                                                 int render_flags,
                                                 int alpha_flag,
                                                 void* pIccTransform,
                                                 int blend_type) {
  FX_RECT bitmap_clip = *pClipRect;
  if (dest_width < 0) {
    dest_left += dest_width;
  }
  if (dest_height < 0) {
    dest_top += dest_height;
  }
  bitmap_clip.Offset(-dest_left, -dest_top);
  CFX_DIBitmap* pStretched =
      pSource->StretchTo(dest_width, dest_height, render_flags, &bitmap_clip);
  if (!pStretched) {
    return TRUE;
  }
  FX_RECT src_rect(0, 0, pStretched->GetWidth(), pStretched->GetHeight());
  FX_BOOL ret =
      SetDIBits(pStretched, color, &src_rect, pClipRect->left, pClipRect->top,
                FXDIB_BLEND_NORMAL, alpha_flag, pIccTransform);
  delete pStretched;
  return ret;
}
FX_BOOL CGdiDisplayDriver::StretchDIBits(const CFX_DIBSource* pSource,
                                         FX_DWORD color,
                                         int dest_left,
                                         int dest_top,
                                         int dest_width,
                                         int dest_height,
                                         const FX_RECT* pClipRect,
                                         FX_DWORD flags,
                                         int alpha_flag,
                                         void* pIccTransform,
                                         int blend_type) {
  ASSERT(pSource && pClipRect);
  if (flags || dest_width > 10000 || dest_width < -10000 ||
      dest_height > 10000 || dest_height < -10000) {
    return UseFoxitStretchEngine(pSource, color, dest_left, dest_top,
                                 dest_width, dest_height, pClipRect, flags,
                                 alpha_flag, pIccTransform, blend_type);
  }
  if (pSource->IsAlphaMask()) {
    FX_RECT image_rect;
    image_rect.left = dest_width > 0 ? dest_left : dest_left + dest_width;
    image_rect.right = dest_width > 0 ? dest_left + dest_width : dest_left;
    image_rect.top = dest_height > 0 ? dest_top : dest_top + dest_height;
    image_rect.bottom = dest_height > 0 ? dest_top + dest_height : dest_top;
    FX_RECT clip_rect = image_rect;
    clip_rect.Intersect(*pClipRect);
    clip_rect.Offset(-image_rect.left, -image_rect.top);
    int clip_width = clip_rect.Width(), clip_height = clip_rect.Height();
    CFX_DIBitmap* pStretched =
        pSource->StretchTo(dest_width, dest_height, flags, &clip_rect);
    if (!pStretched) {
      return TRUE;
    }
    CFX_DIBitmap background;
    if (!background.Create(clip_width, clip_height, FXDIB_Rgb32) ||
        !GetDIBits(&background, image_rect.left + clip_rect.left,
                   image_rect.top + clip_rect.top, NULL) ||
        !background.CompositeMask(0, 0, clip_width, clip_height, pStretched,
                                  color, 0, 0, FXDIB_BLEND_NORMAL, NULL, FALSE,
                                  alpha_flag, pIccTransform)) {
      delete pStretched;
      return FALSE;
    }
    FX_RECT src_rect(0, 0, clip_width, clip_height);
    FX_BOOL ret =
        SetDIBits(&background, 0, &src_rect, image_rect.left + clip_rect.left,
                  image_rect.top + clip_rect.top, FXDIB_BLEND_NORMAL, 0, NULL);
    delete pStretched;
    return ret;
  }
  if (pSource->HasAlpha()) {
    CWin32Platform* pPlatform =
        (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    if (pPlatform->m_GdiplusExt.IsAvailable() && !pIccTransform &&
        !pSource->IsCmykImage()) {
      CFX_DIBExtractor temp(pSource);
      CFX_DIBitmap* pBitmap = temp;
      if (!pBitmap) {
        return FALSE;
      }
      return pPlatform->m_GdiplusExt.StretchDIBits(
          m_hDC, pBitmap, dest_left, dest_top, dest_width, dest_height,
          pClipRect, flags);
    }
    return UseFoxitStretchEngine(pSource, color, dest_left, dest_top,
                                 dest_width, dest_height, pClipRect, flags,
                                 alpha_flag, pIccTransform, blend_type);
  }
  CFX_DIBExtractor temp(pSource);
  CFX_DIBitmap* pBitmap = temp;
  if (pBitmap) {
    return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width,
                             dest_height, flags, pIccTransform);
  }
  return FALSE;
}
#define GET_PS_FEATURESETTING 4121
#define FEATURESETTING_PSLEVEL 2
int GetPSLevel(HDC hDC) {
  int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY);
  if (device_type != DT_RASPRINTER) {
    return 0;
  }
  FX_DWORD esc = GET_PS_FEATURESETTING;
  if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL)) {
    int param = FEATURESETTING_PSLEVEL;
    if (ExtEscape(hDC, GET_PS_FEATURESETTING, sizeof(int), (char*)&param,
                  sizeof(int), (char*)&param) > 0) {
      return param;
    }
  }
  esc = POSTSCRIPT_IDENTIFY;
  if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL) == 0) {
    esc = POSTSCRIPT_DATA;
    if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL)) {
      return 2;
    }
    return 0;
  }
  esc = PSIDENT_GDICENTRIC;
  if (ExtEscape(hDC, POSTSCRIPT_IDENTIFY, sizeof(FX_DWORD), (char*)&esc, 0,
                NULL) <= 0) {
    return 2;
  }
  esc = GET_PS_FEATURESETTING;
  if (ExtEscape(hDC, QUERYESCSUPPORT, sizeof esc, (char*)&esc, 0, NULL)) {
    int param = FEATURESETTING_PSLEVEL;
    if (ExtEscape(hDC, GET_PS_FEATURESETTING, sizeof(int), (char*)&param,
                  sizeof(int), (char*)&param) > 0) {
      return param;
    }
  }
  return 2;
}
int CFX_WindowsDevice::m_psLevel = 2;
CFX_WindowsDevice::CFX_WindowsDevice(HDC hDC,
                                     FX_BOOL bCmykOutput,
                                     FX_BOOL bForcePSOutput,
                                     int psLevel) {
  m_bForcePSOutput = bForcePSOutput;
  m_psLevel = psLevel;
  if (bForcePSOutput) {
    IFX_RenderDeviceDriver* pDriver = new CPSPrinterDriver;
    ((CPSPrinterDriver*)pDriver)->Init(hDC, psLevel, bCmykOutput);
    SetDeviceDriver(pDriver);
    return;
  }
  SetDeviceDriver(CreateDriver(hDC, bCmykOutput));
}
HDC CFX_WindowsDevice::GetDC() const {
  IFX_RenderDeviceDriver* pRDD = GetDeviceDriver();
  if (!pRDD) {
    return NULL;
  }
  return (HDC)pRDD->GetPlatformSurface();
}
IFX_RenderDeviceDriver* CFX_WindowsDevice::CreateDriver(HDC hDC,
                                                        FX_BOOL bCmykOutput) {
  int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY);
  int obj_type = ::GetObjectType(hDC);
  int device_class;
  if (device_type == DT_RASPRINTER || device_type == DT_PLOTTER ||
      obj_type == OBJ_ENHMETADC) {
    device_class = FXDC_PRINTER;
  } else {
    device_class = FXDC_DISPLAY;
  }
  if (device_class == FXDC_PRINTER) {
    return new CGdiPrinterDriver(hDC);
  }
  return new CGdiDisplayDriver(hDC);
}
CFX_WinBitmapDevice::CFX_WinBitmapDevice(int width,
                                         int height,
                                         FXDIB_Format format) {
  BITMAPINFOHEADER bmih;
  FXSYS_memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
  bmih.biSize = sizeof(BITMAPINFOHEADER);
  bmih.biBitCount = format & 0xff;
  bmih.biHeight = -height;
  bmih.biPlanes = 1;
  bmih.biWidth = width;
  uint8_t* pBuffer;
  m_hBitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
                               (void**)&pBuffer, NULL, 0);
  if (!m_hBitmap) {
    return;
  }
  CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
  pBitmap->Create(width, height, format, pBuffer);
  SetBitmap(pBitmap);
  m_hDC = ::CreateCompatibleDC(NULL);
  m_hOldBitmap = (HBITMAP)SelectObject(m_hDC, m_hBitmap);
  IFX_RenderDeviceDriver* pDriver = new CGdiDisplayDriver(m_hDC);
  SetDeviceDriver(pDriver);
}
CFX_WinBitmapDevice::~CFX_WinBitmapDevice() {
  if (m_hDC) {
    SelectObject(m_hDC, m_hOldBitmap);
    DeleteDC(m_hDC);
  }
  if (m_hBitmap) {
    DeleteObject(m_hBitmap);
  }
  delete GetBitmap();
}

#endif  // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
