diff options
Diffstat (limited to 'layout/painting/nsCSSRenderingGradients.cpp')
-rw-r--r-- | layout/painting/nsCSSRenderingGradients.cpp | 30 |
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()); |