Clean up CPDF_AnnotList.
[pdfium.git] / core / src / fxge / win32 / fx_win32_dib.cpp
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 "../../../include/fxge/fx_ge.h"
8 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
9 #include <windows.h>
10 #include "../../../include/fxge/fx_ge_win32.h"
11 #include "win32_int.h"
12 CFX_ByteString CFX_WindowsDIB::GetBitmapInfo(const CFX_DIBitmap* pBitmap) {
13   CFX_ByteString result;
14   int len = sizeof(BITMAPINFOHEADER);
15   if (pBitmap->GetBPP() == 1 || pBitmap->GetBPP() == 8) {
16     len += sizeof(DWORD) * (int)(1 << pBitmap->GetBPP());
17   }
18   BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)result.GetBuffer(len);
19   FXSYS_memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
20   pbmih->biSize = sizeof(BITMAPINFOHEADER);
21   pbmih->biBitCount = pBitmap->GetBPP();
22   pbmih->biCompression = BI_RGB;
23   pbmih->biHeight = -(int)pBitmap->GetHeight();
24   pbmih->biPlanes = 1;
25   pbmih->biWidth = pBitmap->GetWidth();
26   if (pBitmap->GetBPP() == 8) {
27     FX_DWORD* pPalette = (FX_DWORD*)(pbmih + 1);
28     if (pBitmap->GetPalette() == NULL) {
29       for (int i = 0; i < 256; i++) {
30         pPalette[i] = i * 0x010101;
31       }
32     } else {
33       for (int i = 0; i < 256; i++) {
34         pPalette[i] = pBitmap->GetPalette()[i];
35       }
36     }
37   }
38   if (pBitmap->GetBPP() == 1) {
39     FX_DWORD* pPalette = (FX_DWORD*)(pbmih + 1);
40     if (pBitmap->GetPalette() == NULL) {
41       pPalette[0] = 0;
42       pPalette[1] = 0xffffff;
43     } else {
44       pPalette[0] = pBitmap->GetPalette()[0];
45       pPalette[1] = pBitmap->GetPalette()[1];
46     }
47   }
48   result.ReleaseBuffer(len);
49   return result;
50 }
51 CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi,
52                                          LPVOID pData,
53                                          FX_BOOL bAlpha) {
54   int width = pbmi->bmiHeader.biWidth;
55   int height = pbmi->bmiHeader.biHeight;
56   BOOL bBottomUp = TRUE;
57   if (height < 0) {
58     height = -height;
59     bBottomUp = FALSE;
60   }
61   int pitch = (width * pbmi->bmiHeader.biBitCount + 31) / 32 * 4;
62   CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
63   FXDIB_Format format = bAlpha
64                             ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200)
65                             : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
66   FX_BOOL ret = pBitmap->Create(width, height, format);
67   if (!ret) {
68     delete pBitmap;
69     return NULL;
70   }
71   FXSYS_memcpy(pBitmap->GetBuffer(), pData, pitch * height);
72   if (bBottomUp) {
73     uint8_t* temp_buf = FX_Alloc(uint8_t, pitch);
74     int top = 0, bottom = height - 1;
75     while (top < bottom) {
76       FXSYS_memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch);
77       FXSYS_memcpy(pBitmap->GetBuffer() + top * pitch,
78                    pBitmap->GetBuffer() + bottom * pitch, pitch);
79       FXSYS_memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch);
80       top++;
81       bottom--;
82     }
83     FX_Free(temp_buf);
84     temp_buf = NULL;
85   }
86   if (pbmi->bmiHeader.biBitCount == 1) {
87     for (int i = 0; i < 2; i++) {
88       pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000);
89     }
90   } else if (pbmi->bmiHeader.biBitCount == 8) {
91     for (int i = 0; i < 256; i++) {
92       pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000);
93     }
94   }
95   return pBitmap;
96 }
97 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) {
98   return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE);
99 }
100 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC) {
101   CFX_ByteString info = GetBitmapInfo(pBitmap);
102   HBITMAP hBitmap = NULL;
103   hBitmap = CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
104                            pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(),
105                            DIB_RGB_COLORS);
106   return hBitmap;
107 }
108 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h) {
109   BITMAP bmp;
110   GetObject(hBitmap, sizeof bmp, &bmp);
111   w = bmp.bmWidth;
112   h = bmp.bmHeight;
113 }
114 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename) {
115   CWin32Platform* pPlatform =
116       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
117   if (pPlatform->m_GdiplusExt.IsAvailable()) {
118     WINDIB_Open_Args_ args;
119     args.flags = WINDIB_OPEN_PATHNAME;
120     args.path_name = filename;
121     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
122   }
123   HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)filename, IMAGE_BITMAP,
124                                         0, 0, LR_LOADFROMFILE);
125   if (hBitmap == NULL) {
126     return NULL;
127   }
128   HDC hDC = CreateCompatibleDC(NULL);
129   int width, height;
130   GetBitmapSize(hBitmap, width, height);
131   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
132   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
133     delete pDIBitmap;
134     DeleteDC(hDC);
135     return NULL;
136   }
137   CFX_ByteString info = GetBitmapInfo(pDIBitmap);
138   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
139                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
140   if (!ret) {
141     delete pDIBitmap;
142     pDIBitmap = NULL;
143   }
144   DeleteDC(hDC);
145   return pDIBitmap;
146 }
147 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
148   CWin32Platform* pPlatform =
149       (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
150   if (pPlatform->m_GdiplusExt.IsAvailable()) {
151     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
152   }
153   if (args.flags == WINDIB_OPEN_MEMORY) {
154     return NULL;
155   }
156   HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)args.path_name,
157                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
158   if (hBitmap == NULL) {
159     return NULL;
160   }
161   HDC hDC = CreateCompatibleDC(NULL);
162   int width, height;
163   GetBitmapSize(hBitmap, width, height);
164   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
165   if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
166     delete pDIBitmap;
167     DeleteDC(hDC);
168     return NULL;
169   }
170   CFX_ByteString info = GetBitmapInfo(pDIBitmap);
171   int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
172                       (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
173   if (!ret) {
174     delete pDIBitmap;
175     pDIBitmap = NULL;
176   }
177   DeleteDC(hDC);
178   return pDIBitmap;
179 }
180 CFX_DIBitmap* CFX_WindowsDIB::LoadFromDDB(HDC hDC,
181                                           HBITMAP hBitmap,
182                                           FX_DWORD* pPalette,
183                                           FX_DWORD palsize) {
184   FX_BOOL bCreatedDC = hDC == NULL;
185   if (hDC == NULL) {
186     hDC = CreateCompatibleDC(NULL);
187   }
188   BITMAPINFOHEADER bmih;
189   FXSYS_memset(&bmih, 0, sizeof bmih);
190   bmih.biSize = sizeof bmih;
191   GetDIBits(hDC, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
192   int width = bmih.biWidth;
193   int height = abs(bmih.biHeight);
194   bmih.biHeight = -height;
195   bmih.biCompression = BI_RGB;
196   CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
197   int ret = 0;
198   if (bmih.biBitCount == 1 || bmih.biBitCount == 8) {
199     int size = sizeof(BITMAPINFOHEADER) + 8;
200     if (bmih.biBitCount == 8) {
201       size += sizeof(FX_DWORD) * 254;
202     }
203     BITMAPINFO* pbmih = (BITMAPINFO*)FX_Alloc(uint8_t, size);
204     pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
205     pbmih->bmiHeader.biBitCount = bmih.biBitCount;
206     pbmih->bmiHeader.biCompression = BI_RGB;
207     pbmih->bmiHeader.biHeight = -height;
208     pbmih->bmiHeader.biPlanes = 1;
209     pbmih->bmiHeader.biWidth = bmih.biWidth;
210     if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1
211                                                      ? FXDIB_1bppRgb
212                                                      : FXDIB_8bppRgb)) {
213       delete pDIBitmap;
214       FX_Free(pbmih);
215       if (bCreatedDC) {
216         DeleteDC(hDC);
217       }
218       return NULL;
219     }
220     ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
221                     (BITMAPINFO*)pbmih, DIB_RGB_COLORS);
222     FX_Free(pbmih);
223     pbmih = NULL;
224     pDIBitmap->CopyPalette(pPalette, palsize);
225   } else {
226     if (bmih.biBitCount <= 24) {
227       bmih.biBitCount = 24;
228     } else {
229       bmih.biBitCount = 32;
230     }
231     if (!pDIBitmap->Create(bmih.biWidth, height,
232                            bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) {
233       delete pDIBitmap;
234       if (bCreatedDC) {
235         DeleteDC(hDC);
236       }
237       return NULL;
238     }
239     ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(),
240                     (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
241     if (ret != 0 && bmih.biBitCount == 32) {
242       int pitch = pDIBitmap->GetPitch();
243       for (int row = 0; row < height; row++) {
244         uint8_t* dest_scan = (uint8_t*)(pDIBitmap->GetBuffer() + row * pitch);
245         for (int col = 0; col < width; col++) {
246           dest_scan[3] = 255;
247           dest_scan += 4;
248         }
249       }
250     }
251   }
252   if (ret == 0) {
253     delete pDIBitmap;
254     pDIBitmap = NULL;
255   }
256   if (bCreatedDC) {
257     DeleteDC(hDC);
258   }
259   return pDIBitmap;
260 }
261 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height) {
262   Create(width, height, FXDIB_Rgb, (uint8_t*)1);
263   BITMAPINFOHEADER bmih;
264   FXSYS_memset(&bmih, 0, sizeof bmih);
265   bmih.biSize = sizeof bmih;
266   bmih.biBitCount = 24;
267   bmih.biHeight = -height;
268   bmih.biPlanes = 1;
269   bmih.biWidth = width;
270   m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
271                                (LPVOID*)&m_pBuffer, NULL, 0);
272   m_hMemDC = CreateCompatibleDC(hDC);
273   m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
274 }
275 CFX_WindowsDIB::~CFX_WindowsDIB() {
276   SelectObject(m_hMemDC, m_hOldBitmap);
277   DeleteDC(m_hMemDC);
278   DeleteObject(m_hBitmap);
279 }
280 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top) {
281   ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
282 }
283 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top) {
284   ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
285 }
286 #endif