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 int len = sizeof(BITMAPINFOHEADER);
17 if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8)
18 len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());
19
20 ByteString result;
21 {
22 // Span's lifetime must end before ReleaseBuffer() below.
23 pdfium::span<char> cspan = result.GetBuffer(len);
24 BITMAPINFOHEADER* pbmih = reinterpret_cast<BITMAPINFOHEADER*>(cspan.data());
25 memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
26 pbmih->biSize = sizeof(BITMAPINFOHEADER);
27 pbmih->biBitCount = pBitmap->GetBPP();
28 pbmih->biCompression = BI_RGB;
29 pbmih->biHeight = -(int)pBitmap->GetHeight();
30 pbmih->biPlanes = 1;
31 pbmih->biWidth = pBitmap->GetWidth();
32 if (pBitmap->GetBPP() == 8) {
33 uint32_t* pPalette = (uint32_t*)(pbmih + 1);
34 if (pBitmap->GetPalette()) {
35 for (int i = 0; i < 256; i++) {
36 pPalette[i] = pBitmap->GetPalette()[i];
37 }
38 } else {
39 for (int i = 0; i < 256; i++) {
40 pPalette[i] = i * 0x010101;
41 }
42 }
43 }
44 if (pBitmap->GetBPP() == 1) {
45 uint32_t* pPalette = (uint32_t*)(pbmih + 1);
46 if (pBitmap->GetPalette()) {
47 pPalette[0] = pBitmap->GetPalette()[0];
48 pPalette[1] = pBitmap->GetPalette()[1];
49 } else {
50 pPalette[0] = 0;
51 pPalette[1] = 0xffffff;
52 }
53 }
54 }
55 result.ReleaseBuffer(len);
56 return result;
57 }
58
FX_WindowsDIB_LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData,bool bAlpha)59 RetainPtr<CFX_DIBitmap> FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
60 LPVOID pData,
61 bool bAlpha) {
62 int width = pbmi->bmiHeader.biWidth;
63 int height = pbmi->bmiHeader.biHeight;
64 BOOL bBottomUp = true;
65 if (height < 0) {
66 height = -height;
67 bBottomUp = false;
68 }
69 int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4;
70 auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
71 FXDIB_Format format = bAlpha
72 ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200)
73 : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
74 if (!pBitmap->Create(width, height, format))
75 return nullptr;
76
77 memcpy(pBitmap->GetBuffer(), pData, pitch * height);
78 if (bBottomUp) {
79 std::vector<uint8_t> temp_buf(pitch);
80 int top = 0;
81 int bottom = height - 1;
82 while (top < bottom) {
83 uint8_t* top_ptr = pBitmap->GetBuffer() + top * pitch;
84 uint8_t* bottom_ptr = pBitmap->GetBuffer() + bottom * pitch;
85 memcpy(temp_buf.data(), top_ptr, pitch);
86 memcpy(top_ptr, bottom_ptr, pitch);
87 memcpy(bottom_ptr, temp_buf.data(), pitch);
88 top++;
89 bottom--;
90 }
91 }
92 if (pbmi->bmiHeader.biBitCount == 1) {
93 for (int i = 0; i < 2; i++)
94 pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
95 } else if (pbmi->bmiHeader.biBitCount == 8) {
96 for (int i = 0; i < 256; i++)
97 pBitmap->SetPaletteArgb(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
98 }
99 return pBitmap;
100 }
101
LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData)102 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi,
103 LPVOID pData) {
104 return FX_WindowsDIB_LoadFromBuf(pbmi, pData, false);
105 }
106
GetDDBitmap(const RetainPtr<CFX_DIBitmap> & pBitmap,HDC hDC)107 HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap,
108 HDC hDC) {
109 ByteString info = GetBitmapInfo(pBitmap);
110 return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
111 pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
112 DIB_RGB_COLORS);
113 }
114
GetBitmapSize(HBITMAP hBitmap,int & w,int & h)115 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) {
116 BITMAP bmp;
117 GetObject(hBitmap, sizeof bmp, &bmp);
118 w = bmp.bmWidth;
119 h = bmp.bmHeight;
120 }
121
LoadFromFile(const wchar_t * filename)122 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) {
123 auto* pPlatform =
124 static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
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(nullptr, (wchar_t*)filename,
132 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
133 if (!hBitmap) {
134 return nullptr;
135 }
136 HDC hDC = CreateCompatibleDC(nullptr);
137 int width;
138 int height;
139 GetBitmapSize(hBitmap, width, height);
140 auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
141 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
142 DeleteDC(hDC);
143 return nullptr;
144 }
145 ByteString info = GetBitmapInfo(pDIBitmap);
146 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
147 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
148 DeleteDC(hDC);
149 if (!ret)
150 return nullptr;
151 return pDIBitmap;
152 }
153
LoadFromFile(const char * filename)154 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const char* filename) {
155 return LoadFromFile(WideString::FromDefANSI(filename).c_str());
156 }
157
LoadDIBitmap(WINDIB_Open_Args_ args)158 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
159 auto* pPlatform =
160 static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
161 if (pPlatform->m_GdiplusExt.IsAvailable()) {
162 return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
163 }
164 if (args.flags == WINDIB_OPEN_MEMORY) {
165 return nullptr;
166 }
167 HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name,
168 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
169 if (!hBitmap) {
170 return nullptr;
171 }
172 HDC hDC = CreateCompatibleDC(nullptr);
173 int width, height;
174 GetBitmapSize(hBitmap, width, height);
175 auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
176 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
177 DeleteDC(hDC);
178 return nullptr;
179 }
180 ByteString info = GetBitmapInfo(pDIBitmap);
181 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
182 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
183 DeleteDC(hDC);
184 if (!ret)
185 return nullptr;
186 return pDIBitmap;
187 }
188
CFX_WindowsDIB(HDC hDC,int width,int height)189 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
190 Create(width, height, FXDIB_Rgb, (uint8_t*)1, 0);
191 BITMAPINFOHEADER bmih;
192 memset(&bmih, 0, sizeof bmih);
193 bmih.biSize = sizeof bmih;
194 bmih.biBitCount = 24;
195 bmih.biHeight = -height;
196 bmih.biPlanes = 1;
197 bmih.biWidth = width;
198 LPVOID pData = nullptr;
199 m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pData,
200 nullptr, 0);
201 m_pBuffer.Reset(static_cast<uint8_t*>(pData));
202 m_hMemDC = CreateCompatibleDC(hDC);
203 m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
204 }
205
~CFX_WindowsDIB()206 CFX_WindowsDIB::~CFX_WindowsDIB() {
207 SelectObject(m_hMemDC, m_hOldBitmap);
208 DeleteDC(m_hMemDC);
209 DeleteObject(m_hBitmap);
210 }
211
LoadFromDevice(HDC hDC,int left,int top)212 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
213 ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
214 }
215
SetToDevice(HDC hDC,int left,int top)216 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
217 ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
218 }
219