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 <windows.h>
8
9 #include "core/fxcrt/fx_system.h"
10 #include "core/fxge/cfx_gemodule.h"
11 #include "core/fxge/win32/cfx_windowsdib.h"
12 #include "core/fxge/win32/win32_int.h"
13
GetBitmapInfo(const RetainPtr<CFX_DIBitmap> & pBitmap)14 ByteString CFX_WindowsDIB::GetBitmapInfo(
15 const RetainPtr<CFX_DIBitmap>& pBitmap) {
16 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 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 uint32_t* pPalette = (uint32_t*)(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 uint32_t* pPalette = (uint32_t*)(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
_FX_WindowsDIB_LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData,bool bAlpha)55 RetainPtr<CFX_DIBitmap> _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
56 LPVOID pData,
57 bool bAlpha) {
58 int width = pbmi->bmiHeader.biWidth;
59 int height = pbmi->bmiHeader.biHeight;
60 BOOL bBottomUp = true;
61 if (height < 0) {
62 height = -height;
63 bBottomUp = false;
64 }
65 int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4;
66 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
67 FXDIB_Format format = bAlpha
68 ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200)
69 : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
70 if (!pBitmap->Create(width, height, format))
71 return nullptr;
72
73 memcpy(pBitmap->GetBuffer(), pData, pitch * height);
74 if (bBottomUp) {
75 uint8_t* temp_buf = FX_Alloc(uint8_t, pitch);
76 int top = 0, bottom = height - 1;
77 while (top < bottom) {
78 memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch);
79 memcpy(pBitmap->GetBuffer() + top * pitch,
80 pBitmap->GetBuffer() + bottom * pitch, pitch);
81 memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch);
82 top++;
83 bottom--;
84 }
85 FX_Free(temp_buf);
86 temp_buf = nullptr;
87 }
88 if (pbmi->bmiHeader.biBitCount == 1) {
89 for (int i = 0; i < 2; i++)
90 pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
91 } else if (pbmi->bmiHeader.biBitCount == 8) {
92 for (int i = 0; i < 256; i++)
93 pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
94 }
95 return pBitmap;
96 }
97
LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData)98 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi,
99 LPVOID pData) {
100 return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, false);
101 }
102
GetDDBitmap(const RetainPtr<CFX_DIBitmap> & pBitmap,HDC hDC)103 HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
104 HDC hDC) {
105 ByteString info = GetBitmapInfo(pBitmap);
106 return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
107 pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
108 DIB_RGB_COLORS);
109 }
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 }
117
LoadFromFile(const wchar_t * filename)118 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) {
119 CWin32Platform* pPlatform =
120 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
121 if (pPlatform->m_GdiplusExt.IsAvailable()) {
122 WINDIB_Open_Args_ args;
123 args.flags = WINDIB_OPEN_PATHNAME;
124 args.path_name = filename;
125 return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
126 }
127 HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)filename,
128 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
129 if (!hBitmap) {
130 return nullptr;
131 }
132 HDC hDC = CreateCompatibleDC(nullptr);
133 int width;
134 int height;
135 GetBitmapSize(hBitmap, width, height);
136 auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
137 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
138 DeleteDC(hDC);
139 return nullptr;
140 }
141 ByteString info = GetBitmapInfo(pDIBitmap);
142 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
143 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
144 DeleteDC(hDC);
145 if (!ret)
146 return nullptr;
147 return pDIBitmap;
148 }
149
LoadFromFile(const char * filename)150 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const char* filename) {
151 return LoadFromFile(WideString::FromLocal(filename).c_str());
152 }
153
LoadDIBitmap(WINDIB_Open_Args_ args)154 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
155 CWin32Platform* pPlatform =
156 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
157 if (pPlatform->m_GdiplusExt.IsAvailable()) {
158 return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
159 }
160 if (args.flags == WINDIB_OPEN_MEMORY) {
161 return nullptr;
162 }
163 HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name,
164 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
165 if (!hBitmap) {
166 return nullptr;
167 }
168 HDC hDC = CreateCompatibleDC(nullptr);
169 int width, height;
170 GetBitmapSize(hBitmap, width, height);
171 auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
172 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
173 DeleteDC(hDC);
174 return nullptr;
175 }
176 ByteString info = GetBitmapInfo(pDIBitmap);
177 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
178 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
179 DeleteDC(hDC);
180 if (!ret)
181 return nullptr;
182 return pDIBitmap;
183 }
184
CFX_WindowsDIB(HDC hDC,int width,int height)185 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
186 Create(width, height, FXDIB_Rgb, (uint8_t*)1);
187 BITMAPINFOHEADER bmih;
188 memset(&bmih, 0, sizeof bmih);
189 bmih.biSize = sizeof bmih;
190 bmih.biBitCount = 24;
191 bmih.biHeight = -height;
192 bmih.biPlanes = 1;
193 bmih.biWidth = width;
194 LPVOID pData = nullptr;
195 m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pData,
196 nullptr, 0);
197 m_pBuffer.Reset(static_cast<uint8_t*>(pData));
198 m_hMemDC = CreateCompatibleDC(hDC);
199 m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
200 }
201
~CFX_WindowsDIB()202 CFX_WindowsDIB::~CFX_WindowsDIB() {
203 SelectObject(m_hMemDC, m_hOldBitmap);
204 DeleteDC(m_hMemDC);
205 DeleteObject(m_hBitmap);
206 }
207
LoadFromDevice(HDC hDC,int left,int top)208 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
209 ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
210 }
211
SetToDevice(HDC hDC,int left,int top)212 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
213 ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
214 }
215