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