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 = 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         FXSYS_memset32(pbmih, 0, sizeof (BITMAPINFOHEADER));
    228         pbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    229         pbmih->bmiHeader.biBitCount = bmih.biBitCount;
    230         pbmih->bmiHeader.biCompression = BI_RGB;
    231         pbmih->bmiHeader.biHeight = -height;
    232         pbmih->bmiHeader.biPlanes = 1;
    233         pbmih->bmiHeader.biWidth = bmih.biWidth;
    234         if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 1 ? FXDIB_1bppRgb : FXDIB_8bppRgb)) {
    235             delete pDIBitmap;
    236             FX_Free(pbmih);
    237             if (bCreatedDC) {
    238                 DeleteDC(hDC);
    239             }
    240             return NULL;
    241         }
    242         ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)pbmih, DIB_RGB_COLORS);
    243         FX_Free(pbmih);
    244         pbmih = NULL;
    245         pDIBitmap->CopyPalette(pPalette, palsize);
    246     } else {
    247         if (bmih.biBitCount <= 24) {
    248             bmih.biBitCount = 24;
    249         } else {
    250             bmih.biBitCount = 32;
    251         }
    252         if (!pDIBitmap->Create(bmih.biWidth, height, bmih.biBitCount == 24 ? FXDIB_Rgb : FXDIB_Rgb32)) {
    253             delete pDIBitmap;
    254             if (bCreatedDC) {
    255                 DeleteDC(hDC);
    256             }
    257             return NULL;
    258         }
    259         ret = GetDIBits(hDC, hBitmap, 0, height, pDIBitmap->GetBuffer(), (BITMAPINFO*)&bmih, DIB_RGB_COLORS);
    260         if (ret != 0 && bmih.biBitCount == 32) {
    261             int pitch = pDIBitmap->GetPitch();
    262             for (int row = 0; row < height; row ++) {
    263                 FX_BYTE* dest_scan = (FX_BYTE*)(pDIBitmap->GetBuffer() + row * pitch);
    264                 for (int col = 0; col < width; col++) {
    265                     dest_scan[3] = 255;
    266                     dest_scan += 4;
    267                 }
    268             }
    269         }
    270     }
    271     if (ret == 0) {
    272         if (pDIBitmap) {
    273             delete pDIBitmap;
    274         }
    275         pDIBitmap = NULL;
    276     }
    277     if (bCreatedDC) {
    278         DeleteDC(hDC);
    279     }
    280     return pDIBitmap;
    281 }
    282 CFX_WindowsDIB::CFX_WindowsDIB(HDC hDC, int width, int height)
    283 {
    284     Create(width, height, FXDIB_Rgb, (FX_LPBYTE)1);
    285     BITMAPINFOHEADER bmih;
    286     FXSYS_memset32(&bmih, 0, sizeof bmih);
    287     bmih.biSize = sizeof bmih;
    288     bmih.biBitCount = 24;
    289     bmih.biHeight = -height;
    290     bmih.biPlanes = 1;
    291     bmih.biWidth = width;
    292     m_hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (LPVOID*)&m_pBuffer, NULL, 0);
    293     m_hMemDC = CreateCompatibleDC(hDC);
    294     m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
    295 }
    296 CFX_WindowsDIB::~CFX_WindowsDIB()
    297 {
    298     SelectObject(m_hMemDC, m_hOldBitmap);
    299     DeleteDC(m_hMemDC);
    300     DeleteObject(m_hBitmap);
    301 }
    302 void CFX_WindowsDIB::LoadFromDevice(HDC hDC, int left, int top)
    303 {
    304     ::BitBlt(m_hMemDC, 0, 0, m_Width, m_Height, hDC, left, top, SRCCOPY);
    305 }
    306 void CFX_WindowsDIB::SetToDevice(HDC hDC, int left, int top)
    307 {
    308     ::BitBlt(hDC, left, top, m_Width, m_Height, m_hMemDC, 0, 0, SRCCOPY);
    309 }
    310 #endif
    311