X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8ecff18117f8cabc0f515ad81aa4ad265e5e17d3..9eb2347dc3527c32e6a041cba51431bf47c4eac4:/src/msw/bitmap.cpp diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index ebcaac1652..307c67bada 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -24,6 +24,8 @@ #pragma hdrstop #endif +#include "wx/bitmap.h" + #ifndef WX_PRECOMP #include @@ -32,22 +34,20 @@ #include "wx/app.h" #include "wx/palette.h" #include "wx/dcmemory.h" - #include "wx/bitmap.h" #include "wx/icon.h" + #include "wx/log.h" + #include "wx/image.h" #endif #include "wx/msw/private.h" -#include "wx/log.h" +#include "wx/msw/dc.h" #if wxUSE_WXDIB -#include "wx/msw/dib.h" + #include "wx/msw/dib.h" #endif -#include "wx/image.h" -#include "wx/xpmdecod.h" - -#ifdef wxHAVE_RAW_BITMAP -#include "wx/rawbmp.h" +#ifdef wxHAS_RAW_BITMAP + #include "wx/rawbmp.h" #endif // missing from mingw32 header @@ -206,8 +206,13 @@ wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data) m_selectedInto = NULL; #endif - // can't copy the mask as the other bitmap destroys it + // (deep) copy the mask if present m_bitmapMask = NULL; + if (data.m_bitmapMask) + m_bitmapMask = new wxMask(*data.m_bitmapMask); + + // FIXME: we don't copy m_hBitmap currently but we should, see wxBitmap:: + // CloneGDIRefData() wxASSERT_MSG( !data.m_isDIB, _T("can't copy bitmap locked for raw access!") ); @@ -246,35 +251,50 @@ wxGDIImageRefData *wxBitmap::CreateData() const return new wxBitmapRefData; } -wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *dataOrig) const +wxGDIRefData *wxBitmap::CloneGDIRefData(const wxGDIRefData *dataOrig) const { const wxBitmapRefData * data = wx_static_cast(const wxBitmapRefData *, dataOrig); if ( !data ) return NULL; + // FIXME: this method is backwards, it should just create a new + // wxBitmapRefData using its copy ctor but instead it modifies this + // bitmap itself and then returns its m_refData -- which works, of + // course (except in !wxUSE_WXDIB), but is completely illogical wxBitmap *self = wx_const_cast(wxBitmap *, this); + wxBitmapRefData *selfdata; #if wxUSE_WXDIB // copy the other bitmap if ( data->m_hBitmap ) { wxDIB dib((HBITMAP)(data->m_hBitmap)); self->CopyFromDIB(dib); + + selfdata = wx_static_cast(wxBitmapRefData *, m_refData); + selfdata->m_hasAlpha = data->m_hasAlpha; } else #endif // wxUSE_WXDIB { - // don't copy the bitmap data, but do copy the size, depth, ... - self->m_refData = new wxBitmapRefData(*data); + // copy the bitmap data + selfdata = new wxBitmapRefData(*data); + self->m_refData = selfdata; } - return m_refData; -} + // copy also the mask + wxMask * const maskSrc = data->GetMask(); + if ( maskSrc ) + { + selfdata->SetMask(new wxMask(*maskSrc)); + } -#ifdef __WIN32__ + return selfdata; +} -bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) +bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, + wxBitmapTransparency transp) { #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // it may be either HICON or HCURSOR @@ -300,31 +320,51 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor; + switch ( transp ) + { + default: + wxFAIL_MSG( _T("unknown wxBitmapTransparency value") ); + + case wxBitmapTransparency_None: + // nothing to do, refData->m_hasAlpha is false by default + break; + + case wxBitmapTransparency_Auto: #if wxUSE_WXDIB - // If the icon is 32 bits per pixel then it may have alpha channel data, - // although there are some icons that are 32 bpp but have no alpha... So - // convert to a DIB and manually check the 4th byte for each pixel. - BITMAP bm; - if ( ::GetObject(iconInfo.hbmColor, sizeof(BITMAP), (LPVOID)&bm) - && bm.bmBitsPixel == 32) - { - wxDIB dib(iconInfo.hbmColor); - if (dib.IsOk()) - { - unsigned char* pixels = dib.GetData(); - for (int idx=0; idxm_hasAlpha = true; - break; + wxDIB dib(iconInfo.hbmColor); + if (dib.IsOk()) + { + const unsigned char* pixels = dib.GetData(); + for (int idx = 0; idx < w*h*4; idx+=4) + { + if (pixels[idx+3] != 0) + { + // If there is an alpha byte that is non-zero + // then set the alpha flag and stop checking + refData->m_hasAlpha = true; + break; + } + } + } } } - } + break; +#endif // wxUSE_WXDIB + + case wxBitmapTransparency_Always: + refData->m_hasAlpha = true; + break; } -#endif + if ( !refData->m_hasAlpha ) { // the mask returned by GetIconInfo() is inverted compared to the usual @@ -336,32 +376,32 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) ::DeleteObject(iconInfo.hbmMask); return true; -#else +#else // __WXMICROWIN__ || __WXWINCE__ wxUnusedVar(icon); + wxUnusedVar(transp); + return false; -#endif +#endif // !__WXWINCE__/__WXWINCE__ } -#endif // Win32 - -bool wxBitmap::CopyFromCursor(const wxCursor& cursor) +bool wxBitmap::CopyFromCursor(const wxCursor& cursor, wxBitmapTransparency transp) { UnRef(); if ( !cursor.Ok() ) return false; - return CopyFromIconOrCursor(cursor); + return CopyFromIconOrCursor(cursor, transp); } -bool wxBitmap::CopyFromIcon(const wxIcon& icon) +bool wxBitmap::CopyFromIcon(const wxIcon& icon, wxBitmapTransparency transp) { UnRef(); if ( !icon.Ok() ) return false; - return CopyFromIconOrCursor(icon); + return CopyFromIconOrCursor(icon, transp); } #ifndef NEVER_USE_DIB @@ -444,7 +484,7 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) reversed |= (unsigned char)(val & 0x01); val >>= 1; } - *dst++ = reversed; + *dst++ = ~reversed; } if ( padding ) @@ -472,24 +512,6 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) #endif } -// Create from XPM data -bool wxBitmap::CreateFromXpm(const char **data) -{ -#if wxUSE_IMAGE && wxUSE_XPM && wxUSE_WXDIB - wxCHECK_MSG( data != NULL, false, wxT("invalid bitmap data") ); - - wxXPMDecoder decoder; - wxImage img = decoder.ReadData(data); - wxCHECK_MSG( img.Ok(), false, wxT("invalid bitmap data") ); - - *this = wxBitmap(img); - return true; -#else - wxUnusedVar(data); - return false; -#endif -} - wxBitmap::wxBitmap(int w, int h, int d) { (void)Create(w, h, d); @@ -500,14 +522,14 @@ wxBitmap::wxBitmap(int w, int h, const wxDC& dc) (void)Create(w, h, dc); } -wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth) +wxBitmap::wxBitmap(const void* data, wxBitmapType type, int width, int height, int depth) { (void)Create(data, type, width, height, depth); } wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type) { - LoadFile(filename, (int)type); + LoadFile(filename, type); } bool wxBitmap::Create(int width, int height, int depth) @@ -517,9 +539,14 @@ bool wxBitmap::Create(int width, int height, int depth) bool wxBitmap::Create(int width, int height, const wxDC& dc) { - wxCHECK_MSG( dc.Ok(), false, _T("invalid HDC in wxBitmap::Create()") ); + wxCHECK_MSG( dc.IsOk(), false, _T("invalid HDC in wxBitmap::Create()") ); - return DoCreate(width, height, -1, dc.GetHDC()); + const wxMSWDCImpl *impl = wxDynamicCast( dc.GetImpl(), wxMSWDCImpl ); + + if (impl) + return DoCreate(width, height, -1, impl->GetHDC()); + else + return false; } bool wxBitmap::DoCreate(int w, int h, int d, WXHDC hdc) @@ -787,10 +814,15 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth) bool wxBitmap::CreateFromImage(const wxImage& image, const wxDC& dc) { - wxCHECK_MSG( dc.Ok(), false, + wxCHECK_MSG( dc.IsOk(), false, _T("invalid HDC in wxBitmap::CreateFromImage()") ); - return CreateFromImage(image, -1, dc.GetHDC()); + const wxMSWDCImpl *impl = wxDynamicCast( dc.GetImpl(), wxMSWDCImpl ); + + if (impl) + return CreateFromImage(image, -1, impl->GetHDC()); + else + return false; } #if wxUSE_WXDIB @@ -809,14 +841,17 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) if ( !dib.IsOk() ) return false; - if ( depth == -1 ) - depth = dib.GetDepth(); // Get depth from image if none specified + const bool hasAlpha = image.HasAlpha(); + + if (depth == -1) + depth = dib.GetDepth(); // store the bitmap parameters - wxBitmapRefData *refData = new wxBitmapRefData; + wxBitmapRefData * const refData = new wxBitmapRefData; refData->m_width = w; refData->m_height = h; - refData->m_hasAlpha = image.HasAlpha(); + refData->m_hasAlpha = hasAlpha; + refData->m_depth = depth; m_refData = refData; @@ -827,20 +862,17 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) // are we going to use DIB? // // NB: DDBs don't support alpha so if we have alpha channel we must use DIB - if ( image.HasAlpha() || wxShouldCreateDIB(w, h, depth, hdc) ) + if ( hasAlpha || wxShouldCreateDIB(w, h, depth, hdc) ) { // don't delete the DIB section in dib object dtor hbitmap = dib.Detach(); refData->m_isDIB = true; - refData->m_depth = depth; } #ifndef ALWAYS_USE_DIB else // we need to convert DIB to DDB { hbitmap = dib.CreateDDB((HDC)hdc); - - refData->m_depth = depth; } #endif // !ALWAYS_USE_DIB @@ -997,7 +1029,7 @@ wxImage wxBitmap::ConvertToImage() const // loading and saving bitmaps // ---------------------------------------------------------------------------- -bool wxBitmap::LoadFile(const wxString& filename, long type) +bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type) { UnRef(); @@ -1025,7 +1057,7 @@ bool wxBitmap::LoadFile(const wxString& filename, long type) return false; } -bool wxBitmap::Create(void *data, long type, int width, int height, int depth) +bool wxBitmap::Create(const void* data, wxBitmapType type, int width, int height, int depth) { UnRef(); @@ -1044,8 +1076,8 @@ bool wxBitmap::Create(void *data, long type, int width, int height, int depth) } bool wxBitmap::SaveFile(const wxString& filename, - int type, - const wxPalette *palette) + wxBitmapType type, + const wxPalette *palette) const { wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler); @@ -1071,8 +1103,14 @@ bool wxBitmap::SaveFile(const wxString& filename, // ---------------------------------------------------------------------------- // sub bitmap extraction // ---------------------------------------------------------------------------- +wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect ) const +{ + MemoryHDC dcSrc; + SelectInHDC selectSrc(dcSrc, GetHbitmap()); + return GetSubBitmapOfHDC( rect, (WXHDC)dcSrc ); +} -wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const +wxBitmap wxBitmap::GetSubBitmapOfHDC( const wxRect& rect, WXHDC hdc ) const { wxCHECK_MSG( Ok() && (rect.x >= 0) && (rect.y >= 0) && @@ -1093,16 +1131,15 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const dcDst; { - SelectInHDC selectSrc(dcSrc, GetHbitmap()), - selectDst(dcDst, GetHbitmapOf(ret)); + SelectInHDC selectDst(dcDst, GetHbitmapOf(ret)); - if ( !selectSrc || !selectDst ) + if ( !selectDst ) { - wxLogLastError(_T("SelectObjct(hBitmap)")); + wxLogLastError(_T("SelectObject(destBitmap)")); } if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height, - dcSrc, rect.x, rect.y, SRCCOPY) ) + (HDC)hdc, rect.x, rect.y, SRCCOPY) ) { wxLogLastError(_T("BitBlt")); } @@ -1165,15 +1202,6 @@ wxDC *wxBitmap::GetSelectedInto() const #endif -#if WXWIN_COMPATIBILITY_2_4 - -int wxBitmap::GetQuality() const -{ - return 0; -} - -#endif // WXWIN_COMPATIBILITY_2_4 - void wxBitmap::UseAlpha() { if ( GetBitmapData() ) @@ -1217,19 +1245,12 @@ void wxBitmap::SetMask(wxMask *mask) GetBitmapData()->SetMask(mask); } -#if WXWIN_COMPATIBILITY_2_4 - -void wxBitmap::SetQuality(int WXUNUSED(quality)) -{ -} - -#endif // WXWIN_COMPATIBILITY_2_4 - // ---------------------------------------------------------------------------- // raw bitmap access support // ---------------------------------------------------------------------------- -#ifdef wxHAVE_RAW_BITMAP +#ifdef wxHAS_RAW_BITMAP + void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) { #if wxUSE_WXDIB @@ -1335,7 +1356,7 @@ void wxBitmap::UngetRawData(wxPixelDataBase& dataBase) } #endif // wxUSE_WXDIB } -#endif // #ifdef wxHAVE_RAW_BITMAP +#endif // wxHAS_RAW_BITMAP // ---------------------------------------------------------------------------- // wxMask @@ -1346,6 +1367,39 @@ wxMask::wxMask() m_maskBitmap = 0; } +// Copy constructor +wxMask::wxMask(const wxMask &mask) + : wxObject() +{ + BITMAP bmp; + + HDC srcDC = CreateCompatibleDC(0); + HDC destDC = CreateCompatibleDC(0); + + // GetBitmapDimensionEx won't work if SetBitmapDimensionEx wasn't used + // so we'll use GetObject() API here: + if (::GetObject((HGDIOBJ)mask.m_maskBitmap, sizeof(bmp), &bmp) == 0) + { + wxFAIL_MSG(wxT("Cannot retrieve the dimensions of the wxMask to copy")); + return; + } + + // create our HBITMAP + int w = bmp.bmWidth, h = bmp.bmHeight; + m_maskBitmap = (WXHBITMAP)CreateCompatibleBitmap(srcDC, w, h); + + // copy the mask's HBITMAP into our HBITMAP + SelectObject(srcDC, (HBITMAP) mask.m_maskBitmap); + SelectObject(destDC, (HBITMAP) m_maskBitmap); + + BitBlt(destDC, 0, 0, w, h, srcDC, 0, 0, SRCCOPY); + + SelectObject(srcDC, 0); + DeleteDC(srcDC); + SelectObject(destDC, 0); + DeleteDC(destDC); +} + // Construct a mask from a bitmap and a colour indicating // the transparent area wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) @@ -1511,37 +1565,37 @@ bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour) // ---------------------------------------------------------------------------- bool wxBitmapHandler::Create(wxGDIImage *image, - void *data, - long flags, + const void* data, + wxBitmapType type, int width, int height, int depth) { wxBitmap *bitmap = wxDynamicCast(image, wxBitmap); - return bitmap ? Create(bitmap, data, flags, width, height, depth) : false; + return bitmap && Create(bitmap, data, type, width, height, depth); } bool wxBitmapHandler::Load(wxGDIImage *image, const wxString& name, - long flags, + wxBitmapType type, int width, int height) { wxBitmap *bitmap = wxDynamicCast(image, wxBitmap); - return bitmap ? LoadFile(bitmap, name, flags, width, height) : false; + return bitmap && LoadFile(bitmap, name, type, width, height); } -bool wxBitmapHandler::Save(wxGDIImage *image, +bool wxBitmapHandler::Save(const wxGDIImage *image, const wxString& name, - int type) + wxBitmapType type) const { wxBitmap *bitmap = wxDynamicCast(image, wxBitmap); - return bitmap ? SaveFile(bitmap, name, type) : false; + return bitmap && SaveFile(bitmap, name, type); } bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), - void *WXUNUSED(data), - long WXUNUSED(type), + const void* WXUNUSED(data), + wxBitmapType WXUNUSED(type), int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth)) @@ -1551,72 +1605,21 @@ bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), - long WXUNUSED(type), + wxBitmapType WXUNUSED(type), int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight)) { return false; } -bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), +bool wxBitmapHandler::SaveFile(const wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), - int WXUNUSED(type), - const wxPalette *WXUNUSED(palette)) + wxBitmapType WXUNUSED(type), + const wxPalette *WXUNUSED(palette)) const { return false; } -// ---------------------------------------------------------------------------- -// DIB functions -// ---------------------------------------------------------------------------- - -#ifndef __WXMICROWIN__ -bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel, - HPALETTE hPal, LPBITMAPINFO* lpDIBHeader) -{ - unsigned long i, headerSize; - - // Allocate space for a DIB header - headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY))); - LPBITMAPINFO lpDIBheader = (BITMAPINFO *) malloc(headerSize); - LPPALETTEENTRY lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER)); - - GetPaletteEntries(hPal, 0, 256, lpPe); - - memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER)); - - // Fill in the static parts of the DIB header - lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - lpDIBheader->bmiHeader.biWidth = xSize; - lpDIBheader->bmiHeader.biHeight = ySize; - lpDIBheader->bmiHeader.biPlanes = 1; - - // this value must be 1, 4, 8 or 24 so PixelDepth can only be - lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel); - lpDIBheader->bmiHeader.biCompression = BI_RGB; - lpDIBheader->bmiHeader.biSizeImage = (xSize * abs(ySize) * bitsPerPixel) >> 3; - lpDIBheader->bmiHeader.biClrUsed = 256; - - - // Initialize the DIB palette - for (i = 0; i < 256; i++) { - lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags; - lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed; - lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen; - lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue; - } - - *lpDIBHeader = lpDIBheader; - - return true; -} - -void wxFreeDIB(LPBITMAPINFO lpDIBHeader) -{ - free(lpDIBHeader); -} -#endif - // ---------------------------------------------------------------------------- // global helper functions implemented here // ----------------------------------------------------------------------------