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"
GetBitmapInfo(const CFX_DIBitmap * pBitmap)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 }
_FX_WindowsDIB_LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData,FX_BOOL bAlpha)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 }
LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData)94 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData)
95 {
96 return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE);
97 }
GetDDBitmap(const CFX_DIBitmap * pBitmap,HDC hDC)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 }
GetBitmapSize(HBITMAP hBitmap,int & w,int & h)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 }
LoadFromFile(FX_LPCWSTR filename)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 }
LoadDIBitmap(WINDIB_Open_Args_ args)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 }
LoadFromDDB(HDC hDC,HBITMAP hBitmap,FX_DWORD * pPalette,FX_DWORD palsize)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 }
CFX_WindowsDIB(HDC hDC,int width,int height)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 }
~CFX_WindowsDIB()268 CFX_WindowsDIB::~CFX_WindowsDIB()
269 {
270 SelectObject(m_hMemDC, m_hOldBitmap);
271 DeleteDC(m_hMemDC);
272 DeleteObject(m_hBitmap);
273 }
LoadFromDevice(HDC hDC,int left,int top)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 }
SetToDevice(HDC hDC,int left,int top)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