diff options
author | Armin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de> | 2023-02-21 18:35:39 +0100 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@me.com> | 2023-02-22 09:13:20 +0000 |
commit | c4f252035cd71f9a1b226e69095cc9f4e8f19f3e (patch) | |
tree | 3fba6649662028a15288bbd803acea5a73f500ad /basegfx | |
parent | 0c14b1ba0d560c1de120d2562da6b24db9802149 (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.cxx | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx index b2635b3f09cc..43cca3f1c7ea 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(); } |