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