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 <windows.h>
      8 
      9 #include "core/fxcrt/fx_system.h"
     10 #include "core/fxge/cfx_gemodule.h"
     11 #include "core/fxge/win32/cfx_windowsdib.h"
     12 #include "core/fxge/win32/win32_int.h"
     13 
     14 ByteString CFX_WindowsDIB::GetBitmapInfo(
     15     const RetainPtr<CFX_DIBitmap>& pBitmap) {
     16   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   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     uint32_t* pPalette = (uint32_t*)(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     uint32_t* pPalette = (uint32_t*)(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 
     55 RetainPtr<CFX_DIBitmap> _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
     56                                                    LPVOID pData,
     57                                                    bool bAlpha) {
     58   int width = pbmi->bmiHeader.biWidth;
     59   int height = pbmi->bmiHeader.biHeight;
     60   BOOL bBottomUp = true;
     61   if (height < 0) {
     62     height = -height;
     63     bBottomUp = false;
     64   }
     65   int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4;
     66   auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
     67   FXDIB_Format format = bAlpha
     68                             ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200)
     69                             : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
     70   if (!pBitmap->Create(width, height, format))
     71     return nullptr;
     72 
     73   memcpy(pBitmap->GetBuffer(), pData, pitch * height);
     74   if (bBottomUp) {
     75     uint8_t* temp_buf = FX_Alloc(uint8_t, pitch);
     76     int top = 0, bottom = height - 1;
     77     while (top < bottom) {
     78       memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch);
     79       memcpy(pBitmap->GetBuffer() + top * pitch,
     80              pBitmap->GetBuffer() + bottom * pitch, pitch);
     81       memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch);
     82       top++;
     83       bottom--;
     84     }
     85     FX_Free(temp_buf);
     86     temp_buf = nullptr;
     87   }
     88   if (pbmi->bmiHeader.biBitCount == 1) {
     89     for (int i = 0; i < 2; i++)
     90       pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
     91   } else if (pbmi->bmiHeader.biBitCount == 8) {
     92     for (int i = 0; i < 256; i++)
     93       pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
     94   }
     95   return pBitmap;
     96 }
     97 
     98 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi,
     99                                                     LPVOID pData) {
    100   return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, false);
    101 }
    102 
    103 HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
    104                                     HDC hDC) {
    105   ByteString info = GetBitmapInfo(pBitmap);
    106   return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
    107                         pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
    108                         DIB_RGB_COLORS);
    109 }
    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 
    118 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) {
    119   CWin32Platform* pPlatform =
    120       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    121   if (pPlatform->m_GdiplusExt.IsAvailable()) {
    122     WINDIB_Open_Args_ args;
    123     args.flags = WINDIB_OPEN_PATHNAME;
    124     args.path_name = filename;
    125     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    126   }
    127   HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)filename,
    128                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    129   if (!hBitmap) {
    130     return nullptr;
    131   }
    132   HDC hDC = CreateCompatibleDC(nullptr);
    133   int width;
    134   int height;
    135   GetBitmapSize(hBitmap, width, height);
    136   auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
    137   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    138     DeleteDC(hDC);
    139     return nullptr;
    140   }
    141   ByteString info = GetBitmapInfo(pDIBitmap);
    142   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    143                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    144   DeleteDC(hDC);
    145   if (!ret)
    146     return nullptr;
    147   return pDIBitmap;
    148 }
    149 
    150 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const char* filename) {
    151   return LoadFromFile(WideString::FromLocal(filename).c_str());
    152 }
    153 
    154 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
    155   CWin32Platform* pPlatform =
    156       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    157   if (pPlatform->m_GdiplusExt.IsAvailable()) {
    158     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    159   }
    160   if (args.flags == WINDIB_OPEN_MEMORY) {
    161     return nullptr;
    162   }
    163   HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name,
    164                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    165   if (!hBitmap) {
    166     return nullptr;
    167   }
    168   HDC hDC = CreateCompatibleDC(nullptr);
    169   int width, height;
    170   GetBitmapSize(hBitmap, width, height);
    171   auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
    172   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    173     DeleteDC(hDC);
    174     return nullptr;
    175   }
    176   ByteString info = GetBitmapInfo(pDIBitmap);
    177   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    178                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    179   DeleteDC(hDC);
    180   if (!ret)
    181     return nullptr;
    182   return pDIBitmap;
    183 }
    184 
    185 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
    186   Create(width, height, FXDIB_Rgb, (uint8_t*)1);
    187   BITMAPINFOHEADER bmih;
    188   memset(&bmih, 0, sizeof bmih);
    189   bmih.biSize = sizeof bmih;
    190   bmih.biBitCount = 24;
    191   bmih.biHeight = -height;
    192   bmih.biPlanes = 1;
    193   bmih.biWidth = width;
    194   LPVOID pData = nullptr;
    195   m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pData,
    196                                nullptr, 0);
    197   m_pBuffer.Reset(static_cast<uint8_t*>(pData));
    198   m_hMemDC = CreateCompatibleDC(hDC);
    199   m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
    200 }
    201 
    202 CFX_WindowsDIB::~CFX_WindowsDIB() {
    203   SelectObject(m_hMemDC, m_hOldBitmap);
    204   DeleteDC(m_hMemDC);
    205   DeleteObject(m_hBitmap);
    206 }
    207 
    208 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
    209   ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
    210 }
    211 
    212 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
    213   ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
    214 }
    215