From d61fde6e94bce9f920e9fcc55a43f94c23c40a01 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 15 Jun 2017 21:46:53 +0200 Subject: CSS: Stop using premultiplied color space for gradients. --- layout/base/nsCSSRendering.cpp | 88 ++---------------------------------------- 1 file changed, 4 insertions(+), 84 deletions(-) (limited to 'layout/base/nsCSSRendering.cpp') diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 1c6d97395..5b8a884a1 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2268,14 +2268,8 @@ ComputeRadialGradientLine(nsPresContext* aPresContext, *aLineEnd = *aLineStart + gfxPoint(radiusX*cos(-angle), radiusY*sin(-angle)); } - -static float Interpolate(float aF1, float aF2, float aFrac) -{ - return aF1 + aFrac * (aF2 - aF1); -} - // Returns aFrac*aC2 + (1 - aFrac)*C1. The interpolation is done -// in unpremultiplied space, which is what SVG gradients and cairo +// in RGBA color space, which is what SVG gradients and cairo // gradients expect. static Color InterpolateColor(const Color& aC1, const Color& aC2, float aFrac) @@ -2435,79 +2429,6 @@ static void ResolveMidpoints(nsTArray& stops) } } -static Color -Premultiply(const Color& aColor) -{ - gfx::Float a = aColor.a; - return Color(aColor.r * a, aColor.g * a, aColor.b * a, a); -} - -static Color -Unpremultiply(const Color& aColor) -{ - gfx::Float a = aColor.a; - return (a > 0.f) - ? Color(aColor.r / a, aColor.g / a, aColor.b / a, a) - : aColor; -} - -static Color -TransparentColor(Color aColor) { - aColor.a = 0; - return aColor; -} - -// Adjusts and adds color stops in such a way that drawing the gradient with -// unpremultiplied interpolation looks nearly the same as if it were drawn with -// premultiplied interpolation. -static const float kAlphaIncrementPerGradientStep = 0.1f; -static void -ResolvePremultipliedAlpha(nsTArray& aStops) -{ - for (size_t x = 1; x < aStops.Length(); x++) { - const ColorStop leftStop = aStops[x - 1]; - const ColorStop rightStop = aStops[x]; - - // if the left and right stop have the same alpha value, we don't need - // to do anything - if (leftStop.mColor.a == rightStop.mColor.a) { - continue; - } - - // Is the stop on the left 100% transparent? If so, have it adopt the color - // of the right stop - if (leftStop.mColor.a == 0) { - aStops[x - 1].mColor = TransparentColor(rightStop.mColor); - continue; - } - - // Is the stop on the right completely transparent? - // If so, duplicate it and assign it the color on the left. - if (rightStop.mColor.a == 0) { - ColorStop newStop = rightStop; - newStop.mColor = TransparentColor(leftStop.mColor); - aStops.InsertElementAt(x, newStop); - x++; - continue; - } - - // Now handle cases where one or both of the stops are partially transparent. - if (leftStop.mColor.a != 1.0f || rightStop.mColor.a != 1.0f) { - Color premulLeftColor = Premultiply(leftStop.mColor); - Color premulRightColor = Premultiply(rightStop.mColor); - // Calculate how many extra steps. We do a step per 10% transparency. - size_t stepCount = NSToIntFloor(fabsf(leftStop.mColor.a - rightStop.mColor.a) / kAlphaIncrementPerGradientStep); - for (size_t y = 1; y < stepCount; y++) { - float frac = static_cast(y) / stepCount; - ColorStop newStop(Interpolate(leftStop.mPosition, rightStop.mPosition, frac), false, - Unpremultiply(InterpolateColor(premulLeftColor, premulRightColor, frac))); - aStops.InsertElementAt(x, newStop); - x++; - } - } - } -} - static ColorStop InterpolateColorStop(const ColorStop& aFirst, const ColorStop& aSecond, double aPosition, const Color& aDefault) @@ -2522,9 +2443,9 @@ InterpolateColorStop(const ColorStop& aFirst, const ColorStop& aSecond, } return ColorStop(aPosition, false, - Unpremultiply(InterpolateColor(Premultiply(aFirst.mColor), - Premultiply(aSecond.mColor), - (aPosition - aFirst.mPosition) / delta))); + InterpolateColor(aFirst.mColor, + aSecond.mColor, + (aPosition - aFirst.mPosition) / delta)); } // Clamp and extend the given ColorStop array in-place to fit exactly into the @@ -2924,7 +2845,6 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, } ResolveMidpoints(stops); - ResolvePremultipliedAlpha(stops); bool isRepeat = aGradient->mRepeating || forceRepeatToCoverTiles; -- cgit v1.2.3