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 CFX_DIBitmap * pBitmap)14 CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) {
15 CFX_ByteString result;
16 int len = sizeof(BITMAPINFOHEADER);
17 if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) {
18 len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());
19 }
20 BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)result.GetBuffer(len);
21 FXSYS_memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
22 pbmih->biSize = sizeof(BITMAPINFOHEADER);
23 pbmih->biBitCount = pBitmap->GetBPP();
24 pbmih->biCompression = BI_RGB;
25 pbmih->biHeight = -(int)pBitmap->GetHeight();
26 pbmih->biPlanes = 1;
27 pbmih->biWidth = pBitmap->GetWidth();
28 if (pBitmap->GetBPP() == 8) {
29 uint32_t* pPalette = (uint32_t*)(pbmih + 1);
30 if (pBitmap->GetPalette()) {
31 for (int i = 0; i < 256; i++) {
32 pPalette[i] = pBitmap->GetPalette()[i];
33 }
34 } else {
35 for (int i = 0; i < 256; i++) {
36 pPalette[i] = i * 0x010101;
37 }
38 }
39 }
40 if (pBitmap->GetBPP() == 1) {
41 uint32_t* pPalette = (uint32_t*)(pbmih + 1);
42 if (pBitmap->GetPalette()) {
43 pPalette[0] = pBitmap->GetPalette()[0];
44 pPalette[1] = pBitmap->GetPalette()[1];
45 } else {
46 pPalette[0] = 0;
47 pPalette[1] = 0xffffff;
48 }
49 }
50 result.ReleaseBuffer(len);
51 return result;
52 }
53
_FX_WindowsDIB_LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData,bool bAlpha)54 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
55 LPVOID pData,
56 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 bool ret = pBitmap->Create(width, height, format);
70 if (!ret) {
71 delete pBitmap;
72 return nullptr;
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 = nullptr;
88 }
89 if (pbmi->bmiHeader.biBitCount == 1) {
90 for (int i = 0; i < 2; i++) {
91 pBitmap->SetPaletteEntry(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
92 }
93 } else if (pbmi->bmiHeader.biBitCount == 8) {
94 for (int i = 0; i < 256; i++) {
95 pBitmap->SetPaletteEntry(i, ((uint32_t*)pbmi->bmiColors)[i] | 0xff000000);
96 }
97 }
98 return pBitmap;
99 }
100
LoadFromBuf(BITMAPINFO * pbmi,LPVOID pData)101 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) {
102 return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, false);
103 }
104
GetDDBitmap(const CFX_DIBitmap * pBitmap,HDC hDC)105 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) {
106 CFX_ByteString info = GetBitmapInfo(pBitmap);
107 return CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
108 pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
109 DIB_RGB_COLORS);
110 }
111
GetBitmapSize(HBITMAP hBitmap,int & w,int & h)112 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) {
113 BITMAP bmp;
114 GetObject(hBitmap, sizeof bmp, &bmp);
115 w = bmp.bmWidth;
116 h = bmp.bmHeight;
117 }
118
LoadFromFile(const FX_WCHAR * filename)119 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) {
120 CWin32Platform* pPlatform =
121 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
122 if (pPlatform->m_GdiplusExt.IsAvailable()) {
123 WINDIB_Open_Args_ args;
124 args.flags = WINDIB_OPEN_PATHNAME;
125 args.path_name = filename;
126 return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
127 }
128 HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)filename,
129 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
130 if (!hBitmap) {
131 return nullptr;
132 }
133 HDC hDC = CreateCompatibleDC(nullptr);
134 int width, height;
135 GetBitmapSize(hBitmap, width, height);
136 CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
137 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
138 delete pDIBitmap;
139 DeleteDC(hDC);
140 return nullptr;
141 }
142 CFX_ByteString info = GetBitmapInfo(pDIBitmap);
143 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
144 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
145 if (!ret) {
146 delete pDIBitmap;
147 pDIBitmap = nullptr;
148 }
149 DeleteDC(hDC);
150 return pDIBitmap;
151 }
152
LoadFromFile(const FX_CHAR * filename)153 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_CHAR* filename) {
154 return LoadFromFile(CFX_WideString::FromLocal(filename).c_str());
155 }
156
LoadDIBitmap(WINDIB_Open_Args_ args)157 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
158 CWin32Platform* pPlatform =
159 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
160 if (pPlatform->m_GdiplusExt.IsAvailable()) {
161 return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
162 }
163 if (args.flags == WINDIB_OPEN_MEMORY) {
164 return nullptr;
165 }
166 HBITMAP hBitmap = (HBITMAP)LoadImageW(nullptr, (wchar_t*)args.path_name,
167 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
168 if (!hBitmap) {
169 return nullptr;
170 }
171 HDC hDC = CreateCompatibleDC(nullptr);
172 int width, height;
173 GetBitmapSize(hBitmap, width, height);
174 CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
175 if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
176 delete pDIBitmap;
177 DeleteDC(hDC);
178 return nullptr;
179 }
180 CFX_ByteString info = GetBitmapInfo(pDIBitmap);
181 int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
182 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
183 if (!ret) {
184 delete pDIBitmap;
185 pDIBitmap = nullptr;
186 }
187 DeleteDC(hDC);
188 return pDIBitmap;
189 }
190
CFX_WindowsDIB(HDC hDC,int width,int height)191 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
192 Create(width, height, FXDIB_Rgb, (uint8_t*)1);
193 BITMAPINFOHEADER bmih;
194 FXSYS_memset(&bmih, 0, sizeof bmih);
195 bmih.biSize = sizeof bmih;
196 bmih.biBitCount = 24;
197 bmih.biHeight = -height;
198 bmih.biPlanes = 1;
199 bmih.biWidth = width;
200 m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
201 (LPVOID*)&m_pBuffer, nullptr, 0);
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