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 "core/include/fxge/fx_ge.h" 8 9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ 10 #include <windows.h> 11 12 #include "core/include/fxge/fx_ge_win32.h" 13 #include "win32_int.h" 14 15 CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) { 16 CFX_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 FXSYS_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 FX_DWORD* pPalette = (FX_DWORD*)(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 FX_DWORD* pPalette = (FX_DWORD*)(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 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, 55 LPVOID pData, 56 FX_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 FX_BOOL ret = pBitmap->Create(width, height, format); 70 if (!ret) { 71 delete pBitmap; 72 return NULL; 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 = NULL; 88 } 89 if (pbmi->bmiHeader.biBitCount == 1) { 90 for (int i = 0; i < 2; i++) { 91 pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000); 92 } 93 } else if (pbmi->bmiHeader.biBitCount == 8) { 94 for (int i = 0; i < 256; i++) { 95 pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000); 96 } 97 } 98 return pBitmap; 99 } 100 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) { 101 return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE); 102 } 103 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) { 104 CFX_ByteString info = GetBitmapInfo(pBitmap); 105 HBITMAP hBitmap = NULL; 106 hBitmap = CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT, 107 pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), 108 DIB_RGB_COLORS); 109 return hBitmap; 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 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) { 118 CWin32Platform* pPlatform = 119 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 120 if (pPlatform->m_GdiplusExt.IsAvailable()) { 121 WINDIB_Open_Args_ args; 122 args.flags = WINDIB_OPEN_PATHNAME; 123 args.path_name = filename; 124 return pPlatform->m_GdiplusExt.LoadDIBitmap(args); 125 } 126 HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)filename, IMAGE_BITMAP, 127 0, 0, LR_LOADFROMFILE); 128 if (!hBitmap) { 129 return NULL; 130 } 131 HDC hDC = CreateCompatibleDC(NULL); 132 int width, height; 133 GetBitmapSize(hBitmap, width, height); 134 CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; 135 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { 136 delete pDIBitmap; 137 DeleteDC(hDC); 138 return NULL; 139 } 140 CFX_ByteString info = GetBitmapInfo(pDIBitmap); 141 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), 142 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); 143 if (!ret) { 144 delete pDIBitmap; 145 pDIBitmap = NULL; 146 } 147 DeleteDC(hDC); 148 return pDIBitmap; 149 } 150 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) { 151 CWin32Platform* pPlatform = 152 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 153 if (pPlatform->m_GdiplusExt.IsAvailable()) { 154 return pPlatform->m_GdiplusExt.LoadDIBitmap(args); 155 } 156 if (args.flags == WINDIB_OPEN_MEMORY) { 157 return NULL; 158 } 159 HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)args.path_name, 160 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); 161 if (!hBitmap) { 162 return NULL; 163 } 164 HDC hDC = CreateCompatibleDC(NULL); 165 int width, height; 166 GetBitmapSize(hBitmap, width, height); 167 CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; 168 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { 169 delete pDIBitmap; 170 DeleteDC(hDC); 171 return NULL; 172 } 173 CFX_ByteString info = GetBitmapInfo(pDIBitmap); 174 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), 175 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS); 176 if (!ret) { 177 delete pDIBitmap; 178 pDIBitmap = NULL; 179 } 180 DeleteDC(hDC); 181 return pDIBitmap; 182 } 183 CFX_DIBitmap* CFX_WindowsDIB::LoadFromDDB(HDC hDC, 184 HBITMAP hBitmap, 185 FX_DWORD* pPalette, 186 FX_DWORD palsize) { 187 FX_BOOL bCreatedDC = !hDC; 188 if (bCreatedDC) { 189 hDC = CreateCompatibleDC(NULL); 190 } 191 BITMAPINFOHEADER bmih; 192 FXSYS_memset(&bmih, 0, sizeof bmih); 193 bmih.biSize = sizeof bmih; 194 GetDIBits(hDC, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS); 195 int width = bmih.biWidth; 196 int height = abs(bmih.biHeight); 197 bmih.biHeight = -height; 198 bmih.biCompression = BI_RGB; 199 CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; 200 int ret = 0; 201 if (bmih.biBitCount == 1 || bmih.biBitCount == 8) { 202 int size = sizeof(BITMAPINFOHEADER) + 8; 203 if (bmih.biBitCount == 8) { 204 size += sizeof(FX_DWORD) * 254; 205 } 206 BITMAPINFO* pbmih = (BITMAPINFO*)FX_Alloc(uint8_t, size); 207 pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 208 pbmih->bmiHeader.biBitCount = bmih.biBitCount; 209 pbmih->bmiHeader.biCompression = BI_RGB; 210 pbmih->bmiHeader.biHeight = -height; 211 pbmih->bmiHeader.biPlanes = 1; 212 pbmih->bmiHeader.biWidth = bmih.biWidth; 213 if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1 214 ? FXDIB_1bppRgb 215 : FXDIB_8bppRgb)) { 216 delete pDIBitmap; 217 FX_Free(pbmih); 218 if (bCreatedDC) { 219 DeleteDC(hDC); 220 } 221 return NULL; 222 } 223 ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), 224 (BITMAPINFO*)pbmih, DIB_RGB_COLORS); 225 FX_Free(pbmih); 226 pbmih = NULL; 227 pDIBitmap->CopyPalette(pPalette, palsize); 228 } else { 229 if (bmih.biBitCount <= 24) { 230 bmih.biBitCount = 24; 231 } else { 232 bmih.biBitCount = 32; 233 } 234 if (!pDIBitmap->Create(bmih.biWidth, height, 235 bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) { 236 delete pDIBitmap; 237 if (bCreatedDC) { 238 DeleteDC(hDC); 239 } 240 return NULL; 241 } 242 ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), 243 (BITMAPINFO*)&bmih, DIB_RGB_COLORS); 244 if (ret != 0 && bmih.biBitCount == 32) { 245 int pitch = pDIBitmap->GetPitch(); 246 for (int row = 0; row < height; row++) { 247 uint8_t* dest_scan = (uint8_t*)(pDIBitmap->GetBuffer() + row * pitch); 248 for (int col = 0; col < width; col++) { 249 dest_scan[3] = 255; 250 dest_scan += 4; 251 } 252 } 253 } 254 } 255 if (ret == 0) { 256 delete pDIBitmap; 257 pDIBitmap = NULL; 258 } 259 if (bCreatedDC) { 260 DeleteDC(hDC); 261 } 262 return pDIBitmap; 263 } 264 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) { 265 Create(width, height, FXDIB_Rgb, (uint8_t*)1); 266 BITMAPINFOHEADER bmih; 267 FXSYS_memset(&bmih, 0, sizeof bmih); 268 bmih.biSize = sizeof bmih; 269 bmih.biBitCount = 24; 270 bmih.biHeight = -height; 271 bmih.biPlanes = 1; 272 bmih.biWidth = width; 273 m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, 274 (LPVOID*)&m_pBuffer, NULL, 0); 275 m_hMemDC = CreateCompatibleDC(hDC); 276 m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap); 277 } 278 CFX_WindowsDIB::~CFX_WindowsDIB() { 279 SelectObject(m_hMemDC, m_hOldBitmap); 280 DeleteDC(m_hMemDC); 281 DeleteObject(m_hBitmap); 282 } 283 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) { 284 ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY); 285 } 286 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) { 287 ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY); 288 } 289 #endif 290