Fix else-after-returns throughout pdfium.
[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 {
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_memset(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 = new CFX_DIBitmap;
63     FXDIB_Format format = bAlpha ? (FXDIB_Format)(pbmi->bmiHeader.biBitCount + 0x200) : (FXDIB_Format)pbmi->bmiHeader.biBitCount;
64     FX_BOOL ret = pBitmap->Create(width, height, format);
65     if (!ret) {
66         delete pBitmap;
67         return NULL;
68     }
69     FXSYS_memcpy(pBitmap->GetBuffer(), pData, pitch * height);
70     if (bBottomUp) {
71         uint8_t* temp_buf = FX_Alloc(uint8_t, pitch);
72         int top = 0, bottom = height - 1;
73         while (top < bottom) {
74             FXSYS_memcpy(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch);
75             FXSYS_memcpy(pBitmap->GetBuffer() + top * pitch, pBitmap->GetBuffer() + bottom * pitch, pitch);
76             FXSYS_memcpy(pBitmap->GetBuffer() + bottom * pitch, temp_buf, pitch);
77             top ++;
78             bottom --;
79         }
80         FX_Free(temp_buf);
81         temp_buf = NULL;
82     }
83     if (pbmi->bmiHeader.biBitCount == 1) {
84         for (int i = 0; i < 2; i ++) {
85             pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000);
86         }
87     } else if (pbmi->bmiHeader.biBitCount == 8) {
88         for (int i = 0; i < 256; i ++) {
89             pBitmap->SetPaletteEntry(i, ((FX_DWORD*)pbmi->bmiColors)[i] | 0xff000000);
90         }
91     }
92     return pBitmap;
93 }
94 CFX_DIBitmap* CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData)
95 {
96     return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, FALSE);
97 }
98 HBITMAP CFX_WindowsDIB::GetDDBitmap(const CFX_DIBitmap* pBitmap, HDC hDC)
99 {
100     CFX_ByteString info = GetBitmapInfo(pBitmap);
101     HBITMAP hBitmap = NULL;
102     hBitmap = CreateDIBitmap(hDC, (BITMAPINFOHEADER*)info.c_str(), CBM_INIT,
103         pBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
104     return hBitmap;
105 }
106 void GetBitmapSize(HBITMAP hBitmap, int& w, int& h)
107 {
108     BITMAP bmp;
109     GetObject(hBitmap, sizeof bmp, &bmp);
110     w = bmp.bmWidth;
111     h = bmp.bmHeight;
112 }
113 CFX_DIBitmap* CFX_WindowsDIB::LoadFromFile(const FX_WCHAR* filename)
114 {
115     CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
116     if (pPlatform->m_GdiplusExt.IsAvailable()) {
117         WINDIB_Open_Args_ args;
118         args.flags = WINDIB_OPEN_PATHNAME;
119         args.path_name = filename;
120         return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
121     }
122     HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
123     if (hBitmap == NULL) {
124         return NULL;
125     }
126     HDC hDC = CreateCompatibleDC(NULL);
127     int width, height;
128     GetBitmapSize(hBitmap, width, height);
129     CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
130     if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
131         delete pDIBitmap;
132         DeleteDC(hDC);
133         return NULL;
134     }
135     CFX_ByteString info = GetBitmapInfo(pDIBitmap);
136     int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
137     if (!ret) {
138         delete pDIBitmap;
139         pDIBitmap = NULL;
140     }
141     DeleteDC(hDC);
142     return pDIBitmap;
143 }
144 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args)
145 {
146     CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
147     if (pPlatform->m_GdiplusExt.IsAvailable()) {
148         return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
149     }
150     if (args.flags == WINDIB_OPEN_MEMORY) {
151         return NULL;
152     }
153     HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)args.path_name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
154     if (hBitmap == NULL) {
155         return NULL;
156     }
157     HDC hDC = CreateCompatibleDC(NULL);
158     int width, height;
159     GetBitmapSize(hBitmap, width, height);
160     CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
161     if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
162         delete pDIBitmap;
163         DeleteDC(hDC);
164         return NULL;
165     }
166     CFX_ByteString info = GetBitmapInfo(pDIBitmap);
167     int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
168     if (!ret) {
169         delete pDIBitmap;
170         pDIBitmap = NULL;
171     }
172     DeleteDC(hDC);
173     return pDIBitmap;
174 }
175 CFX_DIBitmap* CFX_WindowsDIB::LoadFromDDB(HDC hDC, HBITMAP hBitmap, FX_DWORD* pPalette, FX_DWORD palsize)
176 {
177     FX_BOOL bCreatedDC = hDC == NULL;
178     if (hDC == NULL) {
179         hDC = CreateCompatibleDC(NULL);
180     }
181     BITMAPINFOHEADER bmih;
182     FXSYS_memset(&bmih, 0, sizeof bmih);
183     bmih.biSize = sizeof bmih;
184     GetDIBits(hDC, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
185     int width = bmih.biWidth;
186     int height = abs(bmih.biHeight);
187     bmih.biHeight = -height;
188     bmih.biCompression = BI_RGB;
189     CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
190     int ret = 0;
191     if (bmih.biBitCount == 1 || bmih.biBitCount == 8) {
192         int size = sizeof (BITMAPINFOHEADER) + 8;
193         if (bmih.biBitCount == 8) {
194             size += sizeof (FX_DWORD) * 254;
195         }
196         BITMAPINFO* pbmih = (BITMAPINFO*)FX_Alloc(uint8_t, size);
197         pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
198         pbmih->bmiHeader.biBitCount = bmih.biBitCount;
199         pbmih->bmiHeader.biCompression = BI_RGB;
200         pbmih->bmiHeader.biHeight = -height;
201         pbmih->bmiHeader.biPlanes = 1;
202         pbmih->bmiHeader.biWidth = bmih.biWidth;
203         if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1 ? FXDIB_1bppRgb : FXDIB_8bppRgb)) {
204             delete pDIBitmap;
205             FX_Free(pbmih);
206             if (bCreatedDC) {
207                 DeleteDC(hDC);
208             }
209             return NULL;
210         }
211         ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)pbmih, DIB_RGB_COLORS);
212         FX_Free(pbmih);
213         pbmih = NULL;
214         pDIBitmap->CopyPalette(pPalette, palsize);
215     } else {
216         if (bmih.biBitCount <= 24) {
217             bmih.biBitCount = 24;
218         } else {
219             bmih.biBitCount = 32;
220         }
221         if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) {
222             delete pDIBitmap;
223             if (bCreatedDC) {
224                 DeleteDC(hDC);
225             }
226             return NULL;
227         }
228         ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
229         if (ret != 0 && bmih.biBitCount == 32) {
230             int pitch = pDIBitmap->GetPitch();
231             for (int row = 0; row < height; row ++) {
232                 uint8_t* dest_scan = (uint8_t*)(pDIBitmap->GetBuffer() + row * pitch);
233                 for (int col = 0; col < width; col++) {
234                     dest_scan[3] = 255;
235                     dest_scan += 4;
236                 }
237             }
238         }
239     }
240     if (ret == 0) {
241         delete pDIBitmap;
242         pDIBitmap = NULL;
243     }
244     if (bCreatedDC) {
245         DeleteDC(hDC);
246     }
247     return pDIBitmap;
248 }
249 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height)
250 {
251     Create(width, height, FXDIB_Rgb, (uint8_t*)1);
252     BITMAPINFOHEADER bmih;
253     FXSYS_memset(&bmih, 0, sizeof bmih);
254     bmih.biSize = sizeof bmih;
255     bmih.biBitCount = 24;
256     bmih.biHeight = -height;
257     bmih.biPlanes = 1;
258     bmih.biWidth = width;
259     m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (LPVOID*)&m_pBuffer, NULL, 0);
260     m_hMemDC = CreateCompatibleDC(hDC);
261     m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
262 }
263 CFX_WindowsDIB::~CFX_WindowsDIB()
264 {
265     SelectObject(m_hMemDC, m_hOldBitmap);
266     DeleteDC(m_hMemDC);
267     DeleteObject(m_hBitmap);
268 }
269 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top)
270 {
271     ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
272 }
273 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top)
274 {
275     ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
276 }
277 #endif