Skip to content

Commit 3f4acfb

Browse files
committed
Bug 1939948 - When extending a gradient beyond the first/last specified color stops, do not add interpolated stops between the specified stops and the newly-added ones at 0% and/or 100%. r=longsonr
Per spec[1], "Before the first color stop, the gradient line is the color of the first color stop, and after the last color stop, the gradient line is the color of the last color stop." Thus, these areas (if they exist, i.e. if the specified color stops do not reach to the ends of the gradient line being rendered) are simply solid areas of the first or last color respectively. In most cases, adding interpolated stops within these areas would be harmless, as they would all be the same color. But in the case of longer-hue interpolation, this is not the case, and if we allow interpolation of extra stops, they will create an additional "cycle" of the gradient, outside the range for which it was actually defined. To avoid this, we ensure that when extending the color line in this way, only the new end stop is added, without any intermediate interpolated stops. [1] https://drafts.csswg.org/css-images-4/#coloring-gradient-line Differential Revision: https://phabricator.services.mozilla.com/D233216
1 parent a5ec89e commit 3f4acfb

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

layout/painting/nsCSSRenderingGradients.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,27 @@ class MOZ_STACK_CLASS ColorStopInterpolator {
6767
// This is never the case on SVG gradients as they only use shorter hue.
6868
//
6969
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1885716 for more info.
70+
uint32_t extraStops = 0;
7071
if (mExtend) {
72+
// If we're extending, we just need a single new stop, which will
73+
// duplicate the end being extended; do not create interpolated stops
74+
// within in the extension area!
7175
if (i == 0) {
7276
startPosition = std::min(startPosition, 0.0f);
77+
extraStops = 1;
7378
}
7479
if (i == iterStops - 1) {
7580
endPosition = std::max(endPosition, 1.0f);
81+
extraStops = 1;
7682
}
7783
}
78-
uint32_t extraStops =
79-
(uint32_t)(floor(endPosition * kFullRangeExtraStops) -
80-
floor(startPosition * kFullRangeExtraStops));
81-
extraStops = std::clamp(extraStops, 1U, kFullRangeExtraStops);
84+
if (!extraStops) {
85+
// Within the actual gradient range, figure out how many extra stops
86+
// to use for this section of the gradient.
87+
extraStops = (uint32_t)(floor(endPosition * kFullRangeExtraStops) -
88+
floor(startPosition * kFullRangeExtraStops));
89+
extraStops = std::clamp(extraStops, 1U, kFullRangeExtraStops);
90+
}
8291
float step = 1.0f / (float)extraStops;
8392
for (uint32_t extraStop = 0; extraStop <= extraStops; extraStop++) {
8493
auto progress = (float)extraStop * step;

0 commit comments

Comments
 (0)