summaryrefslogtreecommitdiff
path: root/basegfx/source/tools/bgradient.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basegfx/source/tools/bgradient.cxx')
-rw-r--r--basegfx/source/tools/bgradient.cxx53
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: */