• 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 <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