X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/adf9e09990c79a3645eaa1f69b44d852c11a72f0..eed9e4791274d68ea1fb0c556bf3199ecf88a7d9:/src/msw/bitmap.cpp diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index 7df1437372..6a2c74a221 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -17,7 +17,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "bitmap.h" #endif @@ -43,14 +43,16 @@ #include "wx/msw/private.h" #include "wx/log.h" -#if !defined(__WXMICROWIN__) +#if wxUSE_WXDIB #include "wx/msw/dib.h" #endif #include "wx/image.h" #include "wx/xpmdecod.h" +#ifdef wxHAVE_RAW_BITMAP #include "wx/rawbmp.h" +#endif // missing from mingw32 header #ifndef CLR_INVALID @@ -100,10 +102,12 @@ public: wxDC *m_selectedInto; #endif // __WXDEBUG__ +#if wxUSE_WXDIB // when GetRawData() is called for a DDB we need to convert it to a DIB // first to be able to provide direct access to it and we cache that DIB // here and convert it back to DDB when UngetRawData() is called wxDIB *m_dib; +#endif // true if we have alpha transparency info and can be drawn using // AlphaBlend() @@ -139,6 +143,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject) // decide whether we should create a DIB or a DDB for the given parameters static bool wxShouldCreateDIB(int w, int h, int d, WXHDC hdc) { +#if wxUSE_WXDIB // here is the logic: // // (a) if hdc is specified, the caller explicitly wants DDB @@ -158,6 +163,9 @@ static bool wxShouldCreateDIB(int w, int h, int d, WXHDC hdc) (d >= 24 || (d == -1 && wxDIB::GetLineSize(w, wxDisplayDepth())*h > 16*1024*1024)); +#else + return FALSE; +#endif } // ---------------------------------------------------------------------------- @@ -172,7 +180,9 @@ wxBitmapRefData::wxBitmapRefData() m_bitmapMask = NULL; m_hBitmap = (WXHBITMAP) NULL; +#if wxUSE_WXDIB m_dib = NULL; +#endif m_isDIB = m_hasAlpha = FALSE; @@ -183,7 +193,9 @@ void wxBitmapRefData::Free() wxASSERT_MSG( !m_selectedInto, wxT("deleting bitmap still selected into wxMemoryDC") ); +#if wxUSE_WXDIB wxASSERT_MSG( !m_dib, _T("forgot to call wxBitmap::UngetRawData()!") ); +#endif if ( m_hBitmap) { @@ -216,7 +228,7 @@ wxGDIImageRefData *wxBitmap::CreateData() const bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) { -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // it may be either HICON or HCURSOR HICON hicon = (HICON)icon.GetHandle(); @@ -248,10 +260,6 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) // delete the old one now as we don't need it any more ::DeleteObject(iconInfo.hbmMask); -#if WXWIN_COMPATIBILITY_2 - refData->m_ok = TRUE; -#endif // WXWIN_COMPATIBILITY_2 - return TRUE; #else return FALSE; @@ -310,16 +318,13 @@ bool wxBitmap::CopyFromIcon(const wxIcon& icon) refData->m_hBitmap = (WXHBITMAP)hbitmap; -#if WXWIN_COMPATIBILITY_2 - refData->m_ok = TRUE; -#endif // WXWIN_COMPATIBILITY_2 - return TRUE; #else // Win32 return CopyFromIconOrCursor(icon); #endif // Win16/Win32 } +#if wxUSE_WXDIB bool wxBitmap::CopyFromDIB(const wxDIB& dib) { wxCHECK_MSG( dib.IsOk(), FALSE, _T("invalid DIB in CopyFromDIB") ); @@ -351,6 +356,7 @@ bool wxBitmap::CopyFromDIB(const wxDIB& dib) return TRUE; } +#endif wxBitmap::~wxBitmap() { @@ -423,7 +429,11 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) } // Create from XPM data +#if wxUSE_IMAGE && wxUSE_XPM bool wxBitmap::CreateFromXpm(const char **data) +#else +bool wxBitmap::CreateFromXpm(const char **WXUNUSED(data)) +#endif { #if wxUSE_IMAGE && wxUSE_XPM Init(); @@ -492,6 +502,7 @@ bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc) HBITMAP hbmp; +#if wxUSE_WXDIB if ( wxShouldCreateDIB(w, h, d, hdc) ) { if ( d == -1 ) @@ -511,11 +522,8 @@ bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc) GetBitmapData()->m_depth = d; } else // create a DDB +#endif { - if ( d == -1 ) - d = wxDisplayDepth(); - - GetBitmapData()->m_depth = d; #ifndef __WXMICROWIN__ if ( d > 0 ) @@ -542,10 +550,6 @@ bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc) SetHBITMAP((WXHBITMAP)hbmp); -#if WXWIN_COMPATIBILITY_2 - GetBitmapData()->m_ok = hbmp != 0; -#endif // WXWIN_COMPATIBILITY_2 - return Ok(); } @@ -670,11 +674,6 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, const wxDC& dc) SetPalette(image.GetPalette()); #endif // wxUSE_PALETTE -#if WXWIN_COMPATIBILITY_2 - // check the wxBitmap object - GetBitmapData()->SetOk(); -#endif // WXWIN_COMPATIBILITY_2 - return TRUE; } @@ -762,6 +761,7 @@ bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc) bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc ) { +#if wxUSE_WXDIB wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") ); UnRef(); @@ -788,7 +788,9 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc ) HBITMAP hbitmap; // are we going to use DIB? - if ( wxShouldCreateDIB(w, h, depth, hdc) ) + // + // NB: DDBs don't support alpha so if we have alpha channel we must use DIB + if ( image.HasAlpha() || wxShouldCreateDIB(w, h, depth, hdc) ) { // don't delete the DIB section in dib object dtor hbitmap = dib.Detach(); @@ -806,10 +808,6 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc ) // validate this object SetHBITMAP((WXHBITMAP)hbitmap); -#if WXWIN_COMPATIBILITY_2 - m_refData->m_ok = TRUE; -#endif // WXWIN_COMPATIBILITY_2 - // finally also set the mask if we have one if ( image.HasMask() ) { @@ -819,10 +817,213 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc ) } return TRUE; +#else + // FIXME: wxWinCE doesn't support wxDIB yet + return FALSE; +#endif } wxImage wxBitmap::ConvertToImage() const { + // FIXME: this is untested code for WinCE, and + // the mask is not yet handled. + // For tips, see: + // http://www.codeproject.com/bitmap/dibsection.asp?print=true + +#ifdef __WXWINCE__ + // the colour used as transparent one in wxImage and the one it is replaced + // with when it really occurs in the bitmap + static const int MASK_RED = 1; + static const int MASK_GREEN = 2; + static const int MASK_BLUE = 3; + static const int MASK_BLUE_REPLACEMENT = 2; + + wxImage image; + + wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") ); + + // create an wxImage object + int width = GetWidth(); + int height = GetHeight(); + image.Create( width, height ); + unsigned char *data = image.GetData(); + if( !data ) + { + wxFAIL_MSG( wxT("could not allocate data for image") ); + return wxNullImage; + } + + // calc the number of bytes per scanline and padding in the DIB + int bytePerLine = width*3; + int sizeDWORD = sizeof( DWORD ); + int lineBoundary = bytePerLine % sizeDWORD; + int padding = 0; + if( lineBoundary > 0 ) + { + padding = sizeDWORD - lineBoundary; + bytePerLine += padding; + } + + // create a DIB header + int headersize = sizeof(BITMAPINFOHEADER); + BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize ); + if( !lpDIBh ) + { + wxFAIL_MSG( wxT("could not allocate data for DIB header") ); + free( data ); + return wxNullImage; + } + // Fill in the DIB header + lpDIBh->bmiHeader.biSize = headersize; + lpDIBh->bmiHeader.biWidth = width; + lpDIBh->bmiHeader.biHeight = -height; + lpDIBh->bmiHeader.biSizeImage = bytePerLine * height; + lpDIBh->bmiHeader.biPlanes = 1; + lpDIBh->bmiHeader.biBitCount = 24; + lpDIBh->bmiHeader.biCompression = BI_RGB; + lpDIBh->bmiHeader.biClrUsed = 0; + // These seem not really needed for our purpose here. + lpDIBh->bmiHeader.biClrImportant = 0; + lpDIBh->bmiHeader.biXPelsPerMeter = 0; + lpDIBh->bmiHeader.biYPelsPerMeter = 0; + + // memory for DIB data is allocated by CreateDIBSection + void *lpBits = NULL; + + // copy data from the device-dependent bitmap to the DIB + HDC hdc = ::GetDC(NULL); + HBITMAP hBitmap = (HBITMAP) GetHBITMAP(); + + HBITMAP hBitmapSection = ::CreateDIBSection( hdc, lpDIBh, DIB_RGB_COLORS, & lpBits, NULL, 0 ); + if (!hBitmapSection) + { + wxFAIL_MSG( wxT("could not create a DIB section") ); + return wxNullImage; + } + + // Copy the image from the DDB to the DIBSection + // Need to copy the supplied bitmap onto the newly created DIBsection + HDC hMemDC = CreateCompatibleDC(hdc); + HDC hCopyDC = CreateCompatibleDC(hdc); + + if (! hMemDC || ! hCopyDC) + { + wxFAIL_MSG( wxT("unable to create compatible DCs") ); + return wxNullImage; + } + +#if 0 + if (m_hPal) + { + SelectPalette(hMemDC, m_hPal, FALSE); RealizePalette(hMemDC); + SelectPalette(hCopyDC, m_hPal, FALSE); RealizePalette(hCopyDC); + } +#endif + + HBITMAP hOldMemBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap); + HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(hCopyDC, hBitmapSection); + + BitBlt(hCopyDC, 0, 0, GetWidth(), GetHeight(), hMemDC, 0, 0, SRCCOPY); + + SelectObject(hMemDC, hOldMemBitmap); + SelectObject(hCopyDC, hOldCopyBitmap); + DeleteDC(hMemDC); + DeleteDC(hCopyDC); + +#if 0 + if (m_hPal) + { + HGDIOBJ hObj = ::GetStockObject(DEFAULT_PALETTE); + SelectObject(hMemDC, hObj); + SelectObject(hCopyDC, hObj); + } +#endif + + ReleaseDC(NULL, hdc); + + // copy DIB data into the wxImage object + int i, j; + unsigned char *ptdata = data; + unsigned char *ptbits = (unsigned char*) lpBits; + for( i=0; iGetMaskBitmap() ) + { + hbitmap = (HBITMAP) GetMask()->GetMaskBitmap(); + // memory DC created, color set, data copied, and memory DC deleted + HDC memdc = ::CreateCompatibleDC( hdc ); + ::SetTextColor( memdc, RGB( 0, 0, 0 ) ); + ::SetBkColor( memdc, RGB( 255, 255, 255 ) ); + ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS ); + ::DeleteDC( memdc ); + ptdata = data; + ptbits = lpBits; + for( i=0; iSetMask(mask); } -#if WXWIN_COMPATIBILITY_2 - -void wxBitmap::SetOk(bool isOk) -{ - EnsureHasData(); - - GetBitmapData()->m_ok = isOk; -} - -#endif // WXWIN_COMPATIBILITY_2 - #if WXWIN_COMPATIBILITY_2_4 void wxBitmap::SetQuality(int WXUNUSED(quality)) @@ -1187,8 +1388,10 @@ void wxBitmap::SetQuality(int WXUNUSED(quality)) // raw bitmap access support // ---------------------------------------------------------------------------- +#ifdef wxHAVE_RAW_BITMAP void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) { +#if wxUSE_WXDIB if ( !Ok() ) { // no bitmap, no data (raw or otherwise) @@ -1255,10 +1458,14 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) } return bits; +#else + return NULL; +#endif } void wxBitmap::UngetRawData(wxPixelDataBase& dataBase) { +#if wxUSE_WXDIB if ( !Ok() ) return; @@ -1303,20 +1510,22 @@ void wxBitmap::UngetRawData(wxPixelDataBase& dataBase) p = rowStart; p.OffsetY(data, 1); } + } - // if we're a DDB we need to convert DIB back to DDB now to make the - // changes made via raw bitmap access effective - if ( !GetBitmapData()->m_isDIB ) - { - wxDIB *dib = GetBitmapData()->m_dib; - GetBitmapData()->m_dib = NULL; + // if we're a DDB we need to convert DIB back to DDB now to make the + // changes made via raw bitmap access effective + if ( !GetBitmapData()->m_isDIB ) + { + wxDIB *dib = GetBitmapData()->m_dib; + GetBitmapData()->m_dib = NULL; - // TODO: convert + // TODO: convert - delete dib; - } + delete dib; } +#endif // wxUSE_WXDIB } +#endif // #ifdef wxHAVE_RAW_BITMAP // ---------------------------------------------------------------------------- // wxMask @@ -1553,14 +1762,11 @@ bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel, HPALETTE hPal, LPBITMAPINFO* lpDIBHeader) { unsigned long i, headerSize; - LPBITMAPINFO lpDIBheader = NULL; - LPPALETTEENTRY lpPe = NULL; - // Allocate space for a DIB header headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY))); - lpDIBheader = (BITMAPINFO *) malloc(headerSize); - lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER)); + LPBITMAPINFO lpDIBheader = (BITMAPINFO *) malloc(headerSize); + LPPALETTEENTRY lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER)); GetPaletteEntries(hPal, 0, 256, lpPe); @@ -1624,6 +1830,7 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, } ICONINFO iconInfo; + wxZeroMemory(iconInfo); iconInfo.fIcon = iconWanted; // do we want an icon or a cursor? if ( !iconWanted ) { @@ -1700,8 +1907,8 @@ HBITMAP wxInvertMask(HBITMAP hbmpMask, int w, int h) wxLogLastError(wxT("CreateBitmap")); } - ::SelectObject(hdcSrc, hbmpMask); - ::SelectObject(hdcDst, hbmpInvMask); + HGDIOBJ srcTmp = ::SelectObject(hdcSrc, hbmpMask); + HGDIOBJ dstTmp = ::SelectObject(hdcDst, hbmpInvMask); if ( !::BitBlt(hdcDst, 0, 0, w, h, hdcSrc, 0, 0, NOTSRCCOPY) ) @@ -1709,6 +1916,10 @@ HBITMAP wxInvertMask(HBITMAP hbmpMask, int w, int h) wxLogLastError(wxT("BitBlt")); } + // Deselect objects + SelectObject(hdcSrc,srcTmp); + SelectObject(hdcDst,dstTmp); + ::DeleteDC(hdcSrc); ::DeleteDC(hdcDst);