summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-02-02 20:16:50 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-02-02 20:16:50 +0100
commitc1fcd03c35ad1e9f97f72d154b25b492622ae7cc (patch)
treedac975cf4cab2cf21e9cef91d789c8d13379c038 /layout
parent0dce1fa11a876df2fa5b507b1370d7206c3628da (diff)
downloaduxp-c1fcd03c35ad1e9f97f72d154b25b492622ae7cc.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).
Diffstat (limited to 'layout')
-rw-r--r--layout/base/nsCSSRendering.cpp38
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) {