summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2023-04-14 16:29:18 +0200
committerAndras Timar <andras.timar@collabora.com>2023-05-15 21:38:54 +0200
commit848feced631f6f457c867fe4eb8ad97577f8b7f3 (patch)
tree1c1a38ada8bbb6fed97a348374071254f4724396 /oox
parent1adcb98d867903f2f8446bb613d29ec554e2c20c (diff)
MCGR: 1st corrections to gradient export, transparency
Changed Alpha export from using Red component of used BColor too use luminance, that will be more safe if we evtl use same gradients for this in the future. Added evtl. needed inversion for gradient exports, also emulation of our 'axial' type. Change-Id: I245959bf1602174f978848e1a02444b4b105f896 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150416 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
Diffstat (limited to 'oox')
-rw-r--r--oox/source/export/drawingml.cxx115
1 files changed, 92 insertions, 23 deletions
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index f75ef46ed019..3fa79f0b7259 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -627,6 +627,15 @@ bool DrawingML::WriteSchemeColor(OUString const& rPropertyName, const uno::Refer
return true;
}
+void DrawingML::WriteGradientStop2(double fOffset, const basegfx::BColor& rColor, const basegfx::BColor& rAlpha)
+{
+ mpFS->startElementNS(XML_a, XML_gs, XML_pos, OString::number(static_cast<sal_uInt32>(fOffset * 100000)));
+ WriteColor(
+ ::Color(rColor),
+ static_cast<sal_Int32>((1.0 - rAlpha.luminance()) * oox::drawingml::MAX_PERCENT));
+ mpFS->endElementNS( XML_a, XML_gs );
+}
+
void DrawingML::WriteGradientStop(sal_uInt16 nStop, ::Color nColor, sal_Int32 nAlpha)
{
mpFS->startElementNS(XML_a, XML_gs, XML_pos, OString::number(nStop * 1000));
@@ -844,35 +853,98 @@ void DrawingML::WriteGradientFill2(
// method (at import time) will be exported again
basegfx::utils::synchronizeColorStops(aColorStops, aAlphaStops, aSingleColor, aSingleAlpha);
- if (aColorStops.size() == aAlphaStops.size())
+ if (aColorStops.size() != aAlphaStops.size())
{
- // export GradientStops (with alpha)
- mpFS->startElementNS(XML_a, XML_gsLst);
+ // this is an error - synchronizeColorStops above *has* to create that
+ // state, see desciption there (!)
+ assert(false && "oox::WriteGradientFill: non-synchronized gradients (!)");
+ return;
+ }
- basegfx::ColorStops::const_iterator aCurrColor(aColorStops.begin());
- basegfx::ColorStops::const_iterator aCurrAlpha(aAlphaStops.begin());
+ bool bRadialOrEllipticalOrRectOrSquare(false);
+ bool bLinear(false);
+ bool bAxial(false);
- while (aCurrColor != aColorStops.end() && aCurrAlpha != aAlphaStops.end())
+ switch (aGradient.Style)
+ {
+ case awt::GradientStyle_LINEAR:
+ {
+ // remember being linear, nothing else to be done
+ bLinear = true;
+ break;
+ }
+ case awt::GradientStyle_AXIAL:
{
- WriteGradientStop(
- static_cast<sal_uInt16>(aCurrColor->getStopOffset() * 100.0),
- ::Color(aCurrColor->getStopColor()),
- sal_Int32(::Color(aCurrAlpha->getStopColor())));
- aCurrColor++;
- aCurrAlpha++;
+ // we need to 'double' the gradient to make it appear as what we call
+ // 'axial', but also scale and mirror in doing so
+ basegfx::ColorStops aNewColorStops;
+ basegfx::ColorStops aNewAlphaStops;
+
+ // add mirrored gadients, scaled to [0.0 .. 0.5]
+ basegfx::ColorStops::const_reverse_iterator aRevCurrColor(aColorStops.rbegin());
+ basegfx::ColorStops::const_reverse_iterator aRevCurrAlpha(aAlphaStops.rbegin());
+
+ while (aRevCurrColor != aColorStops.rend() && aRevCurrAlpha != aAlphaStops.rend())
+ {
+ aNewColorStops.emplace_back((1.0 - aRevCurrColor->getStopOffset()) * 0.5, aRevCurrColor->getStopColor());
+ aNewAlphaStops.emplace_back((1.0 - aRevCurrAlpha->getStopOffset()) * 0.5, aRevCurrAlpha->getStopColor());
+ aRevCurrColor++;
+ aRevCurrAlpha++;
+ }
+
+ // add non-mirrored gradients, translated and scaled to [0.5 .. 1.0]
+ basegfx::ColorStops::const_iterator aCurrColor(aColorStops.begin());
+ basegfx::ColorStops::const_iterator aCurrAlpha(aAlphaStops.begin());
+
+ while (aCurrColor != aColorStops.end() && aCurrAlpha != aAlphaStops.end())
+ {
+ aNewColorStops.emplace_back((aCurrColor->getStopOffset() * 0.5) + 0.5, aCurrColor->getStopColor());
+ aNewAlphaStops.emplace_back((aCurrAlpha->getStopOffset() * 0.5) + 0.5, aCurrAlpha->getStopColor());
+ aCurrColor++;
+ aCurrAlpha++;
+ }
+
+ aColorStops = aNewColorStops;
+ aAlphaStops = aNewAlphaStops;
+
+ // remember being axial
+ bAxial = true;
+ break;
}
+ default:
+ // case awt::GradientStyle_RADIAL:
+ // case awt::GradientStyle_ELLIPTICAL:
+ // case awt::GradientStyle_RECT:
+ // case awt::GradientStyle_SQUARE:
+ {
+ // all these types need the gadiens to be mirrored
+ basegfx::utils::reverseColorStops(aColorStops);
+ basegfx::utils::reverseColorStops(aAlphaStops);
- mpFS->endElementNS( XML_a, XML_gsLst );
+ bRadialOrEllipticalOrRectOrSquare = true;
+ break;
+ }
}
- else
+
+ // export GradientStops (with alpha)
+ mpFS->startElementNS(XML_a, XML_gsLst);
+
+ basegfx::ColorStops::const_iterator aCurrColor(aColorStops.begin());
+ basegfx::ColorStops::const_iterator aCurrAlpha(aAlphaStops.begin());
+
+ while (aCurrColor != aColorStops.end() && aCurrAlpha != aAlphaStops.end())
{
- // this is an error - synchronizeColorStops above *has* to create that
- // state, see desciption there (!)
- assert(false && "oox::WriteGradientFill: non-synchronized gradients (!)");
+ WriteGradientStop2(
+ aCurrColor->getStopOffset(),
+ aCurrColor->getStopColor(),
+ aCurrAlpha->getStopColor());
+ aCurrColor++;
+ aCurrAlpha++;
}
- if (awt::GradientStyle_LINEAR == aGradient.Style ||
- awt::GradientStyle_AXIAL == aGradient.Style)
+ mpFS->endElementNS( XML_a, XML_gsLst );
+
+ if (bLinear || bAxial)
{
// cases where gradient rotation has to be exported
mpFS->singleElementNS(
@@ -880,10 +952,7 @@ void DrawingML::WriteGradientFill2(
OString::number(((3600 - aGradient.Angle + 900) * 6000) % 21600000));
}
- if (awt::GradientStyle_RADIAL == aGradient.Style ||
- awt::GradientStyle_ELLIPTICAL == aGradient.Style ||
- awt::GradientStyle_RECT == aGradient.Style ||
- awt::GradientStyle_SQUARE == aGradient.Style)
+ if (bRadialOrEllipticalOrRectOrSquare)
{
// cases where gradient path has to be exported
const bool bCircle(aGradient.Style == awt::GradientStyle_RADIAL ||