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 CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) {
     15   CFX_ByteString result;
     16   int len = sizeof(BITMAPINFOHEADER);
     17   if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) {
     18     len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());
     19   }
     20   BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)result.GetBuffer(len);
     21   FXSYS_memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
     22   pbmih->biSize = sizeof(BITMAPINFOHEADER);
     23   pbmih->biBitCount = pBitmap->GetBPP();
     24   pbmih->biCompression = BI_RGB;
     25   pbmih->biHeight = -(int)pBitmap->GetHeight();
     26   pbmih->biPlanes = 1;
     27   pbmih->biWidth = pBitmap->GetWidth();
     28   if (pBitmap->GetBPP() == 8) {
     29     uint32_t* pPalette = (uint32_t*)(pbmih + 1);
     30     if (pBitmap->GetPalette()) {
     31       for (int i = 0; i < 256; i++) {
     32         pPalette[i] = pBitmap->GetPalette()[i];
     33       }
     34     } else {
     35       for (int i = 0; i < 256; i++) {
     36         pPalette[i] = i * 0x010101;
     37       }
     38     }
     39   }
     40   if (pBitmap->GetBPP() == 1) {
     41     uint32_t* pPalette = (uint32_t*)(pbmih + 1);
     42     if (pBitmap->GetPalette()) {
     43       pPalette[0] = pBitmap->GetPalette()[0];
     44       pPalette[1] = pBitmap->GetPalette()[1];
     45     } else {
     46       pPalette[0] = 0;
     47       pPalette[1] = 0xffffff;
     48     }
     49   }
     50   result.ReleaseBuffer(len);
     51   return result;
     52 }
     53 
     54 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
     55                                          LPVOID pData,
     56                                          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   bool ret = pBitmap->Create(width, height, format);
     70   if (!ret) {
     71     delete pBitmap;
     72     return nullptr;
     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 = nullptr;
     88   }
     89   if (pbmi->bmiHeader.biBitCount == 1) {
     90     for (int i = 0; i < 2; i++) {
     91       pBitmap->SetPaletteEntry(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
     92     }
     93   } else if (pbmi->bmiHeader.biBitCount == 8) {
     94     for (int i = 0; i < 256; i++) {
     95       pBitmap->SetPaletteEntry(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
     96     }
     97   }
     98   return pBitmap;
     99 }
    100 
    101 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) {
    102   return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, false);
    103 }
    104 
    105 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) {
    106   CFX_ByteString info = GetBitmapInfo(pBitmap);
    107   return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
    108                         pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
    109                         DIB_RGB_COLORS);
    110 }
    111 
    112 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) {
    113   BITMAP bmp;
    114   GetObject(hBitmap, sizeof bmp, &bmp);
    115   w = bmp.bmWidth;
    116   h = bmp.bmHeight;
    117 }
    118 
    119 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) {
    120   CWin32Platform* pPlatform =
    121       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    122   if (pPlatform->m_GdiplusExt.IsAvailable()) {
    123     WINDIB_Open_Args_ args;
    124     args.flags = WINDIB_OPEN_PATHNAME;
    125     args.path_name = filename;
    126     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    127   }
    128   HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)filename,
    129                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    130   if (!hBitmap) {
    131     return nullptr;
    132   }
    133   HDC hDC = CreateCompatibleDC(nullptr);
    134   int width, height;
    135   GetBitmapSize(hBitmap, width, height);
    136   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    137   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    138     delete pDIBitmap;
    139     DeleteDC(hDC);
    140     return nullptr;
    141   }
    142   CFX_ByteString info = GetBitmapInfo(pDIBitmap);
    143   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    144                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    145   if (!ret) {
    146     delete pDIBitmap;
    147     pDIBitmap = nullptr;
    148   }
    149   DeleteDC(hDC);
    150   return pDIBitmap;
    151 }
    152 
    153 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_CHAR* filename) {
    154   return LoadFromFile(CFX_WideString::FromLocal(filename).c_str());
    155 }
    156 
    157 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
    158   CWin32Platform* pPlatform =
    159       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    160   if (pPlatform->m_GdiplusExt.IsAvailable()) {
    161     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    162   }
    163   if (args.flags == WINDIB_OPEN_MEMORY) {
    164     return nullptr;
    165   }
    166   HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name,
    167                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    168   if (!hBitmap) {
    169     return nullptr;
    170   }
    171   HDC hDC = CreateCompatibleDC(nullptr);
    172   int width, height;
    173   GetBitmapSize(hBitmap, width, height);
    174   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    175   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    176     delete pDIBitmap;
    177     DeleteDC(hDC);
    178     return nullptr;
    179   }
    180   CFX_ByteString info = GetBitmapInfo(pDIBitmap);
    181   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
    182                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    183   if (!ret) {
    184     delete pDIBitmap;
    185     pDIBitmap = nullptr;
    186   }
    187   DeleteDC(hDC);
    188   return pDIBitmap;
    189 }
    190 
    191 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
    192   Create(width, height, FXDIB_Rgb, (uint8_t*)1);
    193   BITMAPINFOHEADER bmih;
    194   FXSYS_memset(&bmih, 0, sizeof bmih);
    195   bmih.biSize = sizeof bmih;
    196   bmih.biBitCount = 24;
    197   bmih.biHeight = -height;
    198   bmih.biPlanes = 1;
    199   bmih.biWidth = width;
    200   m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
    201                                (LPVOID*)&m_pBuffer, nullptr, 0);
    202   m_hMemDC = CreateCompatibleDC(hDC);
    203   m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
    204 }
    205 
    206 CFX_WindowsDIB::~CFX_WindowsDIB() {
    207   SelectObject(m_hMemDC, m_hOldBitmap);
    208   DeleteDC(m_hMemDC);
    209   DeleteObject(m_hBitmap);
    210 }
    211 
    212 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
    213   ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
    214 }
    215 
    216 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
    217   ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
    218 }
    219