summaryrefslogtreecommitdiffstats
path: root/layout/painting/nsCSSRenderingGradients.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/painting/nsCSSRenderingGradients.cpp')
-rw-r--r--layout/painting/nsCSSRenderingGradients.cpp30
1 files changed, 23 insertions, 7 deletions
diff --git a/layout/painting/nsCSSRenderingGradients.cpp b/layout/painting/nsCSSRenderingGradients.cpp
index 2fb2f0b024..db30d4fefc 100644
--- a/layout/painting/nsCSSRenderingGradients.cpp
+++ b/layout/painting/nsCSSRenderingGradients.cpp
@@ -1195,15 +1195,16 @@ class MOZ_STACK_CLASS WrColorStopInterpolator
WrColorStopInterpolator(
const nsTArray<ColorStop>& aStops,
const StyleColorInterpolationMethod& aStyleColorInterpolationMethod,
- float aOpacity, nsTArray<wr::GradientStop>& aResult)
- : ColorStopInterpolator(aStops, aStyleColorInterpolationMethod),
+ float aOpacity, nsTArray<wr::GradientStop>& aResult, bool aExtendLastStop)
+ : ColorStopInterpolator(aStops, aStyleColorInterpolationMethod,
+ aExtendLastStop),
mResult(aResult),
mOpacity(aOpacity),
mOutputStop(0) {}
void CreateStops() {
mResult.SetLengthAndRetainStorage(0);
- // we always emit at least two stops (start and end) for each input stop,
+ // We always emit at least two stops (start and end) for each input stop,
// which avoids ambiguity with incomplete oklch/lch/hsv/hsb color stops for
// the last stop pair, where the last color stop can't be interpreted on its
// own because it actually depends on the previous stop.
@@ -1257,11 +1258,26 @@ void nsCSSGradientRenderer::BuildWebRenderParameters(
// * https://bugzilla.mozilla.org/show_bug.cgi?id=1248178
StyleColorInterpolationMethod styleColorInterpolationMethod =
mGradient->ColorInterpolationMethod();
- if (mStops.Length() >= 2 &&
- (styleColorInterpolationMethod.space != StyleColorSpace::Srgb ||
- gfxPlatform::GetCMSMode() == CMSMode::All)) {
+ // For colorspaces supported by WebRender (Srgb, Hsl, Hwb) we technically do
+ // not need to add extra stops, but the only one of those colorspaces that
+ // appears frequently is Srgb, and Srgb still needs extra stops if CMS is
+ // enabled. Hsl/Hwb need extra stops if StyleHueInterpolationMethod is not
+ // Shorter, or if CMS is enabled.
+ //
+ // It's probably best to keep this logic as simple as possible, see
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1885716 for an example of
+ // what can happen if we try to be clever here.
+ if (styleColorInterpolationMethod.space != StyleColorSpace::Srgb ||
+ gfxPlatform::GetCMSMode() == CMSMode::All) {
+ // For the specific case of longer hue interpolation on a CSS non-repeating
+ // gradient, we have to pretend there is another stop at position=1.0 that
+ // duplicates the last stop, this is probably only used for things like a
+ // color wheel. No such problem for SVG as it doesn't have that complexity.
+ bool extendLastStop = aMode == wr::ExtendMode::Clamp &&
+ styleColorInterpolationMethod.hue ==
+ StyleHueInterpolationMethod::Longer;
WrColorStopInterpolator interpolator(mStops, styleColorInterpolationMethod,
- aOpacity, aStops);
+ aOpacity, aStops, extendLastStop);
interpolator.CreateStops();
} else {
aStops.SetLength(mStops.Length());