+ wxMask *mask = NULL;
+ if ( useMask )
+ {
+ const wxBitmap& bmp = source->m_selectedBitmap;
+ mask = bmp.GetMask();
+
+ if ( !(bmp.Ok() && mask && mask->GetMaskBitmap()) )
+ {
+ // don't give assert here because this would break existing
+ // programs - just silently ignore useMask parameter
+ useMask = FALSE;
+ }
+ }
+
+ COLORREF old_textground = ::GetTextColor(GetHdc());
+ COLORREF old_background = ::GetBkColor(GetHdc());
+ if (m_textForegroundColour.Ok())
+ {
+ ::SetTextColor(GetHdc(), m_textForegroundColour.GetPixel() );
+ }
+ if (m_textBackgroundColour.Ok())
+ {
+ ::SetBkColor(GetHdc(), m_textBackgroundColour.GetPixel() );
+ }
+
+ 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 = DSTCOPY; 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__
+ // we want the part of the image corresponding to the mask to be
+ // transparent, so use "DSTCOPY" ROP for the mask points (the usual
+ // meaning of fg and bg is inverted which corresponds to wxWin notion
+ // of the mask which is also contrary to the Windows one)
+ success = ::MaskBlt(GetHdc(), xdest, ydest, width, height,
+ GetHdcOf(*source), xsrc, ysrc,
+ (HBITMAP)mask->GetMaskBitmap(), 0, 0,
+ MAKEROP4(dwRop, DSTCOPY)) != 0;
+
+ if ( !success )
+#endif // Win32
+ {
+ // Blit bitmap with mask
+
+ // create a temp buffer bitmap and DCs to access it and the mask
+ HDC dc_mask = ::CreateCompatibleDC(GetHdcOf(*source));
+ HDC dc_buffer = ::CreateCompatibleDC(GetHdc());
+ HBITMAP buffer_bmap = ::CreateCompatibleBitmap(GetHdc(), width, height);
+ ::SelectObject(dc_mask, (HBITMAP) mask->GetMaskBitmap());
+ ::SelectObject(dc_buffer, buffer_bmap);
+
+ // copy dest to buffer
+ if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
+ GetHdc(), xdest, ydest, SRCCOPY) )
+ {
+ wxLogLastError(wxT("BitBlt"));
+ }
+
+ // copy src to buffer using selected raster op
+ if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
+ GetHdcOf(*source), xsrc, ysrc, dwRop) )
+ {
+ wxLogLastError(wxT("BitBlt"));
+ }
+
+ // set masked area in buffer to BLACK (pixel value 0)
+ COLORREF prevBkCol = ::SetBkColor(GetHdc(), RGB(255, 255, 255));
+ COLORREF prevCol = ::SetTextColor(GetHdc(), RGB(0, 0, 0));
+ if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
+ dc_mask, xsrc, ysrc, SRCAND) )
+ {
+ wxLogLastError(wxT("BitBlt"));
+ }
+
+ // set unmasked area in dest to BLACK
+ ::SetBkColor(GetHdc(), RGB(0, 0, 0));
+ ::SetTextColor(GetHdc(), RGB(255, 255, 255));
+ if ( !::BitBlt(GetHdc(), xdest, ydest, (int)width, (int)height,
+ dc_mask, xsrc, ysrc, SRCAND) )
+ {
+ wxLogLastError(wxT("BitBlt"));
+ }
+ ::SetBkColor(GetHdc(), prevBkCol); // restore colours to original values
+ ::SetTextColor(GetHdc(), prevCol);
+
+ // OR buffer to dest
+ success = ::BitBlt(GetHdc(), xdest, ydest,
+ (int)width, (int)height,
+ dc_buffer, 0, 0, SRCPAINT) != 0;
+ if ( !success )
+ {
+ wxLogLastError(wxT("BitBlt"));
+ }
+
+ // tidy up temporary DCs and bitmap
+ ::SelectObject(dc_mask, 0);
+ ::DeleteDC(dc_mask);
+ ::SelectObject(dc_buffer, 0);
+ ::DeleteDC(dc_buffer);
+ ::DeleteObject(buffer_bmap);
+ }
+ }
+ else // no mask, just BitBlt() it
+ {
+ success = ::BitBlt(GetHdc(), xdest, ydest,
+ (int)width, (int)height,
+ GetHdcOf(*source), xsrc, ysrc, dwRop) != 0;
+ if ( !success )
+ {
+ wxLogLastError(wxT("BitBlt"));
+ }
+ }
+ ::SetTextColor(GetHdc(), old_textground);
+ ::SetBkColor(GetHdc(), old_background);
+
+ return success;