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