mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
CSS: Stop using premultiplied color space for gradients.
This commit is contained in:
parent
8b0f28c3f7
commit
21defafa0b
6 changed files with 4 additions and 90 deletions
|
|
@ -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<ColorStop>& 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<ColorStop>& 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<float>(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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
<div style="background: linear-gradient(to right, rgba(255, 0, 0, .9) 0% , rgba(255, 0, 0, 0) 50%, rgba(0, 0, 255, 0) 50%, rgba(0, 0, 255, 1) 100%) no-repeat; width: 300px; height: 300px;"><br></div>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<div style="background: linear-gradient(to right, rgba(255, 0, 0, .9) 0% , rgba(0, 255, 0, 0) 50%, rgba(0, 0, 255, 1) 100%) no-repeat; width: 300px; height: 300px;"><br></div>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<div style="background: radial-gradient(rgba(255, 0, 0, .9) 0% , rgba(255, 0, 0, 0) 50%, rgba(0, 0, 255, 0) 50%, rgba(0, 0, 255, 1) 100%) no-repeat; width: 300px; height: 300px;"><br></div>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<div style="background: radial-gradient(rgba(255, 0, 0, .9) 0% , rgba(0, 255, 0, 0) 50%, rgba(0, 0, 255, 1) 100%) no-repeat; width: 300px; height: 300px;"><br></div>
|
||||
|
|
@ -16,7 +16,6 @@ fuzzy-if(!contentSameGfxBackendAsCanvas,4,92400) fuzzy-if(azureSkiaGL||skiaConte
|
|||
== linear-diagonal-4a.html linear-diagonal-4-ref.html
|
||||
== linear-diagonal-4b.html linear-diagonal-4-ref.html
|
||||
== linear-diagonal-4c.html linear-diagonal-4-ref.html
|
||||
== linear-premul.html linear-premul-ref.html
|
||||
|
||||
# these tests uses a similar gradient over different bounds. It's perfectly
|
||||
# reasonable to expect implementations to give slightly different results
|
||||
|
|
@ -92,7 +91,6 @@ fuzzy-if(Android,4,248) == radial-zero-length-1g.html radial-zero-length-1-ref.h
|
|||
fuzzy-if(Android,4,248) == radial-zero-length-1h.html radial-zero-length-1-ref.html
|
||||
fuzzy-if(Android,4,248) == radial-zero-length-1i.html radial-zero-length-1-ref.html
|
||||
fuzzy-if(Android,4,248) == radial-zero-length-1j.html radial-zero-length-1-ref.html
|
||||
== radial-premul.html radial-premul-ref.html
|
||||
== repeated-final-stop-1.html repeated-final-stop-1-ref.html
|
||||
== repeating-linear-1a.html repeating-linear-1-ref.html
|
||||
== repeating-linear-1b.html repeating-linear-1-ref.html
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue