diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2015-01-03 13:14:55 +0900 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2015-01-19 00:07:24 +0900 |
commit | 009c1752b1eff36827dae4fa9bd394c5089dcc55 (patch) | |
tree | de783aaf3a0211acd012a6af5c3f9e6d07fdb78d | |
parent | 15db0307fe6429238be72612cccd4a1df5e1e97c (diff) |
Extract slow path of DrawDeviceAlphaBitmap into its own method
Additioanlly cleanup and use ScopedReadAccess
Change-Id: Ia3365f4dc968368bdd90d4398188bffe2d56e89b
-rw-r--r-- | include/vcl/outdev.hxx | 6 | ||||
-rw-r--r-- | vcl/source/outdev/bitmap.cxx | 253 |
2 files changed, 143 insertions, 116 deletions
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 5ce1a27515a8..f8fd837f3bf3 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1406,6 +1406,12 @@ private: const Point& rSrcPtPixel, const Size& rSrcSizePixel ); + SAL_DLLPRIVATE void DrawDeviceAlphaBitmapSlowPath( + const Bitmap& rBitmap, const AlphaMask& rAlpha, + Rectangle aDstRect, Rectangle aBmpRect, + Size& aOutSz, Point& aOutPt); + + SAL_DLLPRIVATE bool BlendBitmap( const SalTwoRect& rPosAry, const Bitmap& rBmp ); diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx index 680f36231c5b..50877bea8011 100644 --- a/vcl/source/outdev/bitmap.cxx +++ b/vcl/source/outdev/bitmap.cxx @@ -604,36 +604,37 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r const Point& rDestPt, const Size& rDestSize, const Point& rSrcPtPixel, const Size& rSrcSizePixel ) { - Point aOutPt( LogicToPixel( rDestPt ) ); - Size aOutSz( LogicToPixel( rDestSize ) ); - Rectangle aDstRect( Point(), GetOutputSizePixel() ); - const bool bHMirr = aOutSz.Width() < 0; - const bool bVMirr = aOutSz.Height() < 0; + Point aOutPt(LogicToPixel(rDestPt)); + Size aOutSz(LogicToPixel(rDestSize)); + Rectangle aDstRect(Point(), GetOutputSizePixel()); + + const bool bHMirr = aOutSz.Width() < 0; + const bool bVMirr = aOutSz.Height() < 0; ClipToPaintRegion(aDstRect); - if( bHMirr ) + if (bHMirr) { aOutSz.Width() = -aOutSz.Width(); - aOutPt.X() -= ( aOutSz.Width() - 1L ); + aOutPt.X() -= aOutSz.Width() - 1L; } - if( bVMirr ) + if (bVMirr) { aOutSz.Height() = -aOutSz.Height(); - aOutPt.Y() -= ( aOutSz.Height() - 1L ); + aOutPt.Y() -= aOutSz.Height() - 1L; } - if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() ) + if (!aDstRect.Intersection(Rectangle(aOutPt, aOutSz)).IsEmpty()) { static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA"); // #i83087# Naturally, system alpha blending cannot work with // separate alpha VDev bool bTryDirectPaint(!pDisableNative && !bHMirr && !bVMirr); - if(bTryDirectPaint) + if (bTryDirectPaint) { - Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY ); + Point aRelPt = aOutPt + Point(mnOutOffX, mnOutOffY); SalTwoRect aTR( rSrcPtPixel.X(), rSrcPtPixel.Y(), rSrcSizePixel.Width(), rSrcSizePixel.Height(), @@ -644,19 +645,19 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap(); // try the blen the alpha bitmap with the alpha virtual device - if( mpAlphaVDev ) + if (mpAlphaVDev) { Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aRelPt, aOutSz ) ); SalBitmap* pSalAlphaBmp2 = aAlphaBitmap.ImplGetImpBitmap()->ImplGetSalBitmap(); - if( mpGraphics->BlendAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, *pSalAlphaBmp2, this ) ) + if (mpGraphics->BlendAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, *pSalAlphaBmp2, this)) { - mpAlphaVDev->BlendBitmap( aTR, rAlpha ); + mpAlphaVDev->BlendBitmap(aTR, rAlpha); return; } } else { - if (mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this )) + if (mpGraphics->DrawAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, this)) return; } } @@ -664,122 +665,142 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r // we need to make sure OpenGL never reaches this slow code path assert(!OpenGLHelper::isVCLOpenGLEnabled()); - VirtualDevice* pOldVDev = mpAlphaVDev; - - Rectangle aBmpRect( Point(), rBmp.GetSizePixel() ); + Rectangle aBmpRect(Point(), rBmp.GetSizePixel()); if (!aBmpRect.Intersection(Rectangle(rSrcPtPixel, rSrcSizePixel)).IsEmpty()) { - // The scaling in this code path produces really ugly results - it - // does the most trivial scaling with no smoothing. - - GDIMetaFile* pOldMetaFile = mpMetaFile; - const bool bOldMap = mbMap; - mpMetaFile = NULL; // fdo#55044 reset before GetBitmap! - mbMap = false; - Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) ); - - // #109044# The generated bitmap need not necessarily be - // of aDstRect dimensions, it's internally clipped to - // window bounds. Thus, we correct the dest size here, - // since we later use it (in nDstWidth/Height) for pixel - // access) - // #i38887# reading from screen may sometimes fail - if( aBmp.ImplGetImpBitmap() ) - aDstRect.SetSize( aBmp.GetSizePixel() ); - - BitmapColor aDstCol; - const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight(); - const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight(); - const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height(); - // calculate offset in original bitmap - // in RTL case this is a little more complicated since the contents of the - // bitmap is not mirrored (it never is), however the paint region and bmp region - // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these - // is content wise somewhere else and needs to take mirroring into account - const long nOffX = IsRTLEnabled() - ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X()) - : aDstRect.Left() - aOutPt.X(), - nOffY = aDstRect.Top() - aOutPt.Y(); - long nX, nOutX, nY, nOutY; - long nMirrOffX = 0; - long nMirrOffY = 0; - boost::scoped_array<long> pMapX(new long[ nDstWidth ]); - boost::scoped_array<long> pMapY(new long[ nDstHeight ]); - - // create horizontal mapping table - if( bHMirr ) - nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1; - - for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) - { - pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth; - if( bHMirr ) - pMapX[ nX ] = nMirrOffX - pMapX[ nX ]; - } + DrawDeviceAlphaBitmapSlowPath(rBmp, rAlpha, aDstRect, aBmpRect, aOutSz, aOutPt); + } + } +} - // create vertical mapping table - if( bVMirr ) - nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1; +void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap, const AlphaMask& rAlpha, Rectangle aDstRect, Rectangle aBmpRect, Size& aOutSize, Point& aOutPoint) +{ + VirtualDevice* pOldVDev = mpAlphaVDev; - for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) - { - pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight; + const bool bHMirr = aOutSize.Width() < 0; + const bool bVMirr = aOutSize.Height() < 0; - if( bVMirr ) - pMapY[ nY ] = nMirrOffY - pMapY[ nY ]; - } + // The scaling in this code path produces really ugly results - it + // does the most trivial scaling with no smoothing. + GDIMetaFile* pOldMetaFile = mpMetaFile; + const bool bOldMap = mbMap; - BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess(); - BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); + mpMetaFile = NULL; // fdo#55044 reset before GetBitmap! + mbMap = false; - DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || - pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK, - "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" ); + Bitmap aBmp(GetBitmap(aDstRect.TopLeft(), aDstRect.GetSize())); - // #i38887# reading from screen may sometimes fail - if( aBmp.ImplGetImpBitmap() ) - { - Bitmap aTmp; + // #109044# The generated bitmap need not necessarily be + // of aDstRect dimensions, it's internally clipped to + // window bounds. Thus, we correct the dest size here, + // since we later use it (in nDstWidth/Height) for pixel + // access) + // #i38887# reading from screen may sometimes fail + if (aBmp.ImplGetImpBitmap()) + { + aDstRect.SetSize(aBmp.GetSizePixel()); + } - if( mpAlphaVDev ) - { - aTmp = BlendBitmapWithAlpha( - aBmp,pP,pA, - aDstRect, - nOffY,nDstHeight, - nOffX,nDstWidth, - pMapX.get(),pMapY.get() ); - } - else - { - aTmp = BlendBitmap( - aBmp,pP,pA, - nOffY,nDstHeight, - nOffX,nDstWidth, - aBmpRect,aOutSz, - bHMirr,bVMirr, - pMapX.get(),pMapY.get() ); - } + BitmapColor aDstCol; + const long nSrcWidth = aBmpRect.GetWidth(); + const long nSrcHeight = aBmpRect.GetHeight(); - // #110958# Disable alpha VDev, we're doing the necessary - // stuff explicitly furher below - if( mpAlphaVDev ) - mpAlphaVDev = NULL; + const long nDstWidth = aDstRect.GetWidth(); + const long nDstHeight = aDstRect.GetHeight(); - DrawBitmap( aDstRect.TopLeft(), - aTmp ); + const long nOutWidth = aOutSize.Width(); + const long nOutHeight = aOutSize.Height(); - // #110958# Enable alpha VDev again - mpAlphaVDev = pOldVDev; - } + // calculate offset in original bitmap + // in RTL case this is a little more complicated since the contents of the + // bitmap is not mirrored (it never is), however the paint region and bmp region + // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these + // is content wise somewhere else and needs to take mirroring into account + const long nOffX = IsRTLEnabled() + ? aOutSize.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPoint.X()) + : aDstRect.Left() - aOutPoint.X(); + + const long nOffY = aDstRect.Top() - aOutPoint.Y(); - ( (Bitmap&) rBmp ).ReleaseAccess( pP ); - ( (AlphaMask&) rAlpha ).ReleaseAccess( pA ); + long nX, nOutX, nY, nOutY; + long nMirrOffX = 0; + long nMirrOffY = 0; - mbMap = bOldMap; - mpMetaFile = pOldMetaFile; + boost::scoped_array<long> pMapX(new long[nDstWidth]); + boost::scoped_array<long> pMapY(new long[nDstHeight]); + + // create horizontal mapping table + if (bHMirr) + { + nMirrOffX = (aBmpRect.Left() << 1) + nSrcWidth - 1; + } + + for (nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++) + { + pMapX[nX] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth; + if(bHMirr) + pMapX[nX] = nMirrOffX - pMapX[nX]; + } + + // create vertical mapping table + if (bVMirr) + { + nMirrOffY = (aBmpRect.Top() << 1) + nSrcHeight - 1; + } + + for(nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++) + { + pMapY[nY] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight; + + if (bVMirr) + pMapY[nY] = nMirrOffY - pMapY[nY]; + } + + Bitmap::ScopedReadAccess pBitmapReadAccess(const_cast<Bitmap&>(rBitmap)); + AlphaMask::ScopedReadAccess pAlphaReadAccess(const_cast<AlphaMask&>(rAlpha)); + + DBG_ASSERT( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || + pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK, + "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" ); + + // #i38887# reading from screen may sometimes fail + if (aBmp.ImplGetImpBitmap()) + { + Bitmap aNewBitmap; + + if (mpAlphaVDev) + { + aNewBitmap = BlendBitmapWithAlpha( + aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(), + aDstRect, + nOffY, nDstHeight, + nOffX, nDstWidth, + pMapX.get(), pMapY.get() ); } + else + { + aNewBitmap = BlendBitmap( + aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(), + nOffY, nDstHeight, + nOffX, nDstWidth, + aBmpRect, aOutSize, + bHMirr, bVMirr, + pMapX.get(), pMapY.get() ); + } + + // #110958# Disable alpha VDev, we're doing the necessary + // stuff explicitly furher below + if (mpAlphaVDev) + mpAlphaVDev = NULL; + + DrawBitmap(aDstRect.TopLeft(), aNewBitmap); + + // #110958# Enable alpha VDev again + mpAlphaVDev = pOldVDev; } + + mbMap = bOldMap; + mpMetaFile = pOldMetaFile; } void OutputDevice::ScaleBitmap (Bitmap &rBmp, SalTwoRect &rPosAry) |