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 "../../../include/fxge/fx_ge.h" 8 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_ 9 #include <windows.h> 10 #include "../../../include/fxge/fx_ge_win32.h" 11 #include "win32_int.h" 12 CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) 13 { 14 CFX_ByteString result; 15 int len = sizeof (BITMAPINFOHEADER); 16 if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) { 17 len += sizeof (DWORD) * (int)(1 << pBitmap->GetBPP()); 18 } 19 BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)result.GetBuffer(len); 20 FXSYS_memset32(pbmih, 0, sizeof (BITMAPINFOHEADER)); 21 pbmih->biSize = sizeof(BITMAPINFOHEADER); 22 pbmih->biBitCount = pBitmap->GetBPP(); 23 pbmih->biCompression = BI_RGB; 24 pbmih->biHeight = -(int)pBitmap->GetHeight(); 25 pbmih->biPlanes = 1; 26 pbmih->biWidth = pBitmap->GetWidth(); 27 if (pBitmap->GetBPP() == 8) { 28 FX_DWORD* pPalette = (FX_DWORD*)(pbmih + 1); 29 if (pBitmap->GetPalette() == NULL) { 30 for (int i = 0; i < 256; i ++) { 31 pPalette[i] = i * 0x010101; 32 } 33 } else { 34 for (int i = 0; i < 256; i ++) { 35 pPalette[i] = pBitmap->GetPalette()[i]; 36 } 37 } 38 } 39 if (pBitmap->GetBPP() == 1) { 40 FX_DWORD* pPalette = (FX_DWORD*)(pbmih + 1); 41 if (pBitmap->GetPalette() == NULL) { 42 pPalette[0] = 0; 43 pPalette[1] = 0xffffff; 44 } else { 45 pPalette[0] = pBitmap->GetPalette()[0]; 46 pPalette[1] = pBitmap->GetPalette()[1]; 47 } 48 } 49 result.ReleaseBuffer(len); 50 return result; 51 } 52 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData, FX_BOOL bAlpha) 53 { 54 int width = pbmi->bmiHeader.biWidth; 55 int height = pbmi->bmiHeader.biHeight; 56 BOOL bBottomUp = TRUE; 57 if (height < 0) { 58 height = -height; 59 bBottomUp = FALSE; 60 } 61 int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4; 62 CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap; 63 if (!pBitmap) { 64 return NULL; 65 } 66 FXDIB_Format format = bAlpha ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200) : (FXDIB_Format)pbmi->bmiHeader.biBitCount; 67 FX_BOOL ret = pBitmap->Create(width, height, format); 68 if (!ret) { 69 delete pBitmap; 70 return NULL; 71 } 72 FXSYS_memcpy32(pBitmap->GetBuffer(), pData, pitch * height); 73 if (bBottomUp) { 74 FX_LPBYTE temp_buf = FX_Alloc(FX_BYTE, pitch); 75 if (!temp_buf) { 76 if (pBitmap) { 77 delete pBitmap; 78 } 79 return NULL; 80 } 81 int top = 0, bottom = height - 1; 82 while (top < bottom) { 83 FXSYS_memcpy32(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch); 84 FXSYS_memcpy32(pBitmap->GetBuffer() + top * pitch, pBitmap->GetBuffer() + bottom * pitch, pitch); 85 FXSYS_memcpy32(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch); 86 top ++; 87 bottom --; 88 } 89 FX_Free(temp_buf); 90 temp_buf = NULL; 91 } 92 if (pbmi->bmiHeader.biBitCount == 1) { 93 for (int i = 0; i < 2; i ++) { 94 pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000); 95 } 96 } else if (pbmi->bmiHeader.biBitCount == 8) { 97 for (int i = 0; i < 256; i ++) { 98 pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000); 99 } 100 } 101 return pBitmap; 102 } 103 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) 104 { 105 return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE); 106 } 107 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) 108 { 109 CFX_ByteString info = GetBitmapInfo(pBitmap); 110 HBITMAP hBitmap = NULL; 111 hBitmap = CreateDIBitmap(hDC, (BITMAPINFOHEADER*)(FX_LPCSTR)info, CBM_INIT, 112 pBitmap->GetBuffer(), (BITMAPINFO*)(FX_LPCSTR)info, DIB_RGB_COLORS); 113 return hBitmap; 114 } 115 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) 116 { 117 BITMAP bmp; 118 GetObject(hBitmap, sizeof bmp, &bmp); 119 w = bmp.bmWidth; 120 h = bmp.bmHeight; 121 } 122 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(FX_LPCWSTR filename) 123 { 124 CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 125 if (pPlatform->m_GdiplusExt.IsAvailable()) { 126 WINDIB_Open_Args_ args; 127 args.flags = WINDIB_OPEN_PATHNAME; 128 args.path_name = filename; 129 return pPlatform->m_GdiplusExt.LoadDIBitmap(args); 130 } 131 HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); 132 if (hBitmap == NULL) { 133 return NULL; 134 } 135 HDC hDC = CreateCompatibleDC(NULL); 136 int width, height; 137 GetBitmapSize(hBitmap, width, height); 138 CFX_DIBitmap* pDIBitmap = FX_NEW CFX_DIBitmap; 139 if (!pDIBitmap) { 140 DeleteDC(hDC); 141 return NULL; 142 } 143 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { 144 delete pDIBitmap; 145 DeleteDC(hDC); 146 return NULL; 147 } 148 CFX_ByteString info = GetBitmapInfo(pDIBitmap); 149 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)(FX_LPCSTR)info, DIB_RGB_COLORS); 150 if (!ret) { 151 if (pDIBitmap) { 152 delete pDIBitmap; 153 } 154 pDIBitmap = NULL; 155 } 156 DeleteDC(hDC); 157 return pDIBitmap; 158 } 159 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) 160 { 161 CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData(); 162 if (pPlatform->m_GdiplusExt.IsAvailable()) { 163 return pPlatform->m_GdiplusExt.LoadDIBitmap(args); 164 } else if (args.flags == WINDIB_OPEN_MEMORY) { 165 return NULL; 166 } 167 HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)args.path_name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); 168 if (hBitmap == NULL) { 169 return NULL; 170 } 171 HDC hDC = CreateCompatibleDC(NULL); 172 int width, height; 173 GetBitmapSize(hBitmap, width, height); 174 CFX_DIBitmap* pDIBitmap = FX_NEW CFX_DIBitmap; 175 if (!pDIBitmap) { 176 DeleteDC(hDC); 177 return NULL; 178 } 179 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) { 180 delete pDIBitmap; 181 DeleteDC(hDC); 182 return NULL; 183 } 184 CFX_ByteString info = GetBitmapInfo(pDIBitmap); 185 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)(FX_LPCSTR)info, DIB_RGB_COLORS); 186 if (!ret) { 187 if (pDIBitmap) { 188 delete pDIBitmap; 189 } 190 pDIBitmap = NULL; 191 } 192 DeleteDC(hDC); 193 return pDIBitmap; 194 } 195 CFX_DIBitmap* CFX_WindowsDIB::LoadFromDDB(HDC hDC, HBITMAP hBitmap, FX_DWORD* pPalette, FX_DWORD palsize) 196 { 197 FX_BOOL bCreatedDC = hDC == NULL; 198 if (hDC == NULL) { 199 hDC = CreateCompatibleDC(NULL); 200 } 201 BITMAPINFOHEADER bmih; 202 FXSYS_memset32(&bmih, 0, sizeof bmih); 203 bmih.biSize = sizeof bmih; 204 GetDIBits(hDC, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS); 205 int width = bmih.biWidth; 206 int height = abs(bmih.biHeight); 207 bmih.biHeight = -height; 208 bmih.biCompression = BI_RGB; 209 CFX_DIBitmap* pDIBitmap = FX_NEW CFX_DIBitmap; 210 if (!pDIBitmap) { 211 return NULL; 212 } 213 int ret = 0; 214 if (bmih.biBitCount == 1 || bmih.biBitCount == 8) { 215 int size = sizeof (BITMAPINFOHEADER) + 8; 216 if (bmih.biBitCount == 8) { 217 size += sizeof (FX_DWORD) * 254; 218 } 219 BITMAPINFO* pbmih = (BITMAPINFO*)FX_Alloc(FX_BYTE, size); 220 if (!pbmih) { 221 delete pDIBitmap; 222 if (bCreatedDC) { 223 DeleteDC(hDC); 224 } 225 return NULL; 226 } 227 FXSYS_memset32(pbmih, 0, sizeof (BITMAPINFOHEADER)); 228 pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 229 pbmih->bmiHeader.biBitCount = bmih.biBitCount; 230 pbmih->bmiHeader.biCompression = BI_RGB; 231 pbmih->bmiHeader.biHeight = -height; 232 pbmih->bmiHeader.biPlanes = 1; 233 pbmih->bmiHeader.biWidth = bmih.biWidth; 234 if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1 ? FXDIB_1bppRgb : FXDIB_8bppRgb)) { 235 delete pDIBitmap; 236 FX_Free(pbmih); 237 if (bCreatedDC) { 238 DeleteDC(hDC); 239 } 240 return NULL; 241 } 242 ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)pbmih, DIB_RGB_COLORS); 243 FX_Free(pbmih); 244 pbmih = NULL; 245 pDIBitmap->CopyPalette(pPalette, palsize); 246 } else { 247 if (bmih.biBitCount <= 24) { 248 bmih.biBitCount = 24; 249 } else { 250 bmih.biBitCount = 32; 251 } 252 if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) { 253 delete pDIBitmap; 254 if (bCreatedDC) { 255 DeleteDC(hDC); 256 } 257 return NULL; 258 } 259 ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)&bmih, DIB_RGB_COLORS); 260 if (ret != 0 && bmih.biBitCount == 32) { 261 int pitch = pDIBitmap->GetPitch(); 262 for (int row = 0; row < height; row ++) { 263 FX_BYTE* dest_scan = (FX_BYTE*)(pDIBitmap->GetBuffer() + row * pitch); 264 for (int col = 0; col < width; col++) { 265 dest_scan[3] = 255; 266 dest_scan += 4; 267 } 268 } 269 } 270 } 271 if (ret == 0) { 272 if (pDIBitmap) { 273 delete pDIBitmap; 274 } 275 pDIBitmap = NULL; 276 } 277 if (bCreatedDC) { 278 DeleteDC(hDC); 279 } 280 return pDIBitmap; 281 } 282 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) 283 { 284 Create(width, height, FXDIB_Rgb, (FX_LPBYTE)1); 285 BITMAPINFOHEADER bmih; 286 FXSYS_memset32(&bmih, 0, sizeof bmih); 287 bmih.biSize = sizeof bmih; 288 bmih.biBitCount = 24; 289 bmih.biHeight = -height; 290 bmih.biPlanes = 1; 291 bmih.biWidth = width; 292 m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (LPVOID*)&m_pBuffer, NULL, 0); 293 m_hMemDC = CreateCompatibleDC(hDC); 294 m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap); 295 } 296 CFX_WindowsDIB::~CFX_WindowsDIB() 297 { 298 SelectObject(m_hMemDC, m_hOldBitmap); 299 DeleteDC(m_hMemDC); 300 DeleteObject(m_hBitmap); 301 } 302 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) 303 { 304 ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY); 305 } 306 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) 307 { 308 ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY); 309 } 310 #endif 311