libreoffice/bsc1189813.patch

306 lines
14 KiB
Diff

From 1d5dc93089ee2e9b3b3761fd7b5558d55ac8a1fa Mon Sep 17 00:00:00 2001
From: Miklos Vajna <vmiklos@collabora.com>
Date: Mon, 20 Sep 2021 11:26:53 +0200
Subject: [PATCH] tdf#144091 svx: fix unwanted blur of shadow from table cell
fill
Initial render support for shadows of table shapes were added in commit
a75bf43a8d6c5dec6dcc86908c142ceec541aa8c (tdf#129961 svx: add rendering
for table shadow as direct format, 2020-12-02).
That already noticed a trick with the shadow of table shapes: the shadow
is generate from the cell fill and the border, but not from the text.
An additional trick is that when blur is enabled for the table shape's
shadow, then only the border should be blurred, not the cell fill.
In the bug document's case, the effective cell background was gray, with
a semi-transparent red shadow. We used to render cc0000 with blur and
cccccc without blur, now we correctly render cca3a3, matching
PowerPoint.
(cherry picked from commit 37a52d30bbfcf1d073779b50139c4dafa507be4b)
Conflicts:
drawinglayer/source/primitive2d/shadowprimitive2d.cxx
drawinglayer/source/tools/primitive2dxmldump.cxx
include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx
Change-Id: I7326a5f6254cf19b2d05181084c78e734ff7a7b4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122357
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Related: tdf#144091 svx: fix interaction of transp cell fill and transp shadow
This is a follow-up to commit 37a52d30bbfcf1d073779b50139c4dafa507be4b
(tdf#144091 svx: fix unwanted blur of shadow from table cell fill,
2021-09-20), where it turned out that the original bugdoc was just a
special case of almost full transparency (80%), that's why avoiding the
blur fixed the problem.
A more general approach instead is to multiply the alpha or the cell
fill of table shapes and the alpha of the shadow itself. The end result
is the same (80% transparency) for the first bugdoc, but this gives back
the blur on the second bugdoc.
(cherry picked from commit 00fa364a2403dc23a786d3f91fde06e10b3a4a9a)
Conflicts:
drawinglayer/source/primitive2d/shadowprimitive2d.cxx
drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx
svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
Change-Id: I63560e3a73473c70157ecee8365ec7154217f269
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122565
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
---
.../processor2d/vclpixelprocessor2d.cxx | 2 +-
.../source/tools/primitive2dxmldump.cxx | 33 +++++-
.../primitive2d/baseprimitive2d.hxx | 11 ++
.../sdr/primitive2d/sdrdecompositiontools.cxx | 72 ++++++++++---
svx/source/table/viewcontactoftableobj.cxx | 16 ++-
vcl/source/bitmap/bitmapfilter.cxx | 5 +
9 files changed, 221 insertions(+), 21 deletions(-)
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 9bdbf95a015b..5e6c6a73cd60 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -1037,7 +1037,7 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitiv
const sal_uInt8 nAlpha = rCandidate.getGlowColor().GetAlpha();
impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
- if (aBufferDevice.isVisible())
+ if (aBufferDevice.isVisible() && !aRange.isEmpty())
{
// remember last OutDev and set to content
OutputDevice* pLastOutputDevice = mpOutputDevice;
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx
index 7c5e5771d9bc..1e99ac91ed54 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -569,11 +569,42 @@ void Primitive2dXmlDump::decomposeAndWrite(
break;
}
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
+ {
+ // ModifiedColorPrimitive2D.
+ rWriter.startElement("modifiedColor");
+ drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
+ pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
+ drawinglayer::geometry::ViewInformation2D());
+ decomposeAndWrite(aPrimitiveContainer, rWriter);
+ rWriter.endElement();
+ break;
+ }
+
default:
{
- rWriter.startElement("unhandled");
+ OString aName("unhandled");
+ switch (nId)
+ {
+ case PRIMITIVE2D_ID_RANGE_SVX | 14: // PRIMITIVE2D_ID_SDRCELLPRIMITIVE2D
+ {
+ aName = "sdrCell";
+ break;
+ }
+ }
+ rWriter.startElement(aName);
rWriter.attribute("id", OUStringToOString(sCurrentElementTag, RTL_TEXTENCODING_UTF8));
rWriter.attribute("idNumber", nId);
+
+ auto pBufferedDecomposition
+ = dynamic_cast<const BufferedDecompositionPrimitive2D*>(pBasePrimitive);
+ if (pBufferedDecomposition)
+ {
+ rWriter.attribute(
+ "transparenceForShadow",
+ OString::number(pBufferedDecomposition->getTransparenceForShadow()));
+ }
+
drawinglayer::primitive2d::Primitive2DContainer aPrimitiveContainer;
pBasePrimitive->get2DDecomposition(aPrimitiveContainer,
drawinglayer::geometry::ViewInformation2D());
diff --git a/include/drawinglayer/primitive2d/baseprimitive2d.hxx b/include/drawinglayer/primitive2d/baseprimitive2d.hxx
index 7619e04e5279..f697886c1ac5 100644
--- a/include/drawinglayer/primitive2d/baseprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/baseprimitive2d.hxx
@@ -204,6 +204,10 @@ private:
/// a sequence used for buffering the last create2DDecomposition() result
Primitive2DContainer maBuffered2DDecomposition;
+ /// When a shadow wraps a list of primitives, this primitive wants to influence the transparency
+ /// of the shadow.
+ sal_uInt16 mnTransparenceForShadow = 0;
+
protected:
/** access methods to maBuffered2DDecomposition. The usage of this methods may allow
later thread-safe stuff to be added if needed. Only to be used by getDecomposition()
@@ -236,6 +240,13 @@ public:
virtual void
get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor,
const geometry::ViewInformation2D& rViewInformation) const override;
+
+ void setTransparenceForShadow(sal_uInt16 nTransparenceForShadow)
+ {
+ mnTransparenceForShadow = nTransparenceForShadow;
+ }
+
+ sal_uInt16 getTransparenceForShadow() const { return mnTransparenceForShadow; }
};
} // end of namespace drawinglayer::primitive2d
diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
index dcff748ea60f..1cd60e75d925 100644
--- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
+++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
@@ -545,7 +545,6 @@ basegfx::B2DRange getTextAnchorRange(const attribute::SdrTextAttribute& rText,
{
if(!rContent.empty())
{
- Primitive2DContainer aRetval(2);
basegfx::B2DHomMatrix aShadowOffset;
{
@@ -576,25 +575,66 @@ basegfx::B2DRange getTextAnchorRange(const attribute::SdrTextAttribute& rText,
}
// create shadow primitive and add content
- aRetval[0] = Primitive2DReference(
- new ShadowPrimitive2D(
- aShadowOffset,
- rShadow.getColor(),
- rShadow.getBlur(),
- (pContentForShadow ? *pContentForShadow : rContent)));
-
- if(0.0 != rShadow.getTransparence())
+ const Primitive2DContainer& rContentForShadow
+ = pContentForShadow ? *pContentForShadow : rContent;
+ int nContentWithTransparence = std::count_if(
+ rContentForShadow.begin(), rContentForShadow.end(),
+ [](const Primitive2DReference& xChild) {
+ auto pChild = dynamic_cast<BufferedDecompositionPrimitive2D*>(xChild.get());
+ return pChild && pChild->getTransparenceForShadow() != 0;
+ });
+ if (nContentWithTransparence == 0)
{
- // create SimpleTransparencePrimitive2D
- const Primitive2DContainer aTempContent { aRetval[0] };
-
+ Primitive2DContainer aRetval(2);
aRetval[0] = Primitive2DReference(
- new UnifiedTransparencePrimitive2D(
- aTempContent,
- rShadow.getTransparence()));
+ new ShadowPrimitive2D(
+ aShadowOffset,
+ rShadow.getColor(),
+ rShadow.getBlur(),
+ (pContentForShadow ? *pContentForShadow : rContent)));
+
+ if(0.0 != rShadow.getTransparence())
+ {
+ // create SimpleTransparencePrimitive2D
+ const Primitive2DContainer aTempContent { aRetval[0] };
+
+ aRetval[0] = Primitive2DReference(
+ new UnifiedTransparencePrimitive2D(
+ aTempContent,
+ rShadow.getTransparence()));
+ }
+
+ aRetval[1] = Primitive2DReference(new GroupPrimitive2D(rContent));
+ return aRetval;
+ }
+
+ Primitive2DContainer aRetval;
+ for (const auto& xChild : rContentForShadow)
+ {
+ double fChildTransparence = 0.0;
+ auto pChild = dynamic_cast<BufferedDecompositionPrimitive2D*>(xChild.get());
+ if (pChild)
+ {
+ fChildTransparence = pChild->getTransparenceForShadow();
+ fChildTransparence /= 100;
+ }
+ aRetval.push_back(Primitive2DReference(
+ new ShadowPrimitive2D(aShadowOffset, rShadow.getColor(), rShadow.getBlur(),
+ { xChild })));
+ if (rShadow.getTransparence() != 0.0 || fChildTransparence != 0.0)
+ {
+ Primitive2DContainer aTempContent{ aRetval.back() };
+
+ double fChildAlpha = 1.0 - fChildTransparence;
+ double fShadowAlpha = 1.0 - rShadow.getTransparence();
+ double fTransparence = 1.0 - fChildAlpha * fShadowAlpha;
+ aRetval.back() = Primitive2DReference(new UnifiedTransparencePrimitive2D(
+ std::move(aTempContent), fTransparence));
+ }
}
- aRetval[1] = Primitive2DReference(new GroupPrimitive2D(rContent));
+ aRetval.push_back(
+ Primitive2DReference(new GroupPrimitive2D(rContent)));
return aRetval;
}
else
diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 967bfe820738..41d60d7652f8 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -39,6 +39,7 @@
#include <svx/sdooitm.hxx>
#include <vcl/canvastools.hxx>
#include <o3tl/unit_conversion.hxx>
+#include <svx/xfltrit.hxx>
#include <cell.hxx>
#include "tablelayouter.hxx"
@@ -326,10 +327,19 @@ namespace sdr::contact
aAttribute
= drawinglayer::primitive2d::createNewSdrFillTextAttribute(
rCellItemSet, nullptr);
+ rtl::Reference pCellReference
+ = new drawinglayer::primitive2d::SdrCellPrimitive2D(
+ aCellMatrix, aAttribute);
+
+ sal_uInt16 nTransparence(
+ rCellItemSet.Get(XATTR_FILLTRANSPARENCE).GetValue());
+ if (nTransparence != 0)
+ {
+ pCellReference->setTransparenceForShadow(nTransparence);
+ }
+
const drawinglayer::primitive2d::Primitive2DReference
- xCellReference(
- new drawinglayer::primitive2d::SdrCellPrimitive2D(
- aCellMatrix, aAttribute));
+ xCellReference(pCellReference);
aRetvalForShadow.append(xCellReference);
}
}
diff --git a/vcl/source/bitmap/bitmapfilter.cxx b/vcl/source/bitmap/bitmapfilter.cxx
index f2020539e04d..9ede4e578b10 100644
--- a/vcl/source/bitmap/bitmapfilter.cxx
+++ b/vcl/source/bitmap/bitmapfilter.cxx
@@ -19,6 +19,11 @@ BitmapFilter::~BitmapFilter() {}
bool BitmapFilter::Filter(BitmapEx& rBmpEx, BitmapFilter const& rFilter)
{
+ if (rBmpEx.IsEmpty())
+ {
+ return true;
+ }
+
BitmapEx aTmpBmpEx(rFilter.execute(rBmpEx));
if (aTmpBmpEx.IsEmpty())
--
2.31.1