X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7010702f631a71afdb7beef50fcb4857db0cc5a2..fd926bccac94c6a717d77e75e0ea65a64e333f8a:/src/msw/bitmap.cpp?ds=sidebyside diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index 99cad6f681..a68457e219 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -67,6 +67,7 @@ class WXDLLEXPORT wxBitmapRefData : public wxGDIImageRefData { public: wxBitmapRefData(); + wxBitmapRefData(const wxBitmapRefData& data); virtual ~wxBitmapRefData() { Free(); } virtual void Free(); @@ -120,7 +121,9 @@ private: // optional mask for transparent drawing wxMask *m_bitmapMask; - DECLARE_NO_COPY_CLASS(wxBitmapRefData) + + // not implemented + wxBitmapRefData& operator=(const wxBitmapRefData&); }; // ---------------------------------------------------------------------------- @@ -200,6 +203,23 @@ wxBitmapRefData::wxBitmapRefData() m_hasAlpha = FALSE; } +wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data) + : wxGDIImageRefData(data) +{ +#ifdef __WXDEBUG__ + m_selectedInto = NULL; +#endif + + // can't copy the mask as the other bitmap destroys it + m_bitmapMask = NULL; + + wxASSERT_MSG( !data.m_isDIB, + _T("can't copy bitmap locked for raw access!") ); + m_isDIB = FALSE; + + m_hasAlpha = data.m_hasAlpha; +} + void wxBitmapRefData::Free() { wxASSERT_MSG( !m_selectedInto, @@ -236,6 +256,32 @@ wxGDIImageRefData *wxBitmap::CreateData() const return new wxBitmapRefData; } +wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *dataOrig) const +{ + const wxBitmapRefData * + data = wx_static_cast(const wxBitmapRefData *, dataOrig); + if ( !data ) + return NULL; + + wxBitmap *self = wx_const_cast(wxBitmap *, this); + +#if wxUSE_WXDIB + // copy the other bitmap + if ( data->m_hBitmap ) + { + wxDIB dib((HBITMAP)(data->m_hBitmap)); + self->CopyFromDIB(dib); + } + else +#endif // wxUSE_WXDIB + { + // don't copy the bitmap data, but do copy the size, depth, ... + self->m_refData = new wxBitmapRefData(*data); + } + + return m_refData; +} + #ifdef __WIN32__ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) @@ -810,6 +856,7 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) wxImage wxBitmap::ConvertToImage() const { + // convert DDB to DIB wxDIB dib(*this); if ( !dib.IsOk() ) @@ -817,122 +864,75 @@ wxImage wxBitmap::ConvertToImage() const return wxNullImage; } + // and then DIB to our wxImage wxImage image = dib.ConvertToImage(); if ( !image.Ok() ) { return wxNullImage; } - // set mask - - // TODO: WinCE mask-copying support and use wxDIB -#ifndef __WXWINCE__ - - if( GetMask() && GetMask()->GetMaskBitmap() ) + // now do the same for the mask, if we have any + HBITMAP hbmpMask = GetMask() ? (HBITMAP) GetMask()->GetMaskBitmap() : NULL; + if ( hbmpMask ) { - 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; - - HBITMAP hbitmap = (HBITMAP) GetMask()->GetMaskBitmap(); - int width = GetWidth(); - int height = GetHeight(); - - int bytesPerLine = width*3; - int sizeDWORD = sizeof( DWORD ); - int lineBoundary = bytesPerLine % sizeDWORD; - int padding = 0; - if( lineBoundary > 0 ) - { - padding = sizeDWORD - lineBoundary; - bytesPerLine += 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 = bytesPerLine * 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 DC created, color set, data copied, and memory DC deleted - - // memory for DIB data - unsigned char *lpBits - = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage ); - if( !lpBits ) + wxDIB dibMask(hbmpMask); + if ( dibMask.IsOk() ) { - wxFAIL_MSG( wxT("could not allocate data for DIB") ); - free( lpDIBh ); - return wxNullImage; - } - - - HDC hdc = ::GetDC(NULL); - - 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 ); - unsigned char *ptdata = image.GetData();//data; - unsigned char *ptbits = lpBits; - int i, j; - for( i=0; i> 3; + const int maskBytesPerLine = wxDIB::GetLineSize(w, bpp); + unsigned char *data = image.GetData(); + + // remember that DIBs are stored in bottom to top order + unsigned char * + maskLineStart = dibMask.GetData() + ((h - 1) * maskBytesPerLine); + + for ( int y = 0; y < h; y++, maskLineStart -= maskBytesPerLine ) { - // is this pixel transparent? - if ( *ptbits != 0 ) + // traverse one mask DIB line + unsigned char *mask = maskLineStart; + for ( int x = 0; x < w; x++, mask += maskBytesPerPixel ) { - if ( (ptdata[0] == MASK_RED) && - (ptdata[1] == MASK_GREEN) && - (ptdata[2] == MASK_BLUE) ) + // should this pixel be transparent? + if ( *mask ) { - // we have to fudge the colour a bit to prevent this - // pixel from appearing transparent - ptdata[2] = MASK_BLUE_REPLACEMENT; + // no, check that it isn't transparent by accident + if ( (data[0] == MASK_RED) && + (data[1] == MASK_GREEN) && + (data[2] == MASK_BLUE) ) + { + // we have to fudge the colour a bit to prevent + // this pixel from appearing transparent + data[2] = MASK_BLUE_REPLACEMENT; + } + + data += 3; + } + else // yes, transparent pixel + { + *data++ = MASK_RED; + *data++ = MASK_GREEN; + *data++ = MASK_BLUE; } - ptdata += 3; - } - else // masked pixel - { - *(ptdata++) = MASK_RED; - *(ptdata++) = MASK_GREEN; - *(ptdata++) = MASK_BLUE; } - ptbits += 3; } - ptbits += padding; - } - image.SetMaskColour( MASK_RED, MASK_GREEN, MASK_BLUE ); - image.SetMask( true ); - - // free allocated resources - ::ReleaseDC(NULL, hdc); - free(lpDIBh); - free(lpBits); + image.SetMaskColour(MASK_RED, MASK_GREEN, MASK_BLUE); + } } -#endif // __WXWINCE__ return image; } @@ -1140,7 +1140,7 @@ void wxBitmap::SetSelectedInto(wxDC *dc) void wxBitmap::SetPalette(const wxPalette& palette) { - EnsureHasData(); + AllocExclusive(); GetBitmapData()->m_bitmapPalette = palette; } @@ -1149,7 +1149,7 @@ void wxBitmap::SetPalette(const wxPalette& palette) void wxBitmap::SetMask(wxMask *mask) { - EnsureHasData(); + AllocExclusive(); GetBitmapData()->SetMask(mask); }