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