diff options
Diffstat (limited to 'layout/painting/nsCSSRenderingGradients.h')
-rw-r--r-- | layout/painting/nsCSSRenderingGradients.h | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/layout/painting/nsCSSRenderingGradients.h b/layout/painting/nsCSSRenderingGradients.h index 549cd8c4b6..68ecab07ae 100644 --- a/layout/painting/nsCSSRenderingGradients.h +++ b/layout/painting/nsCSSRenderingGradients.h @@ -44,23 +44,38 @@ class MOZ_STACK_CLASS ColorStopInterpolator { public: ColorStopInterpolator( const nsTArray<ColorStop>& aStops, - const StyleColorInterpolationMethod& aStyleColorInterpolationMethod) + const StyleColorInterpolationMethod& aStyleColorInterpolationMethod, + bool aExtendLastStop) : mStyleColorInterpolationMethod(aStyleColorInterpolationMethod), - mStops(aStops) {} + mStops(aStops), + mExtendLastStop(aExtendLastStop) {} void CreateStops() { - for (uint32_t i = 0; i < mStops.Length() - 1; i++) { + // This loop intentionally iterates the last stop if extending. + uint32_t iterStops = mStops.Length() - (mExtendLastStop ? 0 : 1); + for (uint32_t i = 0; i < iterStops; i++) { + auto nextindex = i + 1 < mStops.Length() ? i + 1 : i; const auto& start = mStops[i]; - const auto& end = mStops[i + 1]; + const auto& end = mStops[nextindex]; + float startPosition = start.mPosition; + float endPosition = end.mPosition; + // For CSS non-repeating gradients with longer hue specified, we have to + // pretend there is a stop beyond the last stop. This is never the case + // on SVG gradients as they only use shorter hue. + // + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1885716 for more info. + if (i == mStops.Length() - 1 && mExtendLastStop) { + endPosition = 1.0f; + } uint32_t extraStops = - (uint32_t)(floor(end.mPosition * kFullRangeExtraStops) - - floor(start.mPosition * kFullRangeExtraStops)); + (uint32_t)(floor(endPosition * kFullRangeExtraStops) - + floor(startPosition * kFullRangeExtraStops)); extraStops = clamped(extraStops, 1U, kFullRangeExtraStops); float step = 1.0f / (float)extraStops; for (uint32_t extraStop = 0; extraStop <= extraStops; extraStop++) { auto progress = (float)extraStop * step; auto position = - start.mPosition + progress * (end.mPosition - start.mPosition); + startPosition + progress * (endPosition - startPosition); StyleAbsoluteColor color = Servo_InterpolateColor(mStyleColorInterpolationMethod, &end.mColor, &start.mColor, progress); @@ -73,11 +88,15 @@ class MOZ_STACK_CLASS ColorStopInterpolator { protected: StyleColorInterpolationMethod mStyleColorInterpolationMethod; const nsTArray<ColorStop>& mStops; + // This indicates that we want to extend the endPosition on the last stop, + // which only matters if this is a CSS non-repeating gradient with + // StyleHueInterpolationMethod::Longer (only valid for hsl/hwb/lch/oklch). + bool mExtendLastStop; - // this could be made tunable, but at 1.0/128 the error is largely + // This could be made tunable, but at 1.0/128 the error is largely // irrelevant, as WebRender re-encodes it to 128 pairs of stops. // - // note that we don't attempt to place the positions of these stops + // Note that we don't attempt to place the positions of these stops // precisely at intervals, we just add this many extra stops across the // range where it is convenient. inline static const uint32_t kFullRangeExtraStops = 128; |