summaryrefslogtreecommitdiff
path: root/basegfx
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2023-02-21 18:35:39 +0100
committerAndras Timar <andras.timar@collabora.com>2023-05-15 21:38:52 +0200
commitca8a7fe542f8029d82dcafdc776ecc29752f286f (patch)
treedce4fdba0633b94efd1ce5af2fdc4c4d916778a7 /basegfx
parent2486e9254b5fe28f82bc2f2e3c5b2ebd75af0f99 (diff)
MCGR: Adapted GradientLinear to make use of MCGR
Added to make GradientLinear work using the MCGR as 1st of six types. Had to do quite some tickeling to get it all work, but looks good. Five more to go, already started to put some things to tooling to make re-usable for the other types. Besides adapting this the main change is that the adaption of defined step-count (versus automatic) has to be done in modifyBColor now instead of the back-mapping methods (e.g. getLinearGradientAlpha). It is still 100% backward-compatible, so as long as there is no source using this it will stay invisible - by purpose. I started to do quite some tests (and fixes/ adaptions in consequence), see the static variable nUseGradientSteps. If you want to play with this, you might set it to '1' instead of '0' and use a linear gradient on an object. Change-Id: I9d61934defb0674456247f2879f0a89b6a5e50f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147413 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
Diffstat (limited to 'basegfx')
-rw-r--r--basegfx/source/tools/gradienttools.cxx101
1 files changed, 96 insertions, 5 deletions
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx
index b3bb18f918da..a8d36b9f543d 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -21,6 +21,8 @@
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <algorithm>
#include <cmath>
namespace basegfx
@@ -261,6 +263,95 @@ namespace basegfx
namespace utils
{
+ BColor modifyBColor(
+ const ColorSteps& rColorSteps,
+ double fScaler,
+ sal_uInt32 nRequestedSteps)
+ {
+ // no color at all, done
+ if (rColorSteps.empty())
+ return BColor();
+
+ // outside range -> at start
+ if (fScaler <= 0.0)
+ return rColorSteps.front().getColor();
+
+ // outside range -> at end
+ if (fScaler >= 1.0)
+ return rColorSteps.back().getColor();
+
+ // special case for the 'classic' case with just two colors:
+ // we can optimize that and keep the speed/ressources low
+ // by avoiding some calculatins and an O(log(N)) array access
+ if (2 == rColorSteps.size())
+ {
+ const basegfx::BColor aCStart(rColorSteps.front().getColor());
+ const basegfx::BColor aCEnd(rColorSteps.back().getColor());
+ const sal_uInt32 nSteps(
+ calculateNumberOfSteps(
+ nRequestedSteps,
+ aCStart,
+ aCEnd));
+
+ return basegfx::interpolate(
+ aCStart,
+ aCEnd,
+ nSteps > 1 ? floor(fScaler * nSteps) / double(nSteps - 1) : fScaler);
+ }
+
+ // access needed spot in sorted array using binary search
+ // NOTE: This *seems* slow(er) when developing compared to just
+ // looping/accessing, but that's just due to the extensive
+ // debug test code created by the stl. In a pro version,
+ // all is good/fast as expected
+ const auto upperBound(
+ std::lower_bound(
+ rColorSteps.begin(),
+ rColorSteps.end(),
+ ColorStep(fScaler),
+ [](const ColorStep& x, const ColorStep& y) { return x.getOffset() < y.getOffset(); }));
+
+ // no upper bound, done
+ if (rColorSteps.end() == upperBound)
+ return rColorSteps.back().getColor();
+
+ // lower bound is one entry back
+ const auto lowerBound(upperBound - 1);
+
+ // no lower bound, done
+ if (rColorSteps.end() == lowerBound)
+ return rColorSteps.back().getColor();
+
+ // we have lower and upper bound, get colors
+ const BColor aCStart(lowerBound->getColor());
+ const BColor aCEnd(upperBound->getColor());
+
+ // when there are just two color steps this cannot happen, but when using
+ // a range of colors this *may* be used inside the range to represent
+ // single-colored regions inside a ColorRange. Use that color & done
+ if (aCStart == aCEnd)
+ return aCStart;
+
+ // calculate number of steps
+ const sal_uInt32 nSteps(
+ calculateNumberOfSteps(
+ nRequestedSteps,
+ aCStart,
+ aCEnd));
+
+ // get offsets and scale to new [0.0 .. 1.0] relative range for
+ // partial outer range
+ const double fOffsetStart(lowerBound->getOffset());
+ const double fOffsetEnd(upperBound->getOffset());
+ const double fAdaptedScaler((fScaler - fOffsetStart) / (fOffsetEnd - fOffsetStart));
+
+ // interpolate & evtl. apply steps
+ return interpolate(
+ aCStart,
+ aCEnd,
+ nSteps > 1 ? floor(fAdaptedScaler * nSteps) / double(nSteps - 1) : fAdaptedScaler);
+ }
+
sal_uInt32 calculateNumberOfSteps(
sal_uInt32 nRequestedSteps,
const BColor& rStart,
@@ -392,12 +483,12 @@ namespace basegfx
return 1.0; // end value for outside
}
- const sal_uInt32 nSteps(rGradInfo.getRequestedSteps());
+ // const sal_uInt32 nSteps(rGradInfo.getRequestedSteps());
- if(nSteps)
- {
- return floor(aCoor.getY() * nSteps) / double(nSteps - 1);
- }
+ // if(nSteps)
+ // {
+ // return floor(aCoor.getY() * nSteps) / double(nSteps - 1);
+ // }
return aCoor.getY();
}