summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2022-07-21 14:40:54 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2022-07-22 06:36:11 +0200
commitf78588a59efc7813b35e60222efcc76f1116468c (patch)
treecee535cf8f4efe949f8e43285dd5dd3cef3ba402
parentba00d997ddd6867c3f2bd4909625a91bf4db590b (diff)
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.kaganski@collabora.com> (cherry picked from commit 8c15835762f2b16e7c8f5acd2d52f562c7dec9a4) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137322 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
-rw-r--r--drawinglayer/source/processor2d/vclhelperbufferdevice.cxx11
-rw-r--r--drawinglayer/source/processor2d/vclhelperbufferdevice.hxx2
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx42
3 files changed, 34 insertions, 21 deletions
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(