summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2023-03-27 12:35:07 +0200
committerArmin Le Grand <Armin.Le.Grand@me.com>2023-03-27 12:42:28 +0000
commit13c37d2c0f0a172d2522b255c0416a4ade639b7a (patch)
tree3167d60542b6ec15ff98615baed7bc1e1f6e24c2
parentb653556f8dc5a65805a0ef091f654b95caa20a63 (diff)
MCGR: More corrections fo sortAndCorrectColorStops
Handle cases where gradient snippets overlap Start/End- Color to preverve input information. Added more test cases to createNewSdrFillAttribute to check these cases. All 27 look good, so add this changes. Change-Id: I6b2ba190ac8cf5a00c5a27865cea6bb41efe5110 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149624 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
-rw-r--r--basegfx/source/tools/gradienttools.cxx71
-rw-r--r--svx/source/sdr/primitive2d/sdrattributecreator.cxx106
2 files changed, 173 insertions, 4 deletions
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx
index 3b9fcda25ea1..a98eeddf641c 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -436,16 +436,60 @@ namespace basegfx
for (size_t read(0); read < rColorStops.size(); read++)
{
// get offset of entry at read position
- const double rOff(rColorStops[read].getStopOffset());
+ double fOff(rColorStops[read].getStopOffset());
+
+ if (basegfx::fTools::less(fOff, 0.0) && read + 1 < rColorStops.size())
+ {
+ // value < 0.0 and we have a next entry. check for gradient snippet
+ // containing 0.0 resp. StartColor
+ const double fOff2(rColorStops[read + 1].getStopOffset());
+
+ if (basegfx::fTools::more(fOff2, 0.0))
+ {
+ // read is the start of a gradient snippet containing 0.0. Correct
+ // entry to StartColor, interpolate to correct StartColor
+ rColorStops[read] = ColorStop(0.0, basegfx::interpolate(
+ rColorStops[read].getStopColor(),
+ rColorStops[read + 1].getStopColor(),
+ (0.0 - fOff) / (fOff2 - fOff)));
+
+ // adapt fOff
+ fOff = 0.0;
+ }
+ }
// step over < 0 values, these are outside and will be removed
- if (basegfx::fTools::less(rOff, 0.0))
+ if (basegfx::fTools::less(fOff, 0.0))
+ {
continue;
+ }
+
+ if (basegfx::fTools::less(fOff, 1.0) && read + 1 < rColorStops.size())
+ {
+ // value < 1.0 and we have a next entry. check for gradient snippet
+ // containing 1.0 resp. EndColor
+ const double fOff2(rColorStops[read + 1].getStopOffset());
+
+ if (basegfx::fTools::more(fOff2, 1.0))
+ {
+ // read is the start of a gradient snippet containing 1.0. Correct
+ // next entry to EndColor, interpolate to correct EndColor
+ rColorStops[read + 1] = ColorStop(1.0, basegfx::interpolate(
+ rColorStops[read].getStopColor(),
+ rColorStops[read + 1].getStopColor(),
+ (1.0 - fOff) / (fOff2 - fOff)));
+
+ // adapt fOff
+ fOff = 1.0;
+ }
+ }
// 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))
+ if (basegfx::fTools::more(fOff, 1.0))
+ {
break;
+ }
// entry is valid value at read position
// copy if write target is empty (write at start) or when
@@ -467,7 +511,26 @@ namespace basegfx
// last used position + 1
if (rColorStops.size() > write)
{
- rColorStops.resize(write);
+ if (0 == write)
+ {
+ // no valid entries at all, but not empty. This can only happen
+ // when all entries are below 0.0 or above 1.0 (else a gradient
+ // snippet spawning over both would have been detected)
+ if (basegfx::fTools::less(rColorStops.back().getStopOffset(), 0.0))
+ {
+ // all outside too low, rescue last due to being closest to content
+ rColorStops = ColorStops { ColorStop(0.0, rColorStops.back().getStopColor()) };
+ }
+ else // if (basegfx::fTools::more(rColorStops.front().getStopOffset(), 1.0))
+ {
+ // all outside too high, rescue first due to being closest to content
+ rColorStops = ColorStops { ColorStop(1.0, rColorStops.front().getStopColor()) };
+ }
+ }
+ else
+ {
+ rColorStops.resize(write);
+ }
}
}
diff --git a/svx/source/sdr/primitive2d/sdrattributecreator.cxx b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
index 344e16e95a8e..a7670606adff 100644
--- a/svx/source/sdr/primitive2d/sdrattributecreator.cxx
+++ b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
@@ -644,6 +644,112 @@ namespace drawinglayer::primitive2d
break;
}
+ case 17:
+ {
+ // check case with single stop < 0.0
+ aColorStops.clear();
+ aColorStops.emplace_back(-0.5, COL_LIGHTRED.getBColor()); // red
+ break;
+ }
+
+ case 18:
+ {
+ // check case with single stop > 1.0
+ aColorStops.clear();
+ aColorStops.emplace_back(1.5, COL_LIGHTRED.getBColor()); // red
+ break;
+ }
+
+ case 19:
+ {
+ // check case with stops overlapping 0.0
+ aColorStops.clear();
+ aColorStops.emplace_back(-0.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(0.5, COL_LIGHTBLUE.getBColor()); // blue
+ break;
+ }
+
+ case 20:
+ {
+ // check case with stops overlapping 1.0
+ aColorStops.clear();
+ aColorStops.emplace_back(0.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(1.5, COL_LIGHTBLUE.getBColor()); // blue
+ break;
+ }
+
+ case 21:
+ {
+ // check case with multiple stops < 0.0
+ aColorStops.clear();
+ aColorStops.emplace_back(-0.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(-0.4, COL_LIGHTBLUE.getBColor()); // blue
+ aColorStops.emplace_back(-0.3, COL_LIGHTGREEN.getBColor()); // green
+ break;
+ }
+
+ case 22:
+ {
+ // check case with multiple stops > 1.0
+ aColorStops.clear();
+ aColorStops.emplace_back(1.3, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(1.4, COL_LIGHTBLUE.getBColor()); // blue
+ aColorStops.emplace_back(1.5, COL_LIGHTGREEN.getBColor()); // green
+ break;
+ }
+
+ case 23:
+ {
+ // check case with stops overlapping 0.0 and 1.0
+ aColorStops.clear();
+ aColorStops.emplace_back(-0.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(0.5, COL_LIGHTBLUE.getBColor()); // blue
+ aColorStops.emplace_back(0.5, COL_LIGHTGREEN.getBColor()); // green
+ aColorStops.emplace_back(1.5, COL_LIGHTRED.getBColor()); // red
+ break;
+ }
+
+ case 24:
+ {
+ // check case with stops overlapping 0.0 and 1.0 and multiple entries
+ aColorStops.clear();
+ aColorStops.emplace_back(-0.5, COL_LIGHTGREEN.getBColor()); // green
+ aColorStops.emplace_back(-0.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(0.4, COL_LIGHTBLUE.getBColor()); // blue
+ aColorStops.emplace_back(0.5, COL_YELLOW.getBColor()); // yellow
+ aColorStops.emplace_back(0.6, COL_LIGHTGREEN.getBColor()); // green
+ aColorStops.emplace_back(1.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(1.5, COL_LIGHTGREEN.getBColor()); // green
+ break;
+ }
+
+ case 25:
+ {
+ // check case with just two stops overlapping 0.0 and 1.0
+ aColorStops.clear();
+ aColorStops.emplace_back(-0.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(1.5, COL_LIGHTGREEN.getBColor()); // green
+ break;
+ }
+
+ case 26:
+ {
+ // check case with just two stops overlapping 0.0 and 1.0 faaaar out
+ aColorStops.clear();
+ aColorStops.emplace_back(-5.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(5.5, COL_LIGHTGREEN.getBColor()); // green
+ break;
+ }
+
+ case 27:
+ {
+ // check case with just two stops overlapping 0.0 and 1.0 faaaar out but closer to one
+ aColorStops.clear();
+ aColorStops.emplace_back(-1.5, COL_LIGHTRED.getBColor()); // red
+ aColorStops.emplace_back(5.5, COL_LIGHTGREEN.getBColor()); // green
+ break;
+ }
+
default:
{
break;