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