diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index 1ec1c8910bf1..ac95c65d95fe 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -1192,9 +1192,18 @@ GetPremultipliedColorComponents(const nsCSSValue& aValue) alpha); } +enum class ColorAdditionType { + Clamped, // Clamp each color channel after adding. + Unclamped // Do not clamp color channels after adding. +}; + +// |aAdditionType| should be Clamped in case of interpolation or SMIL +// animation (e.g. 'by' attribute). For now, Unclamped is only for +// accumulation. static void AddWeightedColors(double aCoeff1, const nsCSSValue& aValue1, double aCoeff2, const nsCSSValue& aValue2, + ColorAdditionType aAdditionType, nsCSSValue& aResult) { MOZ_ASSERT(aValue1.IsNumericColorUnit() && aValue2.IsNumericColorUnit(), @@ -1222,11 +1231,23 @@ AddWeightedColors(double aCoeff1, const nsCSSValue& aValue1, } double factor = 1.0 / Aresf; - uint8_t Ares = NSToIntRound(Aresf * 255.0); - uint8_t Rres = ClampColor((R1 * aCoeff1 + R2 * aCoeff2) * factor); - uint8_t Gres = ClampColor((G1 * aCoeff1 + G2 * aCoeff2) * factor); - uint8_t Bres = ClampColor((B1 * aCoeff1 + B2 * aCoeff2) * factor); - aResult.SetColorValue(NS_RGBA(Rres, Gres, Bres, Ares)); + double Rres = (R1 * aCoeff1 + R2 * aCoeff2) * factor; + double Gres = (G1 * aCoeff1 + G2 * aCoeff2) * factor; + double Bres = (B1 * aCoeff1 + B2 * aCoeff2) * factor; + + if (aAdditionType == ColorAdditionType::Clamped) { + aResult.SetColorValue( + NS_RGBA(ClampColor(Rres), ClampColor(Gres), ClampColor(Bres), + NSToIntRound(Aresf * 255.0))); + return; + } + + Rres = Rres * (1.0 / 255.0); + Gres = Gres * (1.0 / 255.0); + Bres = Bres * (1.0 / 255.0); + + aResult.SetFloatColorValue(Rres, Gres, Bres, Aresf, + eCSSUnit_PercentageRGBAColor); } // Multiplies |aValue| color by |aDilutionRation| with premultiplication. @@ -1282,10 +1303,13 @@ AddShadowItems(double aCoeff1, const nsCSSValue &aValue1, const nsCSSValue& color2 = array2->Item(4); const nsCSSValue& inset1 = array1->Item(5); const nsCSSValue& inset2 = array2->Item(5); - if (color1.GetUnit() != color2.GetUnit() || + if ((color1.GetUnit() != color2.GetUnit() && + (!color1.IsNumericColorUnit() || !color2.IsNumericColorUnit())) || inset1.GetUnit() != inset2.GetUnit()) { // We don't know how to animate between color and no-color, or // between inset and not-inset. + // NOTE: In case when both colors' units are eCSSUnit_Null, that means + // neither color value was specified, so we can interpolate. return false; } @@ -1293,7 +1317,9 @@ AddShadowItems(double aCoeff1, const nsCSSValue &aValue1, if (aCoeff2 == 0.0 && aCoeff1 != 1.0) { DiluteColor(color1, aCoeff1, resultArray->Item(4)); } else { - AddWeightedColors(aCoeff1, color1, aCoeff2, color2, resultArray->Item(4)); + AddWeightedColors(aCoeff1, color1, aCoeff2, color2, + ColorAdditionType::Clamped, + resultArray->Item(4)); } } @@ -2447,7 +2473,9 @@ StyleAnimationValue::AddWeighted(nsCSSPropertyID aProperty, if (aCoeff2 == 0.0) { DiluteColor(*value1, aCoeff1, *resultColor); } else { - AddWeightedColors(aCoeff1, *value1, aCoeff2, *value2, *resultColor); + AddWeightedColors(aCoeff1, *value1, aCoeff2, *value2, + ColorAdditionType::Clamped, + *resultColor); } aResultValue.SetAndAdoptCSSValueValue(resultColor.release(), eUnit_Color); return true; @@ -2838,9 +2866,20 @@ StyleAnimationValue::Accumulate(nsCSSPropertyID aProperty, GetCommonUnit(aProperty, aDest.GetUnit(), aValueToAccumulate.GetUnit()); switch (commonUnit) { // FIXME: implement them! - //case eUnit_Color: //case eUnit_Shadow: //case eUnit_Filter: + case eUnit_Color: { + auto resultColor = MakeUnique(); + AddWeightedColors(1.0, + *aDest.GetCSSValueValue(), + aCount, + *aValueToAccumulate.GetCSSValueValue(), + ColorAdditionType::Unclamped, + *resultColor); + + aDest.SetAndAdoptCSSValueValue(resultColor.release(), eUnit_Color); + return true; + } default: return Add(aProperty, aDest, aValueToAccumulate, aCount); } diff --git a/testing/web-platform/meta/web-animations/interfaces/KeyframeEffect/iterationComposite.html.ini b/testing/web-platform/meta/web-animations/interfaces/KeyframeEffect/iterationComposite.html.ini index 6cd2752d228a..5732cbe494a1 100644 --- a/testing/web-platform/meta/web-animations/interfaces/KeyframeEffect/iterationComposite.html.ini +++ b/testing/web-platform/meta/web-animations/interfaces/KeyframeEffect/iterationComposite.html.ini @@ -1,8 +1,5 @@ [iterationComposite.html] type: testharness - [iterationComposite of type animation] - expected: FAIL - [iterationComposite of filter drop-shadow animation] expected: FAIL