diff options
author | Regina Henschel <rb.henschel@t-online.de> | 2023-06-03 14:56:29 +0200 |
---|---|---|
committer | Regina Henschel <rb.henschel@t-online.de> | 2023-06-05 17:34:57 +0200 |
commit | 6c49886ab46c53398d74610b264e5edb0332a059 (patch) | |
tree | 4be7b6fcc85f2ca9388ed0a470d035a7cb7a3c7d /basegfx | |
parent | 6014fd047a62e1a002cc27334e39e1d2e54e342f (diff) |
tdf#155549 MCGR: Recreate 'axial' from symmetric 'linear'
When exporting a shape with an axial gradient fill to OOXML, it is
converted to a linear gradient with multiple color stops. Versions
before MCGR had recreated it as axial gradient on import from OOXML.
But now LO is able to handle multiple color stops and so the linear
gradient from OOXML is imported as linear gradient in LO.
When such file is then written as ODF, the multiple color stops are
in elements in extended namespace and versions before MCGR do not
understand them. They show only the first and last color (which are
equal) and the gradient is lost.
With this patch LO converts the linear gradient back to an axial gradient
on export to ODF. The exported axial gradient is rendered in a version
with MCGR same as the linear gradient when opening the OOXML file. The
difference is, that versions without MCGR now render an axial gradient
with two colors.
Change-Id: I2b416b4cdca75d8327107a4f259d63c2e6e97ac3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152574
Tested-by: Jenkins
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Diffstat (limited to 'basegfx')
-rw-r--r-- | basegfx/source/tools/bgradient.cxx | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/basegfx/source/tools/bgradient.cxx b/basegfx/source/tools/bgradient.cxx index b7ee0780a2cc..b56ef0540d17 100644 --- a/basegfx/source/tools/bgradient.cxx +++ b/basegfx/source/tools/bgradient.cxx @@ -657,6 +657,28 @@ double BColorStops::detectPossibleOffsetAtStart() const return aColorL->getStopOffset(); } +// checks whether the color stops are symmetrical in color and offset. +bool BColorStops::isSymmetrical() const +{ + if (empty()) + return false; + if (1 == size()) + return basegfx::fTools::equal(0.5, front().getStopOffset()); + + BColorStops::const_iterator aIter(begin()); // for going forward + BColorStops::const_iterator aRIter(end()); // for going backward + --aRIter; + // We have at least two elements, so aIter <= aRIter fails before iterators no longer point to + // an element. + while (aIter <= aRIter && aIter->getStopColor().equal(aRIter->getStopColor()) + && basegfx::fTools::equal(aIter->getStopOffset(), 1.0 - aRIter->getStopOffset())) + { + ++aIter; + --aRIter; + } + return aIter > aRIter; +} + std::string BGradient::GradientStyleToString(css::awt::GradientStyle eStyle) { switch (eStyle) @@ -917,7 +939,7 @@ void BGradient::tryToRecreateBorder(basegfx::BColorStops* pAssociatedTransparenc pAssociatedTransparencyStops->removeSpaceAtStart(fOffset); // ...and create border value - SetBorder(static_cast<sal_uInt16>(fOffset * 100.0)); + SetBorder(static_cast<sal_uInt16>(std::lround(fOffset * 100.0))); } if (bIsAxial) @@ -971,6 +993,35 @@ void BGradient::tryToApplyStartEndIntensity() SetStartIntens(100); SetEndIntens(100); } + +void BGradient::tryToConvertToAxial() +{ + if (css::awt::GradientStyle_LINEAR != GetGradientStyle() || 0 != GetBorder() + || GetColorStops().empty()) + return; + + if (!GetColorStops().isSymmetrical()) + return; + + SetGradientStyle(css::awt::GradientStyle_AXIAL); + + // Stretch the first half of the color stops to double width + // and collect them in a new color stops vector. + BColorStops aAxialColorStops; + aAxialColorStops.reserve(std::ceil(GetColorStops().size() / 2.0)); + BColorStops::const_iterator aIter(GetColorStops().begin()); + while (basegfx::fTools::lessOrEqual(aIter->getStopOffset(), 0.5)) + { + BColorStop aNextStop(std::clamp((*aIter).getStopOffset() * 2.0, 0.0, 1.0), + (*aIter).getStopColor()); + aAxialColorStops.push_back(aNextStop); + ++aIter; + } + // Axial gradients have outmost color as last color stop. + aAxialColorStops.reverseColorStops(); + + SetColorStops(aAxialColorStops); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |