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 "core/include/fxge/fx_ge.h"
      8 
      9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
     10 #include <windows.h>
     11 
     12 #include "core/include/fxge/fx_ge_win32.h"
     13 #include "win32_int.h"
     14 
     15 CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) {
     16   CFX_ByteString result;
     17   int len = sizeof(BITMAPINFOHEADER);
     18   if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) {
     19     len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());
     20   }
     21   BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)result.GetBuffer(len);
     22   FXSYS_memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
     23   pbmih->biSize = sizeof(BITMAPINFOHEADER);
     24   pbmih->biBitCount = pBitmap->GetBPP();
     25   pbmih->biCompression = BI_RGB;
     26   pbmih->biHeight = -(int)pBitmap->GetHeight();
     27   pbmih->biPlanes = 1;
     28   pbmih->biWidth = pBitmap->GetWidth();
     29   if (pBitmap->GetBPP() == 8) {
     30     FX_DWORD* pPalette = (FX_DWORD*)(pbmih + 1);
     31     if (pBitmap->GetPalette()) {
     32       for (int i = 0; i < 256; i++) {
     33         pPalette[i] = pBitmap->GetPalette()[i];
     34       }
     35     } else {
     36       for (int i = 0; i < 256; i++) {
     37         pPalette[i] = i * 0x010101;
     38       }
     39     }
     40   }
     41   if (pBitmap->GetBPP() == 1) {
     42     FX_DWORD* pPalette = (FX_DWORD*)(pbmih + 1);
     43     if (pBitmap->GetPalette()) {
     44       pPalette[0] = pBitmap->GetPalette()[0];
     45       pPalette[1] = pBitmap->GetPalette()[1];
     46     } else {
     47       pPalette[0] = 0;
     48       pPalette[1] = 0xffffff;
     49     }
     50   }
     51   result.ReleaseBuffer(len);
     52   return result;
     53 }
     54 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
     55                                          LPVOID pData,
     56                                          FX_BOOL bAlpha) {
     57   int width = pbmi->bmiHeader.biWidth;
     58   int height = pbmi->bmiHeader.biHeight;
     59   BOOL bBottomUp = TRUE;
     60   if (height < 0) {
     61     height = -height;
     62     bBottomUp = FALSE;
     63   }
     64   int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4;
     65   CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
     66   FXDIB_Format format = bAlpha
     67                             ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200)
     68                             : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
     69   FX_BOOL ret = pBitmap->Create(width, height, format);
     70   if (!ret) {
     71     delete pBitmap;
     72     return NULL;
     73   }
     74   FXSYS_memcpy(pBitmap->GetBuffer(), pData, pitch * height);
     75   if (bBottomUp) {
     76     uint8_t* temp_buf = FX_Alloc(uint8_t, pitch);
     77     int top = 0, bottom = height - 1;
     78     while (top < bottom) {
     79       FXSYS_memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch);
     80       FXSYS_memcpy(pBitmap->GetBuffer() + top * pitch,
     81                    pBitmap->GetBuffer() + bottom * pitch, pitch);
     82       FXSYS_memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch);
     83       top++;
     84       bottom--;
     85     }
     86     FX_Free(temp_buf);
     87     temp_buf = NULL;
     88   }
     89   if (pbmi->bmiHeader.biBitCount == 1) {
     90     for (int i = 0; i < 2; i++) {
     91       pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000);
     92     }
     93   } else if (pbmi->bmiHeader.biBitCount == 8) {
     94     for (int i = 0; i < 256; i++) {
     95       pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000);
     96     }
     97   }
     98   return pBitmap;
     99 }
    100 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) {
    101   return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE);
    102 }
    103 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) {
    104   CFX_ByteString info = GetBitmapInfo(pBitmap);
    105   HBITMAP hBitmap = NULL;
    106   hBitmap = CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
    107                            pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
    108                            DIB_RGB_COLORS);
    109   return hBitmap;
    110 }
    111 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) {
    112   BITMAP bmp;
    113   GetObject(hBitmap, sizeof bmp, &bmp);
    114   w = bmp.bmWidth;
    115   h = bmp.bmHeight;
    116 }
    117 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) {
    118   CWin32Platform* pPlatform =
    119       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    120   if (pPlatform->m_GdiplusExt.IsAvailable()) {
    121     WINDIB_Open_Args_ args;
    122     args.flags = WINDIB_OPEN_PATHNAME;
    123     args.path_name = filename;
    124     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    125   }
    126   HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)filename, IMAGE_BITMAP,
    127                                         0, 0, LR_LOADFROMFILE);
    128   if (!hBitmap) {
    129     return NULL;
    130   }
    131   HDC hDC = CreateCompatibleDC(NULL);
    132   int width, height;
    133   GetBitmapSize(hBitmap, width, height);
    134   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    135   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    136     delete pDIBitmap;
    137     DeleteDC(hDC);
    138     return NULL;
    139   }
    140   CFX_ByteString info = GetBitmapInfo(pDIBitmap);
    141   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    142                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    143   if (!ret) {
    144     delete pDIBitmap;
    145     pDIBitmap = NULL;
    146   }
    147   DeleteDC(hDC);
    148   return pDIBitmap;
    149 }
    150 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
    151   CWin32Platform* pPlatform =
    152       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    153   if (pPlatform->m_GdiplusExt.IsAvailable()) {
    154     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    155   }
    156   if (args.flags == WINDIB_OPEN_MEMORY) {
    157     return NULL;
    158   }
    159   HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)args.path_name,
    160                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    161   if (!hBitmap) {
    162     return NULL;
    163   }
    164   HDC hDC = CreateCompatibleDC(NULL);
    165   int width, height;
    166   GetBitmapSize(hBitmap, width, height);
    167   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    168   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    169     delete pDIBitmap;
    170     DeleteDC(hDC);
    171     return NULL;
    172   }
    173   CFX_ByteString info = GetBitmapInfo(pDIBitmap);
    174   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    175                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    176   if (!ret) {
    177     delete pDIBitmap;
    178     pDIBitmap = NULL;
    179   }
    180   DeleteDC(hDC);
    181   return pDIBitmap;
    182 }
    183 CFX_DIBitmap* CFX_WindowsDIB::LoadFromDDB(HDC hDC,
    184                                           HBITMAP hBitmap,
    185                                           FX_DWORD* pPalette,
    186                                           FX_DWORD palsize) {
    187   FX_BOOL bCreatedDC = !hDC;
    188   if (bCreatedDC) {
    189     hDC = CreateCompatibleDC(NULL);
    190   }
    191   BITMAPINFOHEADER bmih;
    192   FXSYS_memset(&bmih, 0, sizeof bmih);
    193   bmih.biSize = sizeof bmih;
    194   GetDIBits(hDC, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
    195   int width = bmih.biWidth;
    196   int height = abs(bmih.biHeight);
    197   bmih.biHeight = -height;
    198   bmih.biCompression = BI_RGB;
    199   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    200   int ret = 0;
    201   if (bmih.biBitCount == 1 || bmih.biBitCount == 8) {
    202     int size = sizeof(BITMAPINFOHEADER) + 8;
    203     if (bmih.biBitCount == 8) {
    204       size += sizeof(FX_DWORD) * 254;
    205     }
    206     BITMAPINFO* pbmih = (BITMAPINFO*)FX_Alloc(uint8_t, size);
    207     pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    208     pbmih->bmiHeader.biBitCount = bmih.biBitCount;
    209     pbmih->bmiHeader.biCompression = BI_RGB;
    210     pbmih->bmiHeader.biHeight = -height;
    211     pbmih->bmiHeader.biPlanes = 1;
    212     pbmih->bmiHeader.biWidth = bmih.biWidth;
    213     if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1
    214                                                      ? FXDIB_1bppRgb
    215                                                      : FXDIB_8bppRgb)) {
    216       delete pDIBitmap;
    217       FX_Free(pbmih);
    218       if (bCreatedDC) {
    219         DeleteDC(hDC);
    220       }
    221       return NULL;
    222     }
    223     ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    224                     (BITMAPINFO*)pbmih, DIB_RGB_COLORS);
    225     FX_Free(pbmih);
    226     pbmih = NULL;
    227     pDIBitmap->CopyPalette(pPalette, palsize);
    228   } else {
    229     if (bmih.biBitCount <= 24) {
    230       bmih.biBitCount = 24;
    231     } else {
    232       bmih.biBitCount = 32;
    233     }
    234     if (!pDIBitmap->Create(bmih.biWidth, height,
    235                            bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) {
    236       delete pDIBitmap;
    237       if (bCreatedDC) {
    238         DeleteDC(hDC);
    239       }
    240       return NULL;
    241     }
    242     ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    243                     (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
    244     if (ret != 0 && bmih.biBitCount == 32) {
    245       int pitch = pDIBitmap->GetPitch();
    246       for (int row = 0; row < height; row++) {
    247         uint8_t* dest_scan = (uint8_t*)(pDIBitmap->GetBuffer() + row * pitch);
    248         for (int col = 0; col < width; col++) {
    249           dest_scan[3] = 255;
    250           dest_scan += 4;
    251         }
    252       }
    253     }
    254   }
    255   if (ret == 0) {
    256     delete pDIBitmap;
    257     pDIBitmap = NULL;
    258   }
    259   if (bCreatedDC) {
    260     DeleteDC(hDC);
    261   }
    262   return pDIBitmap;
    263 }
    264 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
    265   Create(width, height, FXDIB_Rgb, (uint8_t*)1);
    266   BITMAPINFOHEADER bmih;
    267   FXSYS_memset(&bmih, 0, sizeof bmih);
    268   bmih.biSize = sizeof bmih;
    269   bmih.biBitCount = 24;
    270   bmih.biHeight = -height;
    271   bmih.biPlanes = 1;
    272   bmih.biWidth = width;
    273   m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
    274                                (LPVOID*)&m_pBuffer, NULL, 0);
    275   m_hMemDC = CreateCompatibleDC(hDC);
    276   m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
    277 }
    278 CFX_WindowsDIB::~CFX_WindowsDIB() {
    279   SelectObject(m_hMemDC, m_hOldBitmap);
    280   DeleteDC(m_hMemDC);
    281   DeleteObject(m_hBitmap);
    282 }
    283 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
    284   ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
    285 }
    286 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
    287   ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
    288 }
    289 #endif
    290