X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/878711c01c1b9ad5b97d35f379a048b8ce1bfb49..b8d24d4edd1f91339918134d2420af39c324aa1f:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index c153967b61..06fbd633bb 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -44,7 +44,10 @@ #include "wx/dcprint.h" #include "wx/module.h" #include "wx/dynload.h" + +#ifdef wxHAVE_RAW_BITMAP #include "wx/rawbmp.h" +#endif #include #include @@ -114,9 +117,24 @@ static const int MM_METRIC = 10; // convert degrees to radians static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } +// call AlphaBlend() to blit contents of hdcSrc to hdcDst using alpha +// +// NB: bmpSrc is the bitmap selected in hdcSrc, it is not really needed +// to pass it to this function but as we already have it at the point +// of call anyhow we do +// +// return true if we could draw the bitmap in one way or the other, false +// otherwise +static bool AlphaBlt(HDC hdcDst, + int x, int y, int w, int h, + HDC hdcSrc, + const wxBitmap& bmpSrc); + +#ifdef wxHAVE_RAW_BITMAP // our (limited) AlphaBlend() replacement static void -wxAlphaBlend(wxDC& dc, int x, int y, int w, int h, const wxBitmap& bmp); +wxAlphaBlend(HDC hdcDst, int x, int y, int w, int h, const wxBitmap& bmp); +#endif // ---------------------------------------------------------------------------- // private classes @@ -656,7 +674,7 @@ void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord x2 = x1 + width, y2 = y1 + height; -#if defined(__WIN32__) && !defined(__SC__) && !defined(__WXMICROWIN__) +#if defined(__WIN32__) && !defined(__SYMANTEC__) && !defined(__WXMICROWIN__) RECT rect; rect.left = x1; rect.top = y1; @@ -951,68 +969,14 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask HPALETTE oldPal = 0; #endif // wxUSE_PALETTE - // do we have AlphaBlend() and company in the headers? -#ifdef AC_SRC_OVER if ( bmp.HasAlpha() ) { - // yes, now try to see if we have it during run-time - - typedef BOOL (WINAPI *AlphaBlend_t)(HDC,int,int,int,int, - HDC,int,int,int,int, - BLENDFUNCTION); - - // bitmaps can be drawn only from GUI thread so there is no need to - // protect this static variable from multiple threads - static bool s_triedToLoad = FALSE; - static AlphaBlend_t pfnAlphaBlend = NULL; - if ( !s_triedToLoad ) - { - s_triedToLoad = TRUE; - - // don't give errors about the DLL being unavailable, we're - // prepared to handle this - wxLogNull nolog; - - wxDynamicLibrary dll(_T("msimg32.dll")); - if ( dll.IsLoaded() ) - { - pfnAlphaBlend = (AlphaBlend_t)dll.GetSymbol(_T("AlphaBlend")); - if ( pfnAlphaBlend ) - { - // we must keep the DLL loaded if we want to be able to - // call AlphaBlend() so just never unload it at all, not a - // big deal - dll.Detach(); - } - } - } + MemoryHDC hdcMem; + SelectInHDC select(hdcMem, GetHbitmapOf(bmp)); - if ( pfnAlphaBlend ) - { - MemoryHDC hdcMem; - SelectInHDC select(hdcMem, GetHbitmapOf(bmp)); - - BLENDFUNCTION bf; - bf.BlendOp = AC_SRC_OVER; - bf.BlendFlags = 0; - bf.SourceConstantAlpha = 0xff; - bf.AlphaFormat = AC_SRC_ALPHA; - - if ( !pfnAlphaBlend(GetHdc(), x, y, width, height, - hdcMem, 0, 0, width, height, - bf) ) - { - wxLogLastError(_T("AlphaBlend")); - } - } - else // use our own (probably much slower) implementation - { - wxAlphaBlend(*this, x, y, width, height, bmp); - } - - return; + if ( AlphaBlt(GetHdc(), x, y, width, height, hdcMem, bmp) ) + return; } -#endif // defined(AC_SRC_OVER) if ( useMask ) { @@ -1832,11 +1796,19 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, int rop, bool useMask, wxCoord xsrcMask, wxCoord ysrcMask) { + wxCHECK_MSG( source, FALSE, _T("wxDC::Blit(): NULL wxDC pointer") ); + #ifdef __WXMICROWIN__ if (!GetHDC()) return FALSE; #endif const wxBitmap& bmpSrc = source->m_selectedBitmap; + if ( bmpSrc.Ok() && bmpSrc.HasAlpha() ) + { + if ( AlphaBlt(GetHdc(), xdest, ydest, width, height, + GetHdcOf(*source), bmpSrc) ) + return TRUE; + } wxMask *mask = NULL; if ( useMask ) @@ -2296,33 +2268,114 @@ IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) #endif // wxUSE_DC_CACHEING // ---------------------------------------------------------------------------- -// wxAlphaBlend: our fallback if ::AlphaBlend() is unavailable +// alpha channel support // ---------------------------------------------------------------------------- +static bool AlphaBlt(HDC hdcDst, + int x, int y, int width, int height, + HDC hdcSrc, + const wxBitmap& bmp) +{ + wxASSERT_MSG( bmp.Ok() && bmp.HasAlpha(), _T("AlphaBlt(): invalid bitmap") ); + wxASSERT_MSG( hdcDst && hdcSrc, _T("AlphaBlt(): invalid HDC") ); + + // do we have AlphaBlend() and company in the headers? +#ifdef AC_SRC_OVER + // yes, now try to see if we have it during run-time + typedef BOOL (WINAPI *AlphaBlend_t)(HDC,int,int,int,int, + HDC,int,int,int,int, + BLENDFUNCTION); + + // bitmaps can be drawn only from GUI thread so there is no need to + // protect this static variable from multiple threads + static bool s_triedToLoad = FALSE; + static AlphaBlend_t pfnAlphaBlend = NULL; + if ( !s_triedToLoad ) + { + s_triedToLoad = TRUE; + + // don't give errors about the DLL being unavailable, we're + // prepared to handle this + wxLogNull nolog; + + wxDynamicLibrary dll(_T("msimg32.dll")); + if ( dll.IsLoaded() ) + { + pfnAlphaBlend = (AlphaBlend_t)dll.GetSymbol(_T("AlphaBlend")); + if ( pfnAlphaBlend ) + { + // we must keep the DLL loaded if we want to be able to + // call AlphaBlend() so just never unload it at all, not a + // big deal + dll.Detach(); + } + } + } + + if ( pfnAlphaBlend ) + { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 0xff; + bf.AlphaFormat = AC_SRC_ALPHA; + + if ( pfnAlphaBlend(hdcDst, x, y, width, height, + hdcSrc, 0, 0, width, height, + bf) ) + { + // skip wxAlphaBlend() call below + return TRUE; + } + + wxLogLastError(_T("AlphaBlend")); + } +#endif // defined(AC_SRC_OVER) + + // AlphaBlend() unavailable of failed: use our own (probably much slower) + // implementation +#ifdef wxHAVE_RAW_BITMAP + wxAlphaBlend(hdcDst, x, y, width, height, bmp); + + return TRUE; +#else // !wxHAVE_RAW_BITMAP + // no wxAlphaBlend() neither, fall back to using simple BitBlt() (we lose + // alpha but at least something will be shown like this) + return FALSE; +#endif // wxHAVE_RAW_BITMAP +} + + +// wxAlphaBlend: our fallback if ::AlphaBlend() is unavailable +#ifdef wxHAVE_RAW_BITMAP + static void -wxAlphaBlend(wxDC& dc, int xDst, int yDst, int w, int h, const wxBitmap& bmpSrc) +wxAlphaBlend(HDC hdcDst, int xDst, int yDst, int w, int h, const wxBitmap& bmpSrc) { // get the destination DC pixels - wxBitmap bmpDst(w, h, 32); + wxBitmap bmpDst(w, h, 32 /* force creating RGBA DIB */); MemoryHDC hdcMem; SelectInHDC select(hdcMem, GetHbitmapOf(bmpDst)); - if ( !::BitBlt(hdcMem, 0, 0, w, h, GetHdcOf(dc), 0, 0, SRCCOPY) ) + if ( !::BitBlt(hdcMem, 0, 0, w, h, hdcDst, 0, 0, SRCCOPY) ) { wxLogLastError(_T("BitBlt")); } // combine them with the source bitmap using alpha - wxRawBitmapData dataDst(bmpDst), - dataSrc(bmpSrc); + wxAlphaPixelData dataDst(bmpDst), + dataSrc((wxBitmap &)bmpSrc); + + wxCHECK_RET( dataDst && dataSrc, + _T("failed to get raw data in wxAlphaBlend") ); - wxRawBitmapIterator pDst(dataDst), - pSrc(dataSrc); + wxAlphaPixelData::Iterator pDst(dataDst), + pSrc(dataSrc); for ( int y = 0; y < h; y++ ) { - wxRawBitmapIterator pDstRowStart = pDst, - pSrcRowStart = pSrc; + wxAlphaPixelData::Iterator pDstRowStart = pDst, + pSrcRowStart = pSrc; for ( int x = 0; x < w; x++ ) { @@ -2340,14 +2393,15 @@ wxAlphaBlend(wxDC& dc, int xDst, int yDst, int w, int h, const wxBitmap& bmpSrc) pDst = pDstRowStart; pSrc = pSrcRowStart; - pDst.OffsetY(1); - pSrc.OffsetY(1); + pDst.OffsetY(dataDst, 1); + pSrc.OffsetY(dataSrc, 1); } // and finally blit them back to the destination DC - if ( !::BitBlt(GetHdcOf(dc), xDst, yDst, w, h, hdcMem, 0, 0, SRCCOPY) ) + if ( !::BitBlt(hdcDst, xDst, yDst, w, h, hdcMem, 0, 0, SRCCOPY) ) { wxLogLastError(_T("BitBlt")); } } +#endif // #ifdef wxHAVE_RAW_BITMAP