X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a3a1ceae81727ebfeb286d60770491a5cf478f30..4634a5d6d71c051d189c8e58f13bda52a77bf8e3:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 3fc309221a..c720b36fa3 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -657,7 +657,56 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask int width = bmp.GetWidth(), height = bmp.GetHeight(); - if ( !useMask ) + HBITMAP hbmpMask = 0; + + if ( useMask ) + { + wxMask *mask = bmp.GetMask(); + if ( mask ) + hbmpMask = (HBITMAP)mask->GetMaskBitmap(); + + if ( !hbmpMask ) + { + // don't give assert here because this would break existing + // programs - just silently ignore useMask parameter + useMask = FALSE; + } + } + + if ( useMask ) + { +#ifdef __WIN32__ + HDC hdcMem = ::CreateCompatibleDC(GetHdc()); + ::SelectObject(hdcMem, GetHbitmapOf(bmp)); + + // this will only work if the transparent part of our bitmap is black + // because it is combined with the destination rectangle using OR, so + // it won't be really transparent otherwise - I don't know what to do + // about it, may be use MAKEROP4(SRCCOPY, DSTINVERT) twice? Or create a + // copy of the bitmap with the transparent part replaced with black + // pixels? + bool ok = ::MaskBlt(GetHdc(), x, y, width, height, + hdcMem, 0, 0, + hbmpMask, 0, 0, + MAKEROP4(SRCCOPY, SRCPAINT)) != 0; + ::DeleteDC(hdcMem); + + if ( !ok ) +#endif // Win32 + { + // VZ: this is incorrect, Blit() doesn't (and can't) draw + // transparently, but it's still better than nothing at all + + // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level + wxMemoryDC memDC; + memDC.SelectObject(bmp); + + Blit(x, y, width, height, &memDC, 0, 0, wxCOPY, useMask); + + memDC.SelectObject(wxNullBitmap); + } + } + else // no mask, just use BitBlt() { HDC cdc = GetHdc(); HDC memdc = ::CreateCompatibleDC( cdc ); @@ -683,16 +732,6 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask ::SetTextColor(GetHdc(), old_textground); ::SetBkColor(GetHdc(), old_background); } - else - { - // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level - wxMemoryDC memDC; - memDC.SelectObject(bmp); - - Blit(x, y, width, height, &memDC, 0, 0, wxCOPY, useMask); - - memDC.SelectObject(wxNullBitmap); - } } void wxDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y) @@ -992,37 +1031,40 @@ void wxDC::SetLogicalFunction(int function) { m_logicalFunction = function; - SetRop((WXHDC) m_hDC); + SetRop(m_hDC); } void wxDC::SetRop(WXHDC dc) { - if (!dc || m_logicalFunction < 0) + if ( !dc || m_logicalFunction < 0 ) return; - int c_rop; - // These may be wrong + int rop; + switch (m_logicalFunction) { - // case wxXOR: c_rop = R2_XORPEN; break; - case wxXOR: c_rop = R2_NOTXORPEN; break; - case wxINVERT: c_rop = R2_NOT; break; - case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break; - case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break; - case wxCLEAR: c_rop = R2_WHITE; break; - case wxSET: c_rop = R2_BLACK; break; - case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break; - case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break; - case wxAND: c_rop = R2_MASKPEN; break; - case wxOR: c_rop = R2_MERGEPEN; break; - case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break; - case wxEQUIV: - case wxNAND: - case wxCOPY: - default: - c_rop = R2_COPYPEN; break; + case wxXOR: rop = R2_XORPEN; break; + case wxINVERT: rop = R2_NOT; break; + case wxOR_REVERSE: rop = R2_MERGEPENNOT; break; + case wxAND_REVERSE: rop = R2_MASKPENNOT; break; + case wxCLEAR: rop = R2_WHITE; break; + case wxSET: rop = R2_BLACK; break; + case wxOR_INVERT: rop = R2_MERGENOTPEN; break; + case wxAND: rop = R2_MASKPEN; break; + case wxOR: rop = R2_MERGEPEN; break; + case wxEQUIV: rop = R2_NOTXORPEN; break; + case wxNAND: rop = R2_NOTMASKPEN; break; + case wxAND_INVERT: rop = R2_MASKNOTPEN; break; + case wxCOPY: rop = R2_COPYPEN; break; + case wxNO_OP: rop = R2_NOP; break; + case wxSRC_INVERT: rop = R2_NOTCOPYPEN; break; + case wxNOR: rop = R2_NOTMERGEPEN; break; + default: + wxFAIL_MSG( wxT("unsupported logical function") ); + return; } - SetROP2((HDC) dc, c_rop); + + SetROP2(GetHdc(), rop); } bool wxDC::StartDoc(const wxString& message) @@ -1271,40 +1313,70 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, ::SetBkColor(GetHdc(), m_textBackgroundColour.GetPixel() ); } - DWORD dwRop = rop == wxCOPY ? SRCCOPY : - rop == wxCLEAR ? WHITENESS : - rop == wxSET ? BLACKNESS : - rop == wxINVERT ? DSTINVERT : - rop == wxAND ? MERGECOPY : - rop == wxOR ? MERGEPAINT : - rop == wxSRC_INVERT ? NOTSRCCOPY : - rop == wxXOR ? SRCINVERT : - rop == wxOR_REVERSE ? MERGEPAINT : - rop == wxAND_REVERSE ? SRCERASE : - rop == wxSRC_OR ? SRCPAINT : - rop == wxSRC_AND ? SRCAND : - SRCCOPY; + DWORD dwRop = SRCCOPY; + switch (rop) + { + case wxXOR: dwRop = SRCINVERT; break; + case wxINVERT: dwRop = DSTINVERT; break; + case wxOR_REVERSE: dwRop = 0x00DD0228; break; + case wxAND_REVERSE: dwRop = SRCERASE; break; + case wxCLEAR: dwRop = BLACKNESS; break; + case wxSET: dwRop = WHITENESS; break; + case wxOR_INVERT: dwRop = MERGEPAINT; break; + case wxAND: dwRop = SRCAND; break; + case wxOR: dwRop = SRCPAINT; break; + case wxEQUIV: dwRop = 0x00990066; break; + case wxNAND: dwRop = 0x007700E6; break; + case wxAND_INVERT: dwRop = 0x00220326; break; + case wxCOPY: dwRop = SRCCOPY; break; + case wxNO_OP: dwRop = 0x00AA0029; break; + case wxSRC_INVERT: dwRop = NOTSRCCOPY; break; + case wxNOR: dwRop = NOTSRCCOPY; break; + default: + wxFAIL_MSG( wxT("unsupported logical function") ); + return FALSE; + } + bool success; if (useMask) { #ifdef __WIN32__ + // prepare the mask bitmap HBITMAP hbmpMask = wxInvertMask((HBITMAP)mask->GetMaskBitmap()); + // select the correct brush: the current one by default, background one + // if none + HBRUSH hbrNew; + if ( m_brush.Ok() ) + { + hbrNew = (HBRUSH)m_brush.GetResourceHandle(); + } + else if ( m_backgroundBrush.Ok() ) + { + hbrNew = (HBRUSH)m_backgroundBrush.GetResourceHandle(); + } + else + { + hbrNew = 0; + } + + HGDIOBJ hbrOld = hbrNew ? ::SelectObject(GetHdc(), hbrNew) : 0; + // we want the part of the image corresponding to the mask to be // transparent, i.e. do PATCOPY there and apply dwRop elsewhere - const wxColour& colBg = m_backgroundBrush.GetColour(); - HBRUSH hbrBg = (HBRUSH)::CreateSolidBrush(wxColourToRGB(colBg)); - HBRUSH hbrOld = (HBRUSH)::SelectObject(GetHdc(), hbrBg); success = ::MaskBlt(GetHdc(), xdest, ydest, width, height, GetHdcOf(*source), xsrc, ysrc, hbmpMask, 0, 0, MAKEROP4(PATCOPY, dwRop)) != 0; - (void)::SelectObject(GetHdc(), hbrOld); - ::DeleteObject(hbrOld); + if ( hbrNew ) + { + (void)::SelectObject(GetHdc(), hbrOld); + } + ::DeleteObject(hbmpMask); if ( !success )