summaryrefslogtreecommitdiff
path: root/basegfx
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 /basegfx
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>
Diffstat (limited to 'basegfx')
-rw-r--r--basegfx/source/tools/gradienttools.cxx71
1 files changed, 67 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);
+ }
}
}