Home | History | Annotate | Download | only in win32
      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 = 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_memcpy32(pBitmap->GetBuffer(), pData, pitch * height);
     70     if (bBottomUp) {
     71         FX_LPBYTE temp_buf = FX_Alloc(FX_BYTE, pitch);
     72         int top = 0, bottom = height - 1;
     73         while (top < bottom) {
     74             FXSYS_memcpy32(temp_buf, pBitmap->GetBuffer() + top * pitch, pitch);
     75             FXSYS_memcpy32(pBitmap->GetBuffer() + top * pitch, pBitmap->GetBuffer() + bottom * pitch, pitch);
     76             FXSYS_memcpy32(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(FX_LPCWSTR 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         if (pDIBitmap) {
    139             delete pDIBitmap;
    140         }
    141         pDIBitmap = NULL;
    142     }
    143     DeleteDC(hDC);
    144     return pDIBitmap;
    145 }
    146 CFX_DIBitmap* CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args)
    147 {
    148     CWin32Platform* pPlatform = (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
    149     if (pPlatform->m_GdiplusExt.IsAvailable()) {
    150         return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
    151     } else if (args.flags == WINDIB_OPEN_MEMORY) {
    152         return NULL;
    153     }
    154     HBITMAP hBitmap = (HBITMAP)LoadImageW(NULL, (wchar_t*)args.path_name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    155     if (hBitmap == NULL) {
    156         return NULL;
    157     }
    158     HDC hDC = CreateCompatibleDC(NULL);
    159     int width, height;
    160     GetBitmapSize(hBitmap, width, height);
    161     CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    162     if (!pDIBitmap->Create(width, height, FXDIB_Rgb)) {
    163         delete pDIBitmap;
    164         DeleteDC(hDC);
    165         return NULL;
    166     }
    167     CFX_ByteString info = GetBitmapInfo(pDIBitmap);
    168     int ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
    169     if (!ret) {
    170         if (pDIBitmap) {
    171             delete pDIBitmap;
    172         }
    173         pDIBitmap = NULL;
    174     }
    175     DeleteDC(hDC);
    176     return pDIBitmap;
    177 }
    178 CFX_DIBitmap* CFX_WindowsDIB::LoadFromDDB(HDC hDC, HBITMAP hBitmap, FX_DWORD* pPalette, FX_DWORD palsize)
    179 {
    180     FX_BOOL bCreatedDC = hDC == NULL;
    181     if (hDC == NULL) {
    182         hDC = CreateCompatibleDC(NULL);
    183     }
    184     BITMAPINFOHEADER bmih;
    185     FXSYS_memset32(&bmih, 0, sizeof bmih);
    186     bmih.biSize = sizeof bmih;
    187     GetDIBits(hDC, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
    188     int width = bmih.biWidth;
    189     int height = abs(bmih.biHeight);
    190     bmih.biHeight = -height;
    191     bmih.biCompression = BI_RGB;
    192     CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap;
    193     int ret = 0;
    194     if (bmih.biBitCount == 1 || bmih.biBitCount == 8) {
    195         int size = sizeof (BITMAPINFOHEADER) + 8;
    196         if (bmih.biBitCount == 8) {
    197             size += sizeof (FX_DWORD) * 254;
    198         }
    199         BITMAPINFO* pbmih = (BITMAPINFO*)FX_Alloc(FX_BYTE, size);
    200         pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    201         pbmih->bmiHeader.biBitCount = bmih.biBitCount;
    202         pbmih->bmiHeader.biCompression = BI_RGB;
    203         pbmih->bmiHeader.biHeight = -height;
    204         pbmih->bmiHeader.biPlanes = 1;
    205         pbmih->bmiHeader.biWidth = bmih.biWidth;
    206         if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1 ? FXDIB_1bppRgb : FXDIB_8bppRgb)) {
    207             delete pDIBitmap;
    208             FX_Free(pbmih);
    209             if (bCreatedDC) {
    210                 DeleteDC(hDC);
    211             }
    212             return NULL;
    213         }
    214         ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)pbmih, DIB_RGB_COLORS);
    215         FX_Free(pbmih);
    216         pbmih = NULL;
    217         pDIBitmap->CopyPalette(pPalette, palsize);
    218     } else {
    219         if (bmih.biBitCount <= 24) {
    220             bmih.biBitCount = 24;
    221         } else {
    222             bmih.biBitCount = 32;
    223         }
    224         if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) {
    225             delete pDIBitmap;
    226             if (bCreatedDC) {
    227                 DeleteDC(hDC);
    228             }
    229             return NULL;
    230         }
    231         ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
    232         if (ret != 0 && bmih.biBitCount == 32) {
    233             int pitch = pDIBitmap->GetPitch();
    234             for (int row = 0; row < height; row ++) {
    235                 FX_BYTE* dest_scan = (FX_BYTE*)(pDIBitmap->GetBuffer() + row * pitch);
    236                 for (int col = 0; col < width; col++) {
    237                     dest_scan[3] = 255;
    238                     dest_scan += 4;
    239                 }
    240             }
    241         }
    242     }
    243     if (ret == 0) {
    244         if (pDIBitmap) {
    245             delete pDIBitmap;
    246         }
    247         pDIBitmap = NULL;
    248     }
    249     if (bCreatedDC) {
    250         DeleteDC(hDC);
    251     }
    252     return pDIBitmap;
    253 }
    254 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height)
    255 {
    256     Create(width, height, FXDIB_Rgb, (FX_LPBYTE)1);
    257     BITMAPINFOHEADER bmih;
    258     FXSYS_memset32(&bmih, 0, sizeof bmih);
    259     bmih.biSize = sizeof bmih;
    260     bmih.biBitCount = 24;
    261     bmih.biHeight = -height;
    262     bmih.biPlanes = 1;
    263     bmih.biWidth = width;
    264     m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (LPVOID*)&m_pBuffer, NULL, 0);
    265     m_hMemDC = CreateCompatibleDC(hDC);
    266     m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
    267 }
    268 CFX_WindowsDIB::~CFX_WindowsDIB()
    269 {
    270     SelectObject(m_hMemDC, m_hOldBitmap);
    271     DeleteDC(m_hMemDC);
    272     DeleteObject(m_hBitmap);
    273 }
    274 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top)
    275 {
    276     ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
    277 }
    278 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top)
    279 {
    280     ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
    281 }
    282 #endif
    283