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