Ticket #16766: Optimize-AlphaBlt-function.patch

File Optimize-AlphaBlt-function.patch, 4.4 KB (added by awi, 6 years ago)

Optimized AlphaBlt function.

  • src/msw/dc.cpp

    a b static bool AlphaBlt(wxMSWDCImpl* dcDst, 
    27582758    bf.BlendFlags = 0;
    27592759    bf.SourceConstantAlpha = 0xff;
    27602760    bf.AlphaFormat = AC_SRC_ALPHA;
    2761 
    2762     if ( !wxDynLoadWrappers::AlphaBlend
    2763           (
    2764             GetHdcOf(*dcDst), x, y, dstWidth, dstHeight,
    2765             hdcSrc, srcX, srcY, srcWidth, srcHeight,
    2766             bf
    2767           ) )
    2768     {
    2769         wxLogLastError(wxT("AlphaBlend"));
    2770         return false;
    2771     }
    2772 
    27732761    // There is an extra complication with drawing bitmaps with alpha
    27742762    // on bitmaps without alpha: AlphaBlt() modifies the alpha
    27752763    // component of the destination bitmap even if it hadn't had it
    static bool AlphaBlt(wxMSWDCImpl* dcDst, 
    27782766    // are now fully transparent: they already had 0 value of alpha
    27792767    // before but it didn't count as long as all other pixels had 0
    27802768    // alpha as well, but now that some of them are not transparent any
    2781     // more, the rest of pixels with 0 alpha is transparent. So undo
    2782     // this to avoid "losing" the existing bitmap contents outside of
    2783     // the area affected by AlphaBlt(), see #14403.
    2784 #ifdef wxHAS_RAW_BITMAP
     2769    // more, the rest of pixels with 0 alpha is transparent.
     2770    // (See #14403)
     2771    // To avoid "losing" the existing bitmap contents outside of
     2772    // the area affected by AlphaBlt(), we do actual drawing
     2773    // on the 24-bit copy of the destination area and afterwards
     2774    // transfer the result back to the destination bitmap.
    27852775    const wxBitmap& bmpDst = dcDst->GetSelectedBitmap();
    27862776    if ( bmpDst.IsOk() && !bmpDst.HasAlpha() && bmpDst.GetDepth() == 32 )
    27872777    {
    2788         // We need to deselect the bitmap from the memory DC it is
    2789         // currently selected into before modifying it.
    2790         wxBitmap bmpOld = bmpDst;
    2791         dcDst->DoSelect(wxNullBitmap);
    2792 
    2793         // Notice the extra block: we must destroy wxAlphaPixelData
    2794         // before selecting the bitmap into the DC again.
     2778        // Temporary 24-bit bitmap to hold the contenst
     2779        // of the destination area.
     2780        // (24-bit bitmap is enough since we know
     2781        // that destination is 32-bit but has no alpha channel.)
     2782        wxBitmap bmp(dstWidth, dstHeight, 24);
     2783        wxMemoryDC dc(bmp);
     2784
     2785        // Fetch the content of the destination area into the temporary buffer.
     2786        wxRect r(x, y, dstWidth, dstHeight);
     2787        dc.DrawBitmap(dcDst->DoGetAsBitmap(&r), 0, 0);
     2788        // Drawing the source over the temporary buffer.
     2789        if ( !wxDynLoadWrappers::AlphaBlend
     2790                (
     2791                GetHdcOf(dc), 0, 0, dstWidth, dstHeight,
     2792                hdcSrc, srcX, srcY, srcWidth, srcHeight,
     2793                bf
     2794                ) )
    27952795        {
    2796             wxAlphaPixelData data(bmpOld);
    2797             if ( data )
    2798             {
    2799                 wxAlphaPixelData::Iterator p(data);
    2800                 for ( int y = 0; y < data.GetHeight(); y++ )
    2801                 {
    2802                     wxAlphaPixelData::Iterator rowStart = p;
    2803 
    2804                     for ( int x = 0; x < data.GetWidth(); x++ )
    2805                     {
    2806                         // We choose to use wxALPHA_TRANSPARENT instead
    2807                         // of perhaps more logical wxALPHA_OPAQUE here
    2808                         // to ensure that the bitmap remains the same
    2809                         // as before, i.e. without any alpha at all.
    2810                         p.Alpha() = wxALPHA_TRANSPARENT;
    2811                         ++p;
    2812                     }
    2813 
    2814                     p = rowStart;
    2815                     p.OffsetY(data, 1);
    2816                 }
    2817             }
     2796            wxLogLastError(wxT("AlphaBlend"));
     2797            return false;
    28182798        }
    28192799
    2820         // Using wxAlphaPixelData sets the internal "has alpha" flag
    2821         // which is usually what we need, but in this particular case
    2822         // we use it to get rid of alpha, not set it, so reset it back.
    2823         bmpOld.ResetAlpha();
    2824 
    2825         dcDst->DoSelect(bmpOld);
     2800        // Transfer temporary buffer back to the destination area.
     2801        dcDst->DoBlit(x, y, dstWidth, dstHeight, &dc, 0, 0);
     2802    }
     2803    else
     2804    {
     2805        if ( !wxDynLoadWrappers::AlphaBlend
     2806              (
     2807                GetHdcOf(*dcDst), x, y, dstWidth, dstHeight,
     2808                hdcSrc, srcX, srcY, srcWidth, srcHeight,
     2809                bf
     2810              ) )
     2811        {
     2812            wxLogLastError(wxT("AlphaBlend"));
     2813            return false;
     2814        }
    28262815    }
    2827 #endif // wxHAS_RAW_BITMAP
    28282816
    28292817    return true;
    28302818}