summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basegfx/source/tools/gradienttools.cxx115
-rw-r--r--drawinglayer/qa/unit/vclpixelprocessor2d.cxx5
-rw-r--r--drawinglayer/source/attribute/fillgradientattribute.cxx116
-rw-r--r--drawinglayer/source/primitive3d/textureprimitive3d.cxx9
-rw-r--r--drawinglayer/source/texture/texture.cxx46
-rw-r--r--drawinglayer/source/tools/wmfemfhelper.cxx8
-rw-r--r--include/basegfx/utils/gradienttools.hxx31
-rw-r--r--include/drawinglayer/attribute/fillgradientattribute.hxx21
-rw-r--r--svx/source/sdr/primitive2d/sdrattributecreator.cxx45
-rw-r--r--svx/source/xoutdev/xtabgrdt.cxx8
-rw-r--r--sw/source/uibase/docvw/HeaderFooterWin.cxx7
-rw-r--r--sw/source/uibase/docvw/ShadowOverlayObject.cxx20
12 files changed, 264 insertions, 167 deletions
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx
index f35f91f5a79a..5743f71ad980 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -263,6 +263,121 @@ namespace basegfx
namespace utils
{
+ /* Tooling method to guarantee sort and correctness for
+ the given ColorSteps vector.
+ At return, the following conditions are guaranteed:
+ - contains no ColorSteps with offset < 0.0 (will
+ be removed)
+ - contains no ColorSteps with offset > 0.0 (will
+ be removed)
+ - contains no ColorSteps with identical offset
+ (will be removed, 1st one wins)
+ - will be sorted from lowest offset to highest
+ - if all colors are the same, the content will
+ be reducved to a single entry with offset 0.0
+ (StartColor)
+
+ Some more notes:
+ - It can happen that the result is empty
+ - It is allowed to have consecutive entries with
+ the same color, this represents single-color
+ regions inside the gradient
+ - A entry with 0.0 is not required or forced, so
+ no 'StartColor' is required on this level
+ - A entry with 1.0 is not required or forced, so
+ no 'EndColor' is required on this level
+
+ All this is done in one run (sort + O(N)) without
+ creating a copy of the data in any form
+ */
+ void sortAndCorrectColorSteps(ColorSteps& rColorSteps)
+ {
+ // no content, we are done
+ if (rColorSteps.empty())
+ return;
+
+ if (1 == rColorSteps.size())
+ {
+ // no gradient at all, but preserve given color
+ // and force it to be the StartColor
+ rColorSteps[0] = ColorStep(0.0, rColorSteps[0].getColor());
+ }
+
+ // start with sorting the input data. Remember that
+ // this preserves the order of equal entries, where
+ // equal is defined here by offset (see use operator==)
+ std::sort(rColorSteps.begin(), rColorSteps.end());
+
+ // preapare status values
+ bool bSameColorInit(false);
+ bool bAllTheSameColor(true);
+ basegfx::BColor aFirstColor;
+ size_t write(0);
+
+ // use the paradigm of a band machine with two heads, read
+ // and write with write <= read all the time. Step over the
+ // data using read and check for valid entry. If valid, decide
+ // how to keep it
+ for (size_t read(0); read < rColorSteps.size(); read++)
+ {
+ // get offset of entry at read position
+ const double rOff(rColorSteps[read].getOffset());
+
+ // step over < 0 values
+ if (basegfx::fTools::less(rOff, 0.0))
+ continue;
+
+ // step over > 1 values; even break, since all following
+ // entries will also be bigger due to being sorted, so done
+ if (basegfx::fTools::more(rOff, 1.0))
+ break;
+
+ // entry is valid value at read position
+
+ // check/init for all-the-same color
+ if(bSameColorInit)
+ {
+ // already initialized, compare
+ bAllTheSameColor = bAllTheSameColor && aFirstColor == rColorSteps[read].getColor();
+ }
+ else
+ {
+ // do initialize, remember 1st valid color
+ bSameColorInit = true;
+ aFirstColor = rColorSteps[read].getColor();
+ }
+
+ // copy if write target is empty (write at start) or when
+ // write target is different to read
+ if (0 == write || rOff != rColorSteps[write-1].getOffset())
+ {
+ if (write != read)
+ {
+ // copy read to write backwards to close gaps
+ rColorSteps[write] = rColorSteps[read];
+ }
+
+ // always forward write position
+ write++;
+ }
+ }
+
+ // correct size when length is reduced. write is always at
+ // last used position + 1
+ if (rColorSteps.size() > write)
+ {
+ rColorSteps.resize(write);
+ }
+
+ if (bSameColorInit && bAllTheSameColor && rColorSteps.size() > 1)
+ {
+ // id all-the-same color is detected, reset to single
+ // entry, but also force to StartColor and preserve the color
+ rColorSteps.resize(1);
+ rColorSteps[0] = ColorStep(0.0, aFirstColor);
+ }
+ }
+
BColor modifyBColor(
const ColorSteps& rColorSteps,
double fScaler,
diff --git a/drawinglayer/qa/unit/vclpixelprocessor2d.cxx b/drawinglayer/qa/unit/vclpixelprocessor2d.cxx
index 573c4bdc32f0..343556aec6d1 100644
--- a/drawinglayer/qa/unit/vclpixelprocessor2d.cxx
+++ b/drawinglayer/qa/unit/vclpixelprocessor2d.cxx
@@ -18,6 +18,7 @@
#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
+#include <basegfx/utils/gradienttools.hxx>
using namespace drawinglayer;
@@ -59,8 +60,10 @@ public:
basegfx::B2DRange definitionRange(0, 0, 100, 200);
basegfx::B2DRange outputRange(0, 100, 100, 200); // Paint only lower half of the gradient.
+ const basegfx::ColorSteps aColorSteps{ basegfx::ColorStep(0.0, COL_WHITE.getBColor()),
+ basegfx::ColorStep(1.0, COL_BLACK.getBColor()) };
attribute::FillGradientAttribute attributes(attribute::GradientStyle::Linear, 0, 0, 0, 0,
- COL_WHITE.getBColor(), COL_BLACK.getBColor());
+ aColorSteps);
rtl::Reference<primitive2d::FillGradientPrimitive2D> gradientPrimitive(
new primitive2d::FillGradientPrimitive2D(outputRange, definitionRange, attributes));
primitive2d::Primitive2DContainer primitives;
diff --git a/drawinglayer/source/attribute/fillgradientattribute.cxx b/drawinglayer/source/attribute/fillgradientattribute.cxx
index 07bc82e4e549..3d78273a6428 100644
--- a/drawinglayer/source/attribute/fillgradientattribute.cxx
+++ b/drawinglayer/source/attribute/fillgradientattribute.cxx
@@ -40,109 +40,31 @@ namespace drawinglayer::attribute
double fOffsetX,
double fOffsetY,
double fAngle,
- const basegfx::BColor& rStartColor,
- const basegfx::BColor& rEndColor,
- const basegfx::ColorSteps* pColorSteps,
+ const basegfx::ColorSteps& rColorSteps,
sal_uInt16 nSteps)
: mfBorder(fBorder),
mfOffsetX(fOffsetX),
mfOffsetY(fOffsetY),
mfAngle(fAngle),
- maColorSteps(),
+ maColorSteps(rColorSteps), // copy ColorSteps
meStyle(eStyle),
mnSteps(nSteps)
{
- // always add start color to guarantee a color at all. It's also just safer
- // to have one and not an empty vector, that spares many checks in the using code
- maColorSteps.emplace_back(0.0, rStartColor);
-
- // if we have given ColorSteps, integrate these
- if(nullptr != pColorSteps && !pColorSteps->empty())
- {
- // append early to local & sort to prepare the following correction(s)
- // and later processing
- maColorSteps.insert(maColorSteps.end(), pColorSteps->begin(), pColorSteps->end());
-
- // no need to sort knowingly lowest entry StartColor, also guarantees that
- // entry to stay at begin
- std::sort(maColorSteps.begin() + 1, maColorSteps.end());
-
- // use two r/w heads on the data band maColorSteps
- size_t curr(0), next(1);
-
- // during processing, check if all colors are the same. We know the
- // StartColor, so to all be the same, all also have to be equal to
- // StartColor (including EndColor, use to initialize)
- bool bAllTheSameColor(rStartColor == rEndColor);
-
- // remove entries <= 0.0, >= 1.0 and with equal offset. do
- // this inside the already sorted local vector by evtl.
- // moving entries closer to begin to keep and adapting size
- // at the end
- for(; next < maColorSteps.size(); next++)
- {
- const double fNextOffset(maColorSteps[next].getOffset());
-
- // check for < 0.0 (should not really happen, see ::ColorStep)
- // also check for == 0.0 which would mean than an implicit
- // StartColor was given in ColorSteps - ignore that, we want
- // the explicitly given StartColor to always win
- if(basegfx::fTools::lessOrEqual(fNextOffset, 0.0))
- continue;
-
- // check for > 1.0 (should not really happen, see ::ColorStep)
- // also check for == 1.0 which would mean than an implicit
- // EndColor was given in ColorSteps - ignore that, we want
- // the explicitly given EndColor to always win
- if(basegfx::fTools::moreOrEqual(fNextOffset, 1.0))
- continue;
-
- // check for equal current offset
- const double fCurrOffset(maColorSteps[curr].getOffset());
- if(basegfx::fTools::equal(fNextOffset, fCurrOffset))
- continue;
-
- // next is > 0.0, < 1.0 and != curr, so a valid entry.
- // take over by evtl. have to move it left
- curr++;
- if(curr != next)
- {
- maColorSteps[curr] = maColorSteps[next];
- }
-
- // new valid entry detected, check it for all the same color
- bAllTheSameColor = bAllTheSameColor && maColorSteps[curr].getColor() == rStartColor;
- }
-
- if(bAllTheSameColor)
- {
- // if all are the same color, reset to StartColor only
- maColorSteps.resize(1);
- }
- else
- {
- // adapt size to detected useful entries
- curr++;
- if(curr != maColorSteps.size())
- {
- maColorSteps.resize(curr);
- }
-
- // add EndColor if in-between colors were added
- // or StartColor != EndColor
- if(curr > 1 || rStartColor != rEndColor)
- {
- maColorSteps.emplace_back(1.0, rEndColor);
- }
- }
- }
- else
+ // Correct the local ColorSteps. That will guarantee that the
+ // content does contain no offsets < 0.0, > 1.0 or double
+ // ones, also secures sorted arrangement and checks for
+ // double colors, too (see there for more information).
+ // This is what the usages of this in primitives need.
+ // Since FillGradientAttribute is read-only doing this
+ // once here in the constructor is sufficient
+ basegfx::utils::sortAndCorrectColorSteps(maColorSteps);
+
+ // sortAndCorrectColorSteps is rigid and can return
+ // an empty result. To keep things simple, add a single
+ // fallback value
+ if (maColorSteps.empty())
{
- // add EndColor if different from StartColor
- if(rStartColor != rEndColor)
- {
- maColorSteps.emplace_back(1.0, rEndColor);
- }
+ maColorSteps.emplace_back(0.0, basegfx::BColor());
}
}
@@ -204,12 +126,10 @@ namespace drawinglayer::attribute
double fOffsetX,
double fOffsetY,
double fAngle,
- const basegfx::BColor& rStartColor,
- const basegfx::BColor& rEndColor,
- const basegfx::ColorSteps* pColorSteps,
+ const basegfx::ColorSteps& rColorSteps,
sal_uInt16 nSteps)
: mpFillGradientAttribute(ImpFillGradientAttribute(
- eStyle, fBorder, fOffsetX, fOffsetY, fAngle, rStartColor, rEndColor, pColorSteps, nSteps))
+ eStyle, fBorder, fOffsetX, fOffsetY, fAngle, rColorSteps, nSteps))
{
}
diff --git a/drawinglayer/source/primitive3d/textureprimitive3d.cxx b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
index ba998c7f50bb..549932e93049 100644
--- a/drawinglayer/source/primitive3d/textureprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/textureprimitive3d.cxx
@@ -20,6 +20,7 @@
#include <primitive3d/textureprimitive3d.hxx>
#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
#include <basegfx/color/bcolor.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <utility>
@@ -92,7 +93,13 @@ namespace drawinglayer::primitive3d
{
// create TransparenceTexturePrimitive3D with fixed transparence as replacement
const basegfx::BColor aGray(getTransparence(), getTransparence(), getTransparence());
- const attribute::FillGradientAttribute aFillGradient(attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, 0.0, aGray, aGray);
+
+ // create ColorSteps with StartColor == EndCoOlor == aGray
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, aGray),
+ basegfx::ColorStep(1.0, aGray) };
+
+ const attribute::FillGradientAttribute aFillGradient(attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, 0.0, aColorSteps);
const Primitive3DReference xRef(new TransparenceTexturePrimitive3D(aFillGradient, getChildren(), getTextureSize()));
return { xRef };
}
diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx
index 788594f3b8eb..375e83f9221c 100644
--- a/drawinglayer/source/texture/texture.cxx
+++ b/drawinglayer/source/texture/texture.cxx
@@ -466,11 +466,9 @@ namespace drawinglayer::texture
if (mnColorSteps.size() < 2)
return;
- // need to start with the offsets *outside* of all loops, these will
- // get modified non-linear below, now in more than one gradient section,
- // but *constantly* over the whole range
- double fAllWidth(0.0);
- double fAllHeight(0.0);
+ // prepare vars dependent on aspect ratio
+ const double fAR(maGradientInfo.getAspectRatio());
+ const bool bMTO(fAR > 1.0);
// outer loop over ColorSteps, each is from cs_l to cs_r
for (auto cs_l(mnColorSteps.begin()), cs_r(cs_l + 1); cs_r != mnColorSteps.end(); cs_l++, cs_r++)
@@ -486,26 +484,21 @@ namespace drawinglayer::texture
const double fOffsetEnd(cs_r->getOffset());
const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
- // prepare individual increments for X/Y dependent on aspect ratio
- const double fAR(maGradientInfo.getAspectRatio());
- const bool bMTO(fAR > 1.0);
- const double fIncrementX(bMTO ? fStripeWidth / fAR : fStripeWidth);
- const double fIncrementY(bMTO ? fStripeWidth : fStripeWidth * fAR);
-
// get correct start for inner loop (see above)
const sal_uInt32 nStartInnerLoop(cs_l == mnColorSteps.begin() ? 1 : 0);
for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
{
- // next step, actively adapt outer-loop w/h values
- fAllWidth += fIncrementX;
- fAllHeight += fIncrementY;
+ // calculate offset position for entry
+ const double fSize(fOffsetStart + (fStripeWidth * innerLoop));
// set and add at target
B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform()
- * basegfx::utils::createScaleB2DHomMatrix(1.0 - fAllWidth, 1.0 - fAllHeight);
+ * basegfx::utils::createScaleB2DHomMatrix(
+ 1.0 - (bMTO ? fSize / fAR : fSize),
+ 1.0 - (bMTO ? fSize : fSize * fAR));
aB2DHomMatrixAndBColor.maBColor = interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1));
rEntries.push_back(aB2DHomMatrixAndBColor);
}
@@ -656,11 +649,9 @@ namespace drawinglayer::texture
if (mnColorSteps.size() < 2)
return;
- // need to start with the offsets *outside* of all loops, these will
- // get modified non-linear below, now in more than one gradient section,
- // but *constantly* over the whole range
- double fAllWidth(0.0);
- double fAllHeight(0.0);
+ // prepare vars dependent on aspect ratio
+ const double fAR(maGradientInfo.getAspectRatio());
+ const bool bMTO(fAR > 1.0);
// outer loop over ColorSteps, each is from cs_l to cs_r
for (auto cs_l(mnColorSteps.begin()), cs_r(cs_l + 1); cs_r != mnColorSteps.end(); cs_l++, cs_r++)
@@ -676,26 +667,21 @@ namespace drawinglayer::texture
const double fOffsetEnd(cs_r->getOffset());
const double fStripeWidth((fOffsetEnd - fOffsetStart) / nSteps);
- // prepare individual increments for X/Y dependent on aspect ratio
- const double fAR(maGradientInfo.getAspectRatio());
- const bool bMTO(fAR > 1.0);
- const double fIncrementX(bMTO ? fStripeWidth / fAR : fStripeWidth);
- const double fIncrementY(bMTO ? fStripeWidth : fStripeWidth * fAR);
-
// get correct start for inner loop (see above)
const sal_uInt32 nStartInnerLoop(cs_l == mnColorSteps.begin() ? 1 : 0);
for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < nSteps; innerLoop++)
{
- // next step, actively adapt outer-loop w/h values
- fAllWidth += fIncrementX;
- fAllHeight += fIncrementY;
+ // calculate offset position for entry
+ const double fSize(fOffsetStart + (fStripeWidth * innerLoop));
// set and add at target
B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform()
- * basegfx::utils::createScaleB2DHomMatrix(1.0 - fAllWidth, 1.0 - fAllHeight);
+ * basegfx::utils::createScaleB2DHomMatrix(
+ 1.0 - (bMTO ? fSize / fAR : fSize),
+ 1.0 - (bMTO ? fSize : fSize * fAR));
aB2DHomMatrixAndBColor.maBColor = interpolate(aCStart, aCEnd, double(innerLoop) / double(nSteps - 1));
rEntries.push_back(aB2DHomMatrixAndBColor);
}
diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx b/drawinglayer/source/tools/wmfemfhelper.cxx
index 0189c621fda3..27e6a6c94e24 100644
--- a/drawinglayer/source/tools/wmfemfhelper.cxx
+++ b/drawinglayer/source/tools/wmfemfhelper.cxx
@@ -711,15 +711,17 @@ namespace wmfemfhelper
}
}
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, aStart),
+ basegfx::ColorStep(1.0, aEnd) };
+
return drawinglayer::attribute::FillGradientAttribute(
aGradientStyle,
static_cast<double>(rGradient.GetBorder()) * 0.01,
static_cast<double>(rGradient.GetOfsX()) * 0.01,
static_cast<double>(rGradient.GetOfsY()) * 0.01,
toRadians(rGradient.GetAngle()),
- aStart,
- aEnd,
- nullptr,
+ aColorSteps,
rGradient.GetSteps());
}
diff --git a/include/basegfx/utils/gradienttools.hxx b/include/basegfx/utils/gradienttools.hxx
index 793d07a75577..328a86b8335c 100644
--- a/include/basegfx/utils/gradienttools.hxx
+++ b/include/basegfx/utils/gradienttools.hxx
@@ -69,9 +69,18 @@ namespace basegfx
// e.g. for usage in std::vector::insert
// ensure [0.0 .. 1.0] range for mfOffset
ColorStep(double fOffset = 0.0, const BColor& rColor = BColor())
- : mfOffset(std::max(0.0, std::min(fOffset, 1.0)))
+ : mfOffset(fOffset)
, maColor(rColor)
{
+ // NOTE: I originally *corrected* mfOffset here by using
+ // mfOffset(std::max(0.0, std::min(fOffset, 1.0)))
+ // While that is formally correct, it moves an invalid
+ // entry to 0.0 or 1.0, thus creating additional wrong
+ // Start/EndColor entries. That may then 'overlay' the
+ // cortrect entry when corrections are applied to the
+ // vector of entries (see sortAndCorrectColorSteps)
+ // which leads to getting the wanted Start/EndColor
+ // to be factically deleted, what is an error.
}
double getOffset() const { return mfOffset; }
@@ -184,6 +193,26 @@ namespace basegfx
namespace utils
{
+ /* Helper to sort and correct ColorSteps. This will
+ sort and then correct the given ColorSteps. The
+ corrected version will
+ - be sorted
+ - have no double values
+ - have no values with offset < 0.0
+ - have no values with offset > 1.0
+ thus be ready to be used in multi-color gradients.
+
+ NOTE: The returned version may be empty (!) if no
+ valid entries were contained
+ NOTE: It does not necessarily contain values for
+ offset == 0.0 and 1.0 if there were none
+ given (so no Start/EndColor)
+ NOTE: If it contains only one entry that entry is
+ set to StartColor and the Color is preserved.
+ This is also done when all Colors are the same
+ */
+ BASEGFX_DLLPUBLIC void sortAndCorrectColorSteps(ColorSteps& rColorSteps);
+
/* Helper to grep the correct ColorStep out of
ColorSteps and interpolate as needed for given
relative value in fScaler in the range of [0.0 .. 1.0].
diff --git a/include/drawinglayer/attribute/fillgradientattribute.hxx b/include/drawinglayer/attribute/fillgradientattribute.hxx
index 4b736e678181..3a62ee41e43c 100644
--- a/include/drawinglayer/attribute/fillgradientattribute.hxx
+++ b/include/drawinglayer/attribute/fillgradientattribute.hxx
@@ -55,15 +55,15 @@ private:
public:
/* MCGR: Adaptions for MultiColorGradients
- To force providing start/end colors these are still part of the
- constructor (see rStartColor/rEndColor). To also provide
- GradientSteps these need to be handed over by ColorSteps data
- if wanted/needed.
+ Direct Start/EndCOlor is no longer required, instead the
+ full color gradient is handed over as ColorSteps vector.
+ To add the former Start/EndColor in a compatible way, just
+ prepare an instance of basegfx::ColorSteps with the
+ StartColor at 0.0 and the EndColor at 1.0.
- Start/EndColor will be added to the internal ColorSteps with
- the according default offsets. A rigid correction/input data
- testing is done by the constructor, including to sort the
- ColorSteps by offset.
+ A rigid correction/input data will be done by the constructor,
+ including to sort the ColorSteps by offset and removing invalid
+ entries (see sortAndCorrectColorSteps)
To access e.g. the StartColor, use getColorSteps().front(), and
getColorSteps().back(), accordingly, for EndColor. The existence
@@ -74,9 +74,8 @@ public:
*/
/// constructors/assignmentoperator/destructor
FillGradientAttribute(GradientStyle eStyle, double fBorder, double fOffsetX, double fOffsetY,
- double fAngle, const basegfx::BColor& rStartColor,
- const basegfx::BColor& rEndColor,
- const basegfx::ColorSteps* pColorSteps = nullptr, sal_uInt16 nSteps = 0);
+ double fAngle, const basegfx::ColorSteps& rColorSteps,
+ sal_uInt16 nSteps = 0);
FillGradientAttribute();
FillGradientAttribute(const FillGradientAttribute&);
FillGradientAttribute(FillGradientAttribute&&);
diff --git a/svx/source/sdr/primitive2d/sdrattributecreator.cxx b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
index 048d5430f6f8..0e0369b08a43 100644
--- a/svx/source/sdr/primitive2d/sdrattributecreator.cxx
+++ b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
@@ -493,7 +493,13 @@ namespace drawinglayer::primitive2d
aEnd = interpolate(aBlack, aEnd, static_cast<double>(nEndIntens) * 0.01);
}
- basegfx::ColorSteps aColorSteps;
+ // prepare ColorSteps
+ // currently always two (Start/EndColor) to stay compatible
+ // for now, but that will change. It already gets manipulated
+ // by the test cases below
+ basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, aStart),
+ basegfx::ColorStep(1.0, aEnd) };
// test code here, can/will be removed later
static sal_uInt32 nUseGradientSteps(0);
@@ -502,11 +508,12 @@ namespace drawinglayer::primitive2d
case 1:
{
// just test a nice valid gradient
- aStart = basegfx::BColor(1.0, 0.0, 0.0); // red
- aEnd = basegfx::BColor(0.0, 0.0, 1.0); // blue
+ aColorSteps.clear();
+ aColorSteps.emplace_back(0.0, basegfx::BColor(1.0, 0.0, 0.0)); // red
aColorSteps.emplace_back(0.25, basegfx::BColor(0.0, 1.0, 0.0)); // green@25%
aColorSteps.emplace_back(0.50, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
aColorSteps.emplace_back(0.75, basegfx::BColor(1.0, 0.0, 1.0)); // pink@75%
+ aColorSteps.emplace_back(1.0, basegfx::BColor(0.0, 0.0, 1.0)); // blue
break;
}
@@ -527,6 +534,7 @@ namespace drawinglayer::primitive2d
case 4:
{
// check additional EndColor, the one given directly has to win
+ // due this one being added *after* the original one
aColorSteps.emplace_back(1.0, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
break;
}
@@ -547,7 +555,7 @@ namespace drawinglayer::primitive2d
case 7:
{
- // check in-between single-color part
+ // check in-between single-color section
aColorSteps.emplace_back(0.3, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
aColorSteps.emplace_back(0.7, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
break;
@@ -555,10 +563,11 @@ namespace drawinglayer::primitive2d
case 8:
{
- // check in-between single-color parts
+ // check in-between single-color sections
aColorSteps.emplace_back(0.2, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
- aColorSteps.emplace_back(0.4, aEnd);
- aColorSteps.emplace_back(0.6, aStart);
+ aColorSteps.emplace_back(0.4, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
+ aColorSteps.emplace_back(0.5, aStart);
+ aColorSteps.emplace_back(0.6, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
aColorSteps.emplace_back(0.8, basegfx::BColor(1.0, 1.0, 0.0)); // yellow@50%
break;
}
@@ -573,7 +582,16 @@ namespace drawinglayer::primitive2d
case 10:
{
// check single-color end area
- aColorSteps.emplace_back(0.6, aEnd);
+ aColorSteps.emplace_back(0.4, aEnd);
+ break;
+ }
+
+ case 11:
+ {
+ // check case without direct Start/EndColor
+ aColorSteps.clear();
+ aColorSteps.emplace_back(0.4, aEnd);
+ aColorSteps.emplace_back(0.6, aStart);
break;
}
@@ -589,9 +607,7 @@ namespace drawinglayer::primitive2d
static_cast<double>(aXGradient.GetXOffset()) * 0.01,
static_cast<double>(aXGradient.GetYOffset()) * 0.01,
toRadians(aXGradient.GetAngle()),
- aStart,
- aEnd,
- aColorSteps.empty() ? nullptr : &aColorSteps,
+ aColorSteps,
rSet.Get(XATTR_GRADIENTSTEPCOUNT).GetValue());
break;
@@ -745,14 +761,17 @@ namespace drawinglayer::primitive2d
const double fStartLum(nStartLuminance / 255.0);
const double fEndLum(nEndLuminance / 255.0);
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, basegfx::BColor(fStartLum, fStartLum, fStartLum)),
+ basegfx::ColorStep(1.0, basegfx::BColor(fEndLum, fEndLum, fEndLum)) };
+
return attribute::FillGradientAttribute(
XGradientStyleToGradientStyle(rGradient.GetGradientStyle()),
static_cast<double>(rGradient.GetBorder()) * 0.01,
static_cast<double>(rGradient.GetXOffset()) * 0.01,
static_cast<double>(rGradient.GetYOffset()) * 0.01,
toRadians(rGradient.GetAngle()),
- basegfx::BColor(fStartLum, fStartLum, fStartLum),
- basegfx::BColor(fEndLum, fEndLum, fEndLum));
+ aColorSteps);
}
}
diff --git a/svx/source/xoutdev/xtabgrdt.cxx b/svx/source/xoutdev/xtabgrdt.cxx
index bc8f79ac0426..219ee2801d69 100644
--- a/svx/source/xoutdev/xtabgrdt.cxx
+++ b/svx/source/xoutdev/xtabgrdt.cxx
@@ -35,6 +35,7 @@
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <memory>
using namespace com::sun::star;
@@ -152,14 +153,17 @@ BitmapEx XGradientList::CreateBitmap( tools::Long nIndex, const Size& rSize ) co
}
}
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, aStart),
+ basegfx::ColorStep(1.0, aEnd) };
+
drawinglayer::attribute::FillGradientAttribute aFillGradient(
aGradientStyle,
static_cast<double>(rGradient.GetBorder()) * 0.01,
static_cast<double>(rGradient.GetXOffset()) * 0.01,
static_cast<double>(rGradient.GetYOffset()) * 0.01,
toRadians(rGradient.GetAngle()),
- aStart,
- aEnd);
+ aColorSteps);
const drawinglayer::primitive2d::Primitive2DReference aGradientPrimitive(
new drawinglayer::primitive2d::PolyPolygonGradientPrimitive2D(
diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx b/sw/source/uibase/docvw/HeaderFooterWin.cxx
index 763d6d729e12..186deaa12ab2 100644
--- a/sw/source/uibase/docvw/HeaderFooterWin.cxx
+++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx
@@ -29,6 +29,7 @@
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/utils/gradienttools.hxx>
#include <drawinglayer/attribute/fillgradientattribute.hxx>
#include <drawinglayer/attribute/fontattribute.hxx>
#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
@@ -150,7 +151,11 @@ void SwFrameButtonPainter::PaintButton(drawinglayer::primitive2d::Primitive2DCon
double nAngle = M_PI;
if (bOnTop)
nAngle = 0;
- FillGradientAttribute aFillAttrs(drawinglayer::attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, nAngle, aLighterColor, aFillColor);
+
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, aLighterColor),
+ basegfx::ColorStep(1.0, aFillColor) };
+ FillGradientAttribute aFillAttrs(drawinglayer::attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, nAngle, aColorSteps );
rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::FillGradientPrimitive2D(aGradientRect, std::move(aFillAttrs))));
}
diff --git a/sw/source/uibase/docvw/ShadowOverlayObject.cxx b/sw/source/uibase/docvw/ShadowOverlayObject.cxx
index 3b7490678533..002a40d5db91 100644
--- a/sw/source/uibase/docvw/ShadowOverlayObject.cxx
+++ b/sw/source/uibase/docvw/ShadowOverlayObject.cxx
@@ -27,6 +27,7 @@
#include <sw_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/primitivetools2d.hxx>
#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
+#include <basegfx/utils/gradienttools.hxx>
namespace sw::sidebarwindows {
@@ -82,14 +83,17 @@ void ShadowPrimitive::create2DDecomposition(
case SS_NORMAL:
{
aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (2.0 * getDiscreteUnit())));
+
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0)),
+ basegfx::ColorStep(1.0, basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0)) };
::drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute(
drawinglayer::attribute::GradientStyle::Linear,
0.0,
0.5,
0.5,
M_PI,
- basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0),
- basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0));
+ aColorSteps);
rContainer.push_back(
new drawinglayer::primitive2d::FillGradientPrimitive2D(
@@ -100,14 +104,16 @@ void ShadowPrimitive::create2DDecomposition(
case SS_VIEW:
{
aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit())));
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0)),
+ basegfx::ColorStep(1.0, basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0)) };
drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute(
drawinglayer::attribute::GradientStyle::Linear,
0.0,
0.5,
0.5,
M_PI,
- basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0),
- basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0));
+ aColorSteps);
rContainer.push_back(
new drawinglayer::primitive2d::FillGradientPrimitive2D(
@@ -118,14 +124,16 @@ void ShadowPrimitive::create2DDecomposition(
case SS_EDIT:
{
aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit())));
+ const basegfx::ColorSteps aColorSteps {
+ basegfx::ColorStep(0.0, basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0)),
+ basegfx::ColorStep(1.0, basegfx::BColor(83.0/255.0,83.0/255.0,83.0/255.0)) };
drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute(
drawinglayer::attribute::GradientStyle::Linear,
0.0,
0.5,
0.5,
M_PI,
- basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0),
- basegfx::BColor(83.0/255.0,83.0/255.0,83.0/255.0));
+ aColorSteps);
rContainer.push_back(
new drawinglayer::primitive2d::FillGradientPrimitive2D(