diff options
Diffstat (limited to 'basegfx/source/tools/bgradient.cxx')
-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: */ |