diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-02-02 20:16:50 +0100 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-02-02 20:16:50 +0100 |
commit | c0cfd6f89cd6b25cc8aaea1a1eb7bc004c88c206 (patch) | |
tree | dac975cf4cab2cf21e9cef91d789c8d13379c038 | |
parent | d61fde6e94bce9f920e9fcc55a43f94c23c40a01 (diff) | |
download | uxp-c0cfd6f89cd6b25cc8aaea1a1eb7bc004c88c206.tar.gz |
CSS gradients: add a special case for transparent stops.
This causes transparent stops to behave like "true transparent" instead
of "transparent black", even in RGBA space.
i.e.: the gradient will transition to a transparent version of the color
adjacent to the transparent color stop (on either side if not on the edge).
-rw-r--r-- | layout/base/nsCSSRendering.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 5b8a884a1b..054632ad79 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2670,6 +2670,44 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, lineLength = rectLen; } + // Special case for 'transparent' + for (uint32_t i = 0; i < stops.Length(); ++i) { + Color color = stops[i].mColor; + if (color.r == 0 && color.g == 0 && color.b == 0 && color.a == 0) { + // We have (0,0,0,0) as a color stop - this means 'transparent'. + // In this case for the usually intended effect, we change the color + // of the transparent stop to the color of the adjacent stop with + // 0 opacity. If we are not on either edge, we add a stop on both + // sides of the transparent point with the adjacent color value. + // i.e.: c1 -> c1 (alpha 0) | c2 (alpha 0) -> c2 + // XXX: We should probably track the use of the transparent keyword + // down from the CSS parsing level to here with a flag in mStops, if + // rgba(0,0,0,0) ever is an intended thing (very much a corner case). + if (i > 0) { + // Change stop color to adjacent-previous (color->T) + color = stops[i - 1].mColor; + color.a = 0; + stops[i].mColor = color; + if (i < stops.Length() - 1) { + // We're in the middle somewhere: insert stop adjacent-next (T->color) + Color color2 = stops[i + 1].mColor; + color2.a = 0; + if (color != color2) { + // Only insert an extra stop if c1 is different than c2 in c1->T->c2 + // Note: A transparent stop is never considered an interpolation hint + stops.InsertElementAt(i + 1, ColorStop(stops[i].mPosition, false, color2)); + i++; + } + } + } else if (i < stops.Length() - 1) { + // Change stop color to adjacent-next (T->color) + color = stops[i + 1].mColor; + color.a = 0; + stops[i].mColor = color; + } + } + } + // Eliminate negative-position stops if the gradient is radial. double firstStop = stops[0].mPosition; if (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR && firstStop < 0.0) { |