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