drawinglayer/source/processor2d/vclhelperbufferdevice.cxx |   13 +---
 drawinglayer/source/processor2d/vclhelperbufferdevice.hxx |    2 
 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx   |   44 +++++++++-----
 3 files changed, 35 insertions(+), 24 deletions(-)

New commits:
commit 7d74030da5b20d8f379544bdb56b26a316801c51
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Jul 21 14:40:54 2022 +0300
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Jul 22 13:26:58 2022 +0200

    tdf#144916: expand range to avoid unwanted effects on viewport edges
    
    This also allows to avoid clipping of impBufferDevice to the passed
    OutputDevice, because the expanded range couldn't otherwise be processed
    on the buffer device.
    
    Change-Id: I0d778365b09937c1a2ecee06477b0b17efcce44b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137296
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit 8c15835762f2b16e7c8f5acd2d52f562c7dec9a4)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137322
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137339
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx 
b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
index 927dacd12b65..d3b4ff10bc49 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -269,7 +269,7 @@ VDevBuffer& getVDevBuffer()
     return *aVDevBuffer.get();
 }
 
-impBufferDevice::impBufferDevice(OutputDevice& rOutDev, const 
basegfx::B2DRange& rRange)
+impBufferDevice::impBufferDevice(OutputDevice& rOutDev, const 
basegfx::B2DRange& rRange, bool bCrop)
     : mrOutDev(rOutDev)
     , mpContent(nullptr)
     , mpMask(nullptr)
@@ -277,13 +277,10 @@ impBufferDevice::impBufferDevice(OutputDevice& rOutDev, 
const basegfx::B2DRange&
 {
     basegfx::B2DRange aRangePixel(rRange);
     aRangePixel.transform(mrOutDev.GetViewTransformation());
-    const ::tools::Rectangle 
aRectPixel(static_cast<sal_Int32>(floor(aRangePixel.getMinX())),
-                                        
static_cast<sal_Int32>(floor(aRangePixel.getMinY())),
-                                        
static_cast<sal_Int32>(ceil(aRangePixel.getMaxX())),
-                                        
static_cast<sal_Int32>(ceil(aRangePixel.getMaxY())));
-    const Point aEmptyPoint;
-    maDestPixel = ::tools::Rectangle(aEmptyPoint, 
mrOutDev.GetOutputSizePixel());
-    maDestPixel.Intersection(aRectPixel);
+    maDestPixel = tools::Rectangle(floor(aRangePixel.getMinX()), 
floor(aRangePixel.getMinY()),
+                                   ceil(aRangePixel.getMaxX()), 
ceil(aRangePixel.getMaxY()));
+    if (bCrop)
+        maDestPixel.Intersection({ {}, mrOutDev.GetOutputSizePixel() });
 
     if (!isVisible())
         return;
diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx 
b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
index 90d351eac50f..1002a930681a 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
@@ -39,7 +39,7 @@ class impBufferDevice
     tools::Rectangle maDestPixel;
 
 public:
-    impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange);
+    impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange, 
bool bCrop = true);
     ~impBufferDevice();
 
     void paint(double fTrans = 0.0);
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 10845409b9ec..ba187de18cd8 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -1019,13 +1019,29 @@ AlphaMask ProcessAndBlurAlphaMask(const Bitmap& rMask, 
double fErodeDilateRadius
 
     return AlphaMask(mask.GetBitmap());
 }
+
+drawinglayer::geometry::ViewInformation2D
+expandRange(const drawinglayer::geometry::ViewInformation2D& rViewInfo, double 
nAmount)
+{
+    basegfx::B2DRange viewport(rViewInfo.getViewport());
+    viewport.grow(nAmount);
+    return { rViewInfo.getObjectTransformation(),
+             rViewInfo.getViewTransformation(),
+             viewport,
+             rViewInfo.getVisualizedPage(),
+             rViewInfo.getViewTime(),
+             rViewInfo.getExtendedInformationSequence() };
+}
 }
 
 void VclPixelProcessor2D::processGlowPrimitive2D(const 
primitive2d::GlowPrimitive2D& rCandidate)
 {
-    basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+    const double nGlowRadius(rCandidate.getGlowRadius());
+    // Avoid wrong effect on the cut-off side; so expand by radius
+    const auto aExpandedViewInfo(expandRange(getViewInformation2D(), 
nGlowRadius));
+    basegfx::B2DRange aRange(rCandidate.getB2DRange(aExpandedViewInfo));
     aRange.transform(maCurrentTransformation);
-    basegfx::B2DVector aGlowRadiusVector(rCandidate.getGlowRadius(), 0);
+    basegfx::B2DVector aGlowRadiusVector(nGlowRadius, 0);
     // Calculate the pixel size of glow radius in current transformation
     aGlowRadiusVector *= maCurrentTransformation;
     // Glow radius is the size of the halo from each side of the object. The 
halo is the
@@ -1036,8 +1052,8 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const 
primitive2d::GlowPrimitiv
     // Consider glow transparency (initial transparency near the object edge)
     const sal_uInt8 nTransparency = 
rCandidate.getGlowColor().GetTransparency();
 
-    impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
-    if (aBufferDevice.isVisible() && !aRange.isEmpty())
+    impBufferDevice aBufferDevice(*mpOutputDevice, aRange, false);
+    if (aBufferDevice.isVisible())
     {
         // remember last OutDev and set to content
         OutputDevice* pLastOutputDevice = mpOutputDevice;
@@ -1048,9 +1064,8 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const 
primitive2d::GlowPrimitiv
         process(rCandidate);
 
         // Limit the bitmap size to the visible area.
-        basegfx::B2DRange 
viewRange(getViewInformation2D().getDiscreteViewport());
         basegfx::B2DRange bitmapRange(aRange);
-        bitmapRange.intersect(viewRange);
+        bitmapRange.intersect(aExpandedViewInfo.getDiscreteViewport());
         if (!bitmapRange.isEmpty())
         {
             const tools::Rectangle aRect(
@@ -1087,19 +1102,19 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const 
primitive2d::GlowPrimitiv
 void VclPixelProcessor2D::processSoftEdgePrimitive2D(
     const primitive2d::SoftEdgePrimitive2D& rCandidate)
 {
-    // TODO: don't limit the object at view range. This is needed to not blur 
objects at window
-    // borders, where they don't end. Ideally, process the full object once at 
maximal reasonable
-    // resolution, and store the resulting alpha mask in primitive's cache; 
then reuse it later,
-    // applying the transform.
-    basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+    const double nRadius(rCandidate.getRadius());
+    // Avoid wrong effect on the cut-off side; so expand by diameter
+    const auto aExpandedViewInfo(expandRange(getViewInformation2D(), nRadius * 
2));
+
+    basegfx::B2DRange aRange(rCandidate.getB2DRange(aExpandedViewInfo));
     aRange.transform(maCurrentTransformation);
-    basegfx::B2DVector aRadiusVector(rCandidate.getRadius(), 0);
+    basegfx::B2DVector aRadiusVector(nRadius, 0);
     // Calculate the pixel size of soft edge radius in current transformation
     aRadiusVector *= maCurrentTransformation;
     // Blur radius is equal to soft edge radius
     const double fBlurRadius = aRadiusVector.getLength();
 
-    impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
+    impBufferDevice aBufferDevice(*mpOutputDevice, aRange, false);
     if (aBufferDevice.isVisible())
     {
         // remember last OutDev and set to content
@@ -1110,9 +1125,8 @@ void VclPixelProcessor2D::processSoftEdgePrimitive2D(
         process(rCandidate);
 
         // Limit the bitmap size to the visible area.
-        basegfx::B2DRange 
viewRange(getViewInformation2D().getDiscreteViewport());
         basegfx::B2DRange bitmapRange(aRange);
-        bitmapRange.intersect(viewRange);
+        bitmapRange.intersect(aExpandedViewInfo.getDiscreteViewport());
         if (!bitmapRange.isEmpty())
         {
             const tools::Rectangle aRect(

Reply via email to