X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d1bf777402bf1eee975f42e42833ddcaf5689c9c..41b78190adf985fa6e91a34aba76b1693a8ffc72:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 64e2dda0db..ad43d3aa01 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -45,6 +45,10 @@ #include "wx/module.h" #include "wx/dynload.h" +#ifdef wxHAVE_RAW_BITMAP +#include "wx/rawbmp.h" +#endif + #include #include @@ -58,6 +62,10 @@ #include #endif +#ifndef AC_SRC_ALPHA +#define AC_SRC_ALPHA 1 +#endif + /* Quaternary raster codes */ #ifndef MAKEROP4 #define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore)) @@ -109,6 +117,13 @@ static const int MM_METRIC = 10; // convert degrees to radians static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } + +#ifdef wxHAVE_RAW_BITMAP +// our (limited) AlphaBlend() replacement +static void +wxAlphaBlend(wxDC& dc, int x, int y, int w, int h, const wxBitmap& bmp); +#endif + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -647,7 +662,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; @@ -983,26 +998,29 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask MemoryHDC hdcMem; SelectInHDC select(hdcMem, GetHbitmapOf(bmp)); -#ifndef AC_SRC_ALPHA - #define AC_SRC_ALPHA 1 -#endif - 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) ) + if ( pfnAlphaBlend(GetHdc(), x, y, width, height, + hdcMem, 0, 0, width, height, + bf) ) { - wxLogLastError(_T("AlphaBlend")); + // skip wxAlphaBlend() call below + return; } - return; + wxLogLastError(_T("AlphaBlend")); } - //else: AlphaBlend() not available + + // use our own (probably much slower) implementation +#ifdef wxHAVE_RAW_BITMAP + wxAlphaBlend(*this, x, y, width, height, bmp); +#endif // wxHAVE_RAW_BITMAP + + return; } #endif // defined(AC_SRC_OVER) @@ -1828,13 +1846,14 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, if (!GetHDC()) return FALSE; #endif + const wxBitmap& bmpSrc = source->m_selectedBitmap; + wxMask *mask = NULL; if ( useMask ) { - const wxBitmap& bmp = source->m_selectedBitmap; - mask = bmp.GetMask(); + mask = bmpSrc.GetMask(); - if ( !(bmp.Ok() && mask && mask->GetMaskBitmap()) ) + if ( !(bmpSrc.Ok() && mask && mask->GetMaskBitmap()) ) { // don't give assert here because this would break existing // programs - just silently ignore useMask parameter @@ -1998,36 +2017,79 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, } else // no mask, just BitBlt() it { - // use StretchBlt() if available - if ( ::GetDeviceCaps(GetHdc(), RASTERCAPS) & RC_STRETCHBLT ) + // if we already have a DIB, draw it using StretchDIBits(), otherwise + // use StretchBlt() if available and finally fall back to BitBlt() + const int caps = ::GetDeviceCaps(GetHdc(), RASTERCAPS); + if ( bmpSrc.Ok() && (caps & RC_STRETCHDIB) ) { - StretchBltModeChanger changeMode(GetHdc(), COLORONCOLOR); + DIBSECTION ds; + wxZeroMemory(ds); - success = ::StretchBlt - ( - GetHdc(), - xdest, ydest, width, height, - GetHdcOf(*source), - xsrc, ysrc, width, height, - dwRop - ) != 0; + if ( ::GetObject(GetHbitmapOf(bmpSrc), + sizeof(ds), + &ds) == sizeof(ds) ) + { + StretchBltModeChanger changeMode(GetHdc(), COLORONCOLOR); + + if ( ::StretchDIBits(GetHdc(), + xdest, ydest, + width, height, + 0, 0, + width, height, + ds.dsBm.bmBits, + (LPBITMAPINFO)&ds.dsBmih, + DIB_RGB_COLORS, + SRCCOPY + ) == (int)GDI_ERROR ) + { + wxLogLastError(wxT("StretchDIBits")); + } + else + { + success = TRUE; + } + } } - else + + if ( !success && (caps & RC_STRETCHBLT) ) { - success = ::BitBlt - ( - GetHdc(), - xdest, ydest, - (int)width, (int)height, - GetHdcOf(*source), - xsrc, ysrc, - dwRop - ) != 0; + StretchBltModeChanger changeMode(GetHdc(), COLORONCOLOR); + + if ( !::StretchBlt + ( + GetHdc(), + xdest, ydest, width, height, + GetHdcOf(*source), + xsrc, ysrc, width, height, + dwRop + ) ) + { + wxLogLastError(_T("StretchBlt")); + } + else + { + success = TRUE; + } } if ( !success ) { - wxLogLastError(wxT("BitBlt/StretchBlt")); + if ( !::BitBlt + ( + GetHdc(), + xdest, ydest, + (int)width, (int)height, + GetHdcOf(*source), + xsrc, ysrc, + dwRop + ) ) + { + wxLogLastError(_T("BitBlt")); + } + else + { + success = TRUE; + } } } @@ -2102,6 +2164,10 @@ void wxDC::SetLogicalScale(double x, double y) m_logicalScaleY = y; } +// ---------------------------------------------------------------------------- +// DC caching +// ---------------------------------------------------------------------------- + #if wxUSE_DC_CACHEING /* @@ -2142,10 +2208,10 @@ wxDCCacheEntry::~wxDCCacheEntry() wxDCCacheEntry* wxDC::FindBitmapInCache(WXHDC dc, int w, int h) { int depth = ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); - wxNode* node = sm_bitmapCache.First(); + wxNode* node = sm_bitmapCache.GetFirst(); while (node) { - wxDCCacheEntry* entry = (wxDCCacheEntry*) node->Data(); + wxDCCacheEntry* entry = (wxDCCacheEntry*) node->GetData(); if (entry->m_depth == depth) { @@ -2163,7 +2229,7 @@ wxDCCacheEntry* wxDC::FindBitmapInCache(WXHDC dc, int w, int h) return entry; } - node = node->Next(); + node = node->GetNext(); } WXHBITMAP hBitmap = (WXHBITMAP) ::CreateCompatibleBitmap((HDC) dc, w, h); if ( !hBitmap) @@ -2178,10 +2244,10 @@ wxDCCacheEntry* wxDC::FindBitmapInCache(WXHDC dc, int w, int h) wxDCCacheEntry* wxDC::FindDCInCache(wxDCCacheEntry* notThis, WXHDC dc) { int depth = ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); - wxNode* node = sm_dcCache.First(); + wxNode* node = sm_dcCache.GetFirst(); while (node) { - wxDCCacheEntry* entry = (wxDCCacheEntry*) node->Data(); + wxDCCacheEntry* entry = (wxDCCacheEntry*) node->GetData(); // Don't return the same one as we already have if (!notThis || (notThis != entry)) @@ -2192,7 +2258,7 @@ wxDCCacheEntry* wxDC::FindDCInCache(wxDCCacheEntry* notThis, WXHDC dc) } } - node = node->Next(); + node = node->GetNext(); } WXHDC hDC = (WXHDC) ::CreateCompatibleDC((HDC) dc); if ( !hDC) @@ -2237,6 +2303,66 @@ private: IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule) -#endif - // wxUSE_DC_CACHEING +#endif // wxUSE_DC_CACHEING + +// ---------------------------------------------------------------------------- +// 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) +{ + // get the destination DC pixels + 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) ) + { + wxLogLastError(_T("BitBlt")); + } + + // combine them with the source bitmap using alpha + wxAlphaPixelData dataDst(bmpDst), + dataSrc((wxBitmap &)bmpSrc); + + wxCHECK_RET( dataDst && dataSrc, + _T("failed to get raw data in wxAlphaBlend") ); + + wxAlphaPixelData::Iterator pDst(dataDst), + pSrc(dataSrc); + + for ( int y = 0; y < h; y++ ) + { + wxAlphaPixelData::Iterator pDstRowStart = pDst, + pSrcRowStart = pSrc; + + for ( int x = 0; x < w; x++ ) + { + // note that source bitmap uses premultiplied alpha (as required by + // the real AlphaBlend) + const unsigned beta = 255 - pSrc.Alpha(); + + pDst.Red() = pSrc.Red() + (beta * pDst.Red() + 127) / 255; + pDst.Blue() = pSrc.Blue() + (beta * pDst.Blue() + 127) / 255; + pDst.Green() = pSrc.Green() + (beta * pDst.Green() + 127) / 255; + + ++pDst; + ++pSrc; + } + + pDst = pDstRowStart; + pSrc = pSrcRowStart; + 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) ) + { + wxLogLastError(_T("BitBlt")); + } +} +#endif // #ifdef wxHAVE_RAW_BITMAP