From 1db7decf3fb172542f5fce03ce7bf0cb310d1ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Fri, 3 Jul 2020 16:02:00 +0200 Subject: [PATCH] limit bitmap size for glow/softedge effects to visible area (tdf#134237) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When zooming in the bitmap can become huge, requiring a lot of processing, most of it not being used. Change-Id: I0a4907f5cf23ab7316fed8568924fe76c744b81a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97872 Tested-by: Jenkins Reviewed-by: Luboš Luňák --- .../processor2d/vclpixelprocessor2d.cxx | 83 ++++++++++++------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index b91bf57c360d..cec0ed29eaf6 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -1002,26 +1002,38 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitiv mpOutputDevice->SetAntialiasing(AntialiasingFlags::NONE); mpOutputDevice->Erase(); process(rCandidate); - const tools::Rectangle aRect(static_cast(std::floor(aRange.getMinX())), - static_cast(std::floor(aRange.getMinY())), - static_cast(std::ceil(aRange.getMaxX())), - static_cast(std::ceil(aRange.getMaxY()))); - BitmapEx bmpEx = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize()); - mpOutputDevice->SetAntialiasing(aPrevAA); - AlphaMask mask - = ProcessAndBlurAlphaMask(bmpEx.GetAlpha(), fBlurRadius, fBlurRadius, nTransparency); + // Limit the bitmap size to the visible area. + basegfx::B2DRange viewRange(getViewInformation2D().getDiscreteViewport()); + basegfx::B2DRange bitmapRange(aRange); + bitmapRange.intersect(viewRange); + if (!bitmapRange.isEmpty()) + { + const tools::Rectangle aRect(static_cast(std::floor(bitmapRange.getMinX())), + static_cast(std::floor(bitmapRange.getMinY())), + static_cast(std::ceil(bitmapRange.getMaxX())), + static_cast(std::ceil(bitmapRange.getMaxY()))); + BitmapEx bmpEx = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize()); + mpOutputDevice->SetAntialiasing(aPrevAA); - // The end result is the bitmap filled with glow color and blurred 8-bit alpha mask - const basegfx::BColor aGlowColor( - maBColorModifierStack.getModifiedColor(rCandidate.getGlowColor().getBColor())); - Bitmap bmp = bmpEx.GetBitmap(); - bmp.Erase(Color(aGlowColor)); - BitmapEx result(bmp, mask); + AlphaMask mask = ProcessAndBlurAlphaMask(bmpEx.GetAlpha(), fBlurRadius, fBlurRadius, + nTransparency); - // back to old OutDev - mpOutputDevice = pLastOutputDevice; - mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result); + // The end result is the bitmap filled with glow color and blurred 8-bit alpha mask + const basegfx::BColor aGlowColor( + maBColorModifierStack.getModifiedColor(rCandidate.getGlowColor().getBColor())); + Bitmap bmp = bmpEx.GetBitmap(); + bmp.Erase(Color(aGlowColor)); + BitmapEx result(bmp, mask); + + // back to old OutDev + mpOutputDevice = pLastOutputDevice; + mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result); + } + else + { + mpOutputDevice = pLastOutputDevice; + } } else SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible"); @@ -1053,23 +1065,34 @@ void VclPixelProcessor2D::processSoftEdgePrimitive2D( // because it would result in poor quality in areas not affected by the effect process(rCandidate); - const tools::Rectangle aRect(static_cast(std::floor(aRange.getMinX())), - static_cast(std::floor(aRange.getMinY())), - static_cast(std::ceil(aRange.getMaxX())), - static_cast(std::ceil(aRange.getMaxY()))); - BitmapEx bitmap = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize()); + // Limit the bitmap size to the visible area. + basegfx::B2DRange viewRange(getViewInformation2D().getDiscreteViewport()); + basegfx::B2DRange bitmapRange(aRange); + bitmapRange.intersect(viewRange); + if (!bitmapRange.isEmpty()) + { + const tools::Rectangle aRect(static_cast(std::floor(bitmapRange.getMinX())), + static_cast(std::floor(bitmapRange.getMinY())), + static_cast(std::ceil(bitmapRange.getMaxX())), + static_cast(std::ceil(bitmapRange.getMaxY()))); + BitmapEx bitmap = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize()); - AlphaMask aMask = bitmap.GetAlpha(); - AlphaMask blurMask = ProcessAndBlurAlphaMask(aMask, -fBlurRadius, fBlurRadius, 0); + AlphaMask aMask = bitmap.GetAlpha(); + AlphaMask blurMask = ProcessAndBlurAlphaMask(aMask, -fBlurRadius, fBlurRadius, 0); - aMask.BlendWith(blurMask); + aMask.BlendWith(blurMask); - // The end result is the original bitmap with blurred 8-bit alpha mask - BitmapEx result(bitmap.GetBitmap(), aMask); + // The end result is the original bitmap with blurred 8-bit alpha mask + BitmapEx result(bitmap.GetBitmap(), aMask); - // back to old OutDev - mpOutputDevice = pLastOutputDevice; - mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result); + // back to old OutDev + mpOutputDevice = pLastOutputDevice; + mpOutputDevice->DrawBitmapEx(aRect.TopLeft(), result); + } + else + { + mpOutputDevice = pLastOutputDevice; + } } else SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible");