зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1709746 - Factor out some sRGBColor interpolation code. r=aosmond
I didn't end up needing this for bug 1709719, but I wrote it and might be worth landing. Differential Revision: https://phabricator.services.mozilla.com/D114429
This commit is contained in:
Родитель
904d40e6b7
Коммит
7459740759
|
@ -489,11 +489,38 @@ struct sRGBColor {
|
||||||
((aColor >> 24) & 0xff) * (1.0f / 255.0f));
|
((aColor >> 24) & 0xff) * (1.0f / 255.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ToABGR() const {
|
constexpr uint32_t ToABGR() const {
|
||||||
return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
|
return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
|
||||||
uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
|
uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr sRGBColor Premultiplied() const {
|
||||||
|
return sRGBColor(r * a, g * a, b * a, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr sRGBColor Unpremultiplied() const {
|
||||||
|
return a > 0.f ? sRGBColor(r / a, g / a, b / a, a) : *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns aFrac*aC2 + (1 - aFrac)*C1. The interpolation is done in
|
||||||
|
// unpremultiplied space, which is what SVG gradients and cairo gradients
|
||||||
|
// expect.
|
||||||
|
constexpr static sRGBColor InterpolatePremultiplied(const sRGBColor& aC1,
|
||||||
|
const sRGBColor& aC2,
|
||||||
|
float aFrac) {
|
||||||
|
double other = 1 - aFrac;
|
||||||
|
return sRGBColor(
|
||||||
|
aC2.r * aFrac + aC1.r * other, aC2.g * aFrac + aC1.g * other,
|
||||||
|
aC2.b * aFrac + aC1.b * other, aC2.a * aFrac + aC1.a * other);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr static sRGBColor Interpolate(const sRGBColor& aC1,
|
||||||
|
const sRGBColor& aC2, float aFrac) {
|
||||||
|
return InterpolatePremultiplied(aC1.Premultiplied(), aC2.Premultiplied(),
|
||||||
|
aFrac)
|
||||||
|
.Unpremultiplied();
|
||||||
|
}
|
||||||
|
|
||||||
// The "Unusual" prefix is to avoid unintentionally using this function when
|
// The "Unusual" prefix is to avoid unintentionally using this function when
|
||||||
// ToABGR(), which is much more common, is needed.
|
// ToABGR(), which is much more common, is needed.
|
||||||
uint32_t UnusualToARGB() const {
|
uint32_t UnusualToARGB() const {
|
||||||
|
|
|
@ -245,17 +245,6 @@ static float Interpolate(float aF1, float aF2, float aFrac) {
|
||||||
return aF1 + aFrac * (aF2 - aF1);
|
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
|
|
||||||
// gradients expect.
|
|
||||||
static sRGBColor InterpolateColor(const sRGBColor& aC1, const sRGBColor& aC2,
|
|
||||||
float aFrac) {
|
|
||||||
double other = 1 - aFrac;
|
|
||||||
return sRGBColor(aC2.r * aFrac + aC1.r * other, aC2.g * aFrac + aC1.g * other,
|
|
||||||
aC2.b * aFrac + aC1.b * other,
|
|
||||||
aC2.a * aFrac + aC1.a * other);
|
|
||||||
}
|
|
||||||
|
|
||||||
static nscoord FindTileStart(nscoord aDirtyCoord, nscoord aTilePos,
|
static nscoord FindTileStart(nscoord aDirtyCoord, nscoord aTilePos,
|
||||||
nscoord aTileDim) {
|
nscoord aTileDim) {
|
||||||
NS_ASSERTION(aTileDim > 0, "Non-positive tile dimension");
|
NS_ASSERTION(aTileDim > 0, "Non-positive tile dimension");
|
||||||
|
@ -403,17 +392,6 @@ static void ResolveMidpoints(nsTArray<ColorStop>& stops) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static sRGBColor Premultiply(const sRGBColor& aColor) {
|
|
||||||
gfx::Float a = aColor.a;
|
|
||||||
return sRGBColor(aColor.r * a, aColor.g * a, aColor.b * a, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static sRGBColor Unpremultiply(const sRGBColor& aColor) {
|
|
||||||
gfx::Float a = aColor.a;
|
|
||||||
return (a > 0.f) ? sRGBColor(aColor.r / a, aColor.g / a, aColor.b / a, a)
|
|
||||||
: aColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sRGBColor TransparentColor(sRGBColor aColor) {
|
static sRGBColor TransparentColor(sRGBColor aColor) {
|
||||||
aColor.a = 0;
|
aColor.a = 0;
|
||||||
return aColor;
|
return aColor;
|
||||||
|
@ -456,8 +434,8 @@ static void ResolvePremultipliedAlpha(nsTArray<ColorStop>& aStops) {
|
||||||
// Now handle cases where one or both of the stops are partially
|
// Now handle cases where one or both of the stops are partially
|
||||||
// transparent.
|
// transparent.
|
||||||
if (leftStop.mColor.a != 1.0f || rightStop.mColor.a != 1.0f) {
|
if (leftStop.mColor.a != 1.0f || rightStop.mColor.a != 1.0f) {
|
||||||
sRGBColor premulLeftColor = Premultiply(leftStop.mColor);
|
sRGBColor premulLeftColor = leftStop.mColor.Premultiplied();
|
||||||
sRGBColor premulRightColor = Premultiply(rightStop.mColor);
|
sRGBColor premulRightColor = rightStop.mColor.Premultiplied();
|
||||||
// Calculate how many extra steps. We do a step per 10% transparency.
|
// Calculate how many extra steps. We do a step per 10% transparency.
|
||||||
size_t stepCount =
|
size_t stepCount =
|
||||||
NSToIntFloor(fabsf(leftStop.mColor.a - rightStop.mColor.a) /
|
NSToIntFloor(fabsf(leftStop.mColor.a - rightStop.mColor.a) /
|
||||||
|
@ -466,8 +444,9 @@ static void ResolvePremultipliedAlpha(nsTArray<ColorStop>& aStops) {
|
||||||
float frac = static_cast<float>(y) / stepCount;
|
float frac = static_cast<float>(y) / stepCount;
|
||||||
ColorStop newStop(
|
ColorStop newStop(
|
||||||
Interpolate(leftStop.mPosition, rightStop.mPosition, frac), false,
|
Interpolate(leftStop.mPosition, rightStop.mPosition, frac), false,
|
||||||
Unpremultiply(
|
sRGBColor::InterpolatePremultiplied(premulLeftColor,
|
||||||
InterpolateColor(premulLeftColor, premulRightColor, frac)));
|
premulRightColor, frac)
|
||||||
|
.Unpremultiplied());
|
||||||
aStops.InsertElementAt(x, newStop);
|
aStops.InsertElementAt(x, newStop);
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
@ -487,10 +466,10 @@ static ColorStop InterpolateColorStop(const ColorStop& aFirst,
|
||||||
return ColorStop(aPosition, false, aDefault);
|
return ColorStop(aPosition, false, aDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ColorStop(aPosition, false,
|
return ColorStop(
|
||||||
Unpremultiply(InterpolateColor(
|
aPosition, false,
|
||||||
Premultiply(aFirst.mColor), Premultiply(aSecond.mColor),
|
sRGBColor::Interpolate(aFirst.mColor, aSecond.mColor,
|
||||||
(aPosition - aFirst.mPosition) / delta)));
|
(aPosition - aFirst.mPosition) / delta));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp and extend the given ColorStop array in-place to fit exactly into the
|
// Clamp and extend the given ColorStop array in-place to fit exactly into the
|
||||||
|
@ -861,8 +840,8 @@ void nsCSSGradientRenderer::Paint(gfxContext& aContext, const nsRect& aDest,
|
||||||
// XXX Color interpolation (in cairo, too) should use the
|
// XXX Color interpolation (in cairo, too) should use the
|
||||||
// CSS 'color-interpolation' property!
|
// CSS 'color-interpolation' property!
|
||||||
float frac = float((0.0 - pos) / (nextPos - pos));
|
float frac = float((0.0 - pos) / (nextPos - pos));
|
||||||
mStops[i].mColor = InterpolateColor(mStops[i].mColor,
|
mStops[i].mColor = sRGBColor::InterpolatePremultiplied(
|
||||||
mStops[i + 1].mColor, frac);
|
mStops[i].mColor, mStops[i + 1].mColor, frac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче