drawinglayer/source/processor2d/vclhelperbufferdevice.cxx |   11 +--
 drawinglayer/source/processor2d/vclhelperbufferdevice.hxx |    2 
 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx   |   42 +++++++++-----
 3 files changed, 34 insertions(+), 21 deletions(-)

New commits:
commit f78588a59efc7813b35e60222efcc76f1116468c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Jul 21 14:40:54 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Fri Jul 22 06:36:11 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>

diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx 
b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
index 7f20d094b446..362293438dd8 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
@@ -285,18 +285,17 @@ 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)
     , mpAlpha(nullptr)
 {
     basegfx::B2DRange aRangePixel(rRange);
     aRangePixel.transform(mrOutDev.GetViewTransformation());
-    const ::tools::Rectangle aRectPixel(floor(aRangePixel.getMinX()), 
floor(aRangePixel.getMinY()),
-                                        ceil(aRangePixel.getMaxX()), 
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 3b5d30415cc2..99585b05b141 100644
--- a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
+++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
@@ -38,7 +38,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 722cd6362807..087f6bcedb37 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -1026,13 +1026,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.getReducedDisplayQuality() };
+}
 }
 
 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
@@ -1043,7 +1059,7 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const 
primitive2d::GlowPrimitiv
     // Consider glow transparency (initial transparency near the object edge)
     const sal_uInt8 nAlpha = rCandidate.getGlowColor().GetAlpha();
 
-    impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
+    impBufferDevice aBufferDevice(*mpOutputDevice, aRange, false);
     if (aBufferDevice.isVisible())
     {
         // remember last OutDev and set to content
@@ -1055,9 +1071,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(
@@ -1094,19 +1109,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
@@ -1117,9 +1132,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