• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetBitmapInfo(const CFX_DIBitmap * pBitmap)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 }
_FX_WindowsDIB_LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData,FX_BOOL bAlpha)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 }
LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData)100 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) {
101   return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE);
102 }
GetDDBitmap(const CFX_DIBitmap * pBitmap,HDC hDC)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 }
GetBitmapSize(HBITMAP hBitmap,int & w,int & h)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 }
LoadFromFile(const FX_WCHAR * filename)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 }
LoadDIBitmap(WINDIB_Open_Args_ args)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 }
LoadFromDDB(HDC hDC,HBITMAP hBitmap,FX_DWORD * pPalette,FX_DWORD palsize)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 }
CFX_WindowsDIB(HDC hDC,int width,int height)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 }
~CFX_WindowsDIB()278 CFX_WindowsDIB::~CFX_WindowsDIB() {
279   SelectObject(m_hMemDC, m_hOldBitmap);
280   DeleteDC(m_hMemDC);
281   DeleteObject(m_hBitmap);
282 }
LoadFromDevice(HDC hDC,int left,int top)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 }
SetToDevice(HDC hDC,int left,int top)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