| // 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 <windows.h> | |
| #include "core/fxcrt/fx_system.h" | |
| #include "core/fxge/cfx_gemodule.h" | |
| #include "core/fxge/win32/cfx_windowsdib.h" | |
| #include "core/fxge/win32/win32_int.h" | |
| ByteString CFX_WindowsDIB::GetBitmapInfo( | |
| const RetainPtr<CFX_DIBitmap>& pBitmap) { | |
| int len = sizeof(BITMAPINFOHEADER); | |
| if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) | |
| len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP()); | |
| ByteString result; | |
| { | |
| // Span's lifetime must end before ReleaseBuffer() below. | |
| pdfium::span<char> cspan = result.GetBuffer(len); | |
| BITMAPINFOHEADER* pbmih = reinterpret_cast<BITMAPINFOHEADER*>(cspan.data()); | |
| memset(pbmih, 0, sizeof(BITMAPINFOHEADER)); | |
| pbmih->biSize = sizeof(BITMAPINFOHEADER); | |
| pbmih->biBitCount = pBitmap->GetBPP(); | |
| pbmih->biCompression = BI_RGB; | |
| pbmih->biHeight = -(int)pBitmap->GetHeight(); | |
| pbmih->biPlanes = 1; | |
| pbmih->biWidth = pBitmap->GetWidth(); | |
| if (pBitmap->GetBPP() == 8) { | |
| uint32_t* pPalette = (uint32_t*)(pbmih + 1); | |
| if (pBitmap->GetPalette()) { | |
| for (int i = 0; i < 256; i++) { | |
| pPalette[i] = pBitmap->GetPalette()[i]; | |
| } | |
| } else { | |
| for (int i = 0; i < 256; i++) { | |
| pPalette[i] = i * 0x010101; | |
| } | |
| } | |
| } | |
| if (pBitmap->GetBPP() == 1) { | |
| uint32_t* pPalette = (uint32_t*)(pbmih + 1); | |
| if (pBitmap->GetPalette()) { | |
| pPalette[0] = pBitmap->GetPalette()[0]; | |
| pPalette[1] = pBitmap->GetPalette()[1]; | |
| } else { | |
| pPalette[0] = 0; | |
| pPalette[1] = 0xffffff; | |
| } | |
| } | |
| } | |
| result.ReleaseBuffer(len); | |
| return result; | |
| } | |
| RetainPtr<CFX_DIBitmap> FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, | |
| LPVOID pData, | |
| bool bAlpha) { | |
| int width = pbmi->bmiHeader.biWidth; | |
| int height = pbmi->bmiHeader.biHeight; | |
| BOOL bBottomUp = true; | |
| if (height < 0) { | |
| height = -height; | |
| bBottomUp = false; | |
| } | |
| int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4; | |
| auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); | |
| FXDIB_Format format = bAlpha | |
| ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200) | |
| : (FXDIB_Format)pbmi->bmiHeader.biBitCount; | |
| if (!pBitmap->Create(width, height, format)) | |
| return nullptr; | |
| memcpy(pBitmap->GetBuffer(), pData, pitch * height); | |
| if (bBottomUp) { | |
| uint8_t* temp_buf = FX_Alloc(uint8_t, pitch); | |
| int top = 0, bottom = height - 1; | |
| while (top < bottom) { | |
| memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch); | |
| memcpy(pBitmap->GetBuffer() + top * pitch, | |
| pBitmap->GetBuffer() + bottom * pitch, pitch); | |
| memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch); | |
| top++; | |
| bottom--; | |
| } | |
| FX_Free(temp_buf); | |
| temp_buf = nullptr; | |
| } | |
| if (pbmi->bmiHeader.biBitCount == 1) { | |
| for (int i = 0; i < 2; i++) | |
| pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000); | |
| } else if (pbmi->bmiHeader.biBitCount == 8) { | |
| for (int i = 0; i < 256; i++) | |
| pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000); | |
| } | |
| return pBitmap; | |
| } | |
| RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, | |
| LPVOID pData) { | |
| return FX_WindowsDIB_LoadFromBuf(pbmi, pData, false); | |
| } | |
| HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap, | |
| HDC hDC) { | |
| ByteString info = GetBitmapInfo(pBitmap); | |
| return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT, | |
| pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), | |
| DIB_RGB_COLORS); | |
| } | |
| void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) { | |
| BITMAP bmp; | |
| GetObject(hBitmap, sizeof bmp, &bmp); | |
| w = bmp.bmWidth; | |
| h = bmp.bmHeight; | |
| } | |
| RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) { | |
| auto* pPlatform = | |
| static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform()); | |
| if (pPlatform->m_GdiplusExt.IsAvailable()) { | |
| WINDIB_Open_Args_ args; | |
| args.flags = WINDIB_OPEN_PATHNAME; | |
| args.path_name = filename; | |
| return pPlatform->m_GdiplusExt.LoadDIBitmap(args); | |
| } | |
| HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)filename, | |
| IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); | |
| if (!hBitmap) { | |
| return nullptr; | |
| } | |
| HDC hDC = CreateCompatibleDC(nullptr); | |
| int width; | |
| int height; | |
| GetBitmapSize(hBitmap, width, height); | |
| auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); | |
| if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { | |
| DeleteDC(hDC); | |
| return nullptr; | |
| } | |
| ByteString info = GetBitmapInfo(pDIBitmap); | |
| int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), | |
| (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); | |
| DeleteDC(hDC); | |
| if (!ret) | |
| return nullptr; | |
| return pDIBitmap; | |
| } | |
| RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const char* filename) { | |
| return LoadFromFile(WideString::FromDefANSI(filename).c_str()); | |
| } | |
| RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) { | |
| auto* pPlatform = | |
| static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform()); | |
| if (pPlatform->m_GdiplusExt.IsAvailable()) { | |
| return pPlatform->m_GdiplusExt.LoadDIBitmap(args); | |
| } | |
| if (args.flags == WINDIB_OPEN_MEMORY) { | |
| return nullptr; | |
| } | |
| HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name, | |
| IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); | |
| if (!hBitmap) { | |
| return nullptr; | |
| } | |
| HDC hDC = CreateCompatibleDC(nullptr); | |
| int width, height; | |
| GetBitmapSize(hBitmap, width, height); | |
| auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); | |
| if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { | |
| DeleteDC(hDC); | |
| return nullptr; | |
| } | |
| ByteString info = GetBitmapInfo(pDIBitmap); | |
| int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), | |
| (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); | |
| DeleteDC(hDC); | |
| if (!ret) | |
| return nullptr; | |
| return pDIBitmap; | |
| } | |
| CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) { | |
| Create(width, height, FXDIB_Rgb, (uint8_t*)1, 0); | |
| BITMAPINFOHEADER bmih; | |
| memset(&bmih, 0, sizeof bmih); | |
| bmih.biSize = sizeof bmih; | |
| bmih.biBitCount = 24; | |
| bmih.biHeight = -height; | |
| bmih.biPlanes = 1; | |
| bmih.biWidth = width; | |
| LPVOID pData = nullptr; | |
| m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pData, | |
| nullptr, 0); | |
| m_pBuffer.Reset(static_cast<uint8_t*>(pData)); | |
| m_hMemDC = CreateCompatibleDC(hDC); | |
| m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap); | |
| } | |
| CFX_WindowsDIB::~CFX_WindowsDIB() { | |
| SelectObject(m_hMemDC, m_hOldBitmap); | |
| DeleteDC(m_hMemDC); | |
| DeleteObject(m_hBitmap); | |
| } | |
| void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) { | |
| ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY); | |
| } | |
| void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) { | |
| ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY); | |
| } |