Bug 1299741 part 9 - Implement interpolation between numeric color and currentcolor. r=birtles
MozReview-Commit-ID: DuB6FZYveXE
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -65,16 +65,25 @@ GetCommonUnit(nsCSSPropertyID aProperty,
aFirstUnit == StyleAnimationValue::eUnit_Percent ||
aFirstUnit == StyleAnimationValue::eUnit_Calc) &&
(aSecondUnit == StyleAnimationValue::eUnit_Coord ||
aSecondUnit == StyleAnimationValue::eUnit_Percent ||
aSecondUnit == StyleAnimationValue::eUnit_Calc)) {
// We can use calc() as the common unit.
return StyleAnimationValue::eUnit_Calc;
}
+ if ((aFirstUnit == StyleAnimationValue::eUnit_Color ||
+ aFirstUnit == StyleAnimationValue::eUnit_CurrentColor ||
+ aFirstUnit == StyleAnimationValue::eUnit_ComplexColor) &&
+ (aSecondUnit == StyleAnimationValue::eUnit_Color ||
+ aSecondUnit == StyleAnimationValue::eUnit_CurrentColor ||
+ aSecondUnit == StyleAnimationValue::eUnit_ComplexColor)) {
+ // We can use complex color as the common unit.
+ return StyleAnimationValue::eUnit_ComplexColor;
+ }
return StyleAnimationValue::eUnit_Null;
}
return aFirstUnit;
}
static
nsCSSUnit
GetCommonUnit(nsCSSPropertyID aProperty,
@@ -513,16 +522,32 @@ static RGBAColorData
ExtractColor(const StyleAnimationValue& aValue)
{
MOZ_ASSERT(aValue.GetUnit() == StyleAnimationValue::eUnit_Color);
nsCSSValue* value = aValue.GetCSSValueValue();
MOZ_ASSERT(value, "CSS value must be valid");
return ExtractColor(*value);
}
+static ComplexColorData
+ExtractComplexColor(const StyleAnimationValue& aValue)
+{
+ switch (aValue.GetUnit()) {
+ case StyleAnimationValue::eUnit_Color:
+ return ComplexColorData(ExtractColor(aValue), 0.0f);
+ case StyleAnimationValue::eUnit_CurrentColor:
+ return ComplexColorData({0, 0, 0, 0}, 1.0f);
+ case StyleAnimationValue::eUnit_ComplexColor:
+ return ComplexColorData(aValue.GetComplexColorData());
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unknown unit");
+ return ComplexColorData({0, 0, 0, 0}, 0.0f);
+ }
+}
+
double
StyleAnimationValue::ComputeColorDistance(const RGBAColorData& aStartColor,
const RGBAColorData& aEndColor)
{
// http://www.w3.org/TR/smil-animation/#animateColorElement says
// that we should use Euclidean RGB cube distance. However, we
// have to extend that to RGBA. For now, we'll just use the
// Euclidean distance in the (part of the) 4-cube of premultiplied
@@ -554,17 +579,16 @@ StyleAnimationValue::ComputeDistance(nsC
switch (commonUnit) {
case eUnit_Null:
case eUnit_Auto:
case eUnit_None:
case eUnit_Normal:
case eUnit_UnparsedString:
case eUnit_URL:
- case eUnit_CurrentColor:
case eUnit_DiscreteCSSValue:
return false;
case eUnit_Enumerated:
switch (aProperty) {
case eCSSProperty_font_stretch: {
// just like eUnit_Integer.
int32_t startInt = aStartValue.GetIntValue();
@@ -613,16 +637,41 @@ StyleAnimationValue::ComputeDistance(nsC
aDistance = Abs(double(endFloat) - double(startFloat));
return true;
}
case eUnit_Color: {
aDistance = ComputeColorDistance(ExtractColor(aStartValue),
ExtractColor(aEndValue));
return true;
}
+ case eUnit_CurrentColor: {
+ aDistance = 0;
+ return true;
+ }
+ case eUnit_ComplexColor: {
+ ComplexColorData color1 = ExtractComplexColor(aStartValue);
+ ComplexColorData color2 = ExtractComplexColor(aEndValue);
+ // Common case is interpolating between a color and a currentcolor
+ if (color1.IsNumericColor() && color2.IsCurrentColor()) {
+ double dist = ComputeColorDistance(color1.mColor, NS_RGBA(0, 0, 0, 0));
+ aDistance = sqrt(dist * dist + 1);
+ return true;
+ }
+ if (color1.IsCurrentColor() && color2.IsNumericColor()) {
+ double dist = ComputeColorDistance(NS_RGBA(0, 0, 0, 0), color2.mColor);
+ aDistance = sqrt(dist * dist + 1);
+ return true;
+ }
+ // If we ever reach here, we may want to use the code in
+ // bug 1299741 comment 79 to compute it.
+ MOZ_ASSERT_UNREACHABLE("We shouldn't get here as we only call "
+ "ComputeDistance on pre-interpolation values");
+ aDistance = 0.0;
+ return true;
+ }
case eUnit_Calc: {
PixelCalcValue v1 = ExtractCalcValue(aStartValue);
PixelCalcValue v2 = ExtractCalcValue(aEndValue);
float difflen = v2.mLength - v1.mLength;
float diffpct = v2.mPercent - v1.mPercent;
aDistance = sqrt(difflen * difflen + diffpct * diffpct);
return true;
}
@@ -2433,17 +2482,16 @@ StyleAnimationValue::AddWeighted(nsCSSPr
switch (commonUnit) {
case eUnit_Null:
case eUnit_Auto:
case eUnit_None:
case eUnit_Normal:
case eUnit_UnparsedString:
case eUnit_URL:
- case eUnit_CurrentColor:
case eUnit_DiscreteCSSValue:
return false;
case eUnit_Enumerated:
switch (aProperty) {
case eCSSProperty_font_stretch: {
// Animate just like eUnit_Integer.
int32_t result = floor(aCoeff1 * double(aValue1.GetIntValue()) +
@@ -2518,16 +2566,48 @@ StyleAnimationValue::AddWeighted(nsCSSPr
RGBAColorData color1 = ExtractColor(aValue1);
RGBAColorData color2 = ExtractColor(aValue2);
auto resultColor = MakeUnique<nsCSSValue>();
resultColor->SetColorValue(
AddWeightedColorsAndClamp(aCoeff1, color1, aCoeff2, color2));
aResultValue.SetAndAdoptCSSValueValue(resultColor.release(), eUnit_Color);
return true;
}
+ case eUnit_CurrentColor: {
+ aResultValue.SetCurrentColorValue();
+ return true;
+ }
+ case eUnit_ComplexColor: {
+ ComplexColorData color1 = ExtractComplexColor(aValue1);
+ ComplexColorData color2 = ExtractComplexColor(aValue2);
+ RefPtr<ComplexColorValue> result = new ComplexColorValue;
+ // Common case is interpolating between a color and a currentcolor.
+ if (color1.IsNumericColor() && color2.IsCurrentColor()) {
+ result->mColor = color1.mColor;
+ result->mForegroundRatio = aCoeff2;
+ } else if (color1.IsCurrentColor() && color2.IsNumericColor()) {
+ result->mColor = color2.mColor;
+ result->mForegroundRatio = aCoeff1;
+ } else {
+ float ratio1 = 1.0f - color1.mForegroundRatio;
+ float ratio2 = 1.0f - color2.mForegroundRatio;
+ float alpha1 = color1.mColor.mA * ratio1;
+ float alpha2 = color2.mColor.mA * ratio2;
+ RGBAColorData resultColor =
+ AddWeightedColors(aCoeff1, color1.mColor.WithAlpha(alpha1),
+ aCoeff2, color2.mColor.WithAlpha(alpha2));
+ float resultRatio = color1.mForegroundRatio * aCoeff1 +
+ color2.mForegroundRatio * aCoeff2;
+ float resultAlpha = resultColor.mA / (1.0f - resultRatio);
+ result->mColor = resultColor.WithAlpha(resultAlpha);
+ result->mForegroundRatio = resultRatio;
+ }
+ aResultValue.SetComplexColorValue(result.forget());
+ return true;
+ }
case eUnit_Calc: {
PixelCalcValue v1 = ExtractCalcValue(aValue1);
PixelCalcValue v2 = ExtractCalcValue(aValue2);
double len = aCoeff1 * v1.mLength + aCoeff2 * v2.mLength;
double pct = aCoeff1 * v1.mPercent + aCoeff2 * v2.mPercent;
bool hasPct = (aCoeff1 != 0.0 && v1.mHasPercent) ||
(aCoeff2 != 0.0 && v2.mHasPercent);
nsCSSValue *val = new nsCSSValue();
@@ -4285,16 +4365,21 @@ StyleAnimationValue::ExtractComputedValu
// interpolation with it.
aComputedValue.SetNoneValue();
}
return true;
case eStyleAnimType_Color:
aComputedValue.SetColorValue(
StyleDataAtOffset<nscolor>(styleStruct, ssOffset));
return true;
+ case eStyleAnimType_ComplexColor: {
+ aComputedValue.SetComplexColorValue(
+ StyleDataAtOffset<StyleComplexColor>(styleStruct, ssOffset));
+ return true;
+ }
case eStyleAnimType_PaintServer: {
const nsStyleSVGPaint& paint =
StyleDataAtOffset<nsStyleSVGPaint>(styleStruct, ssOffset);
if (paint.mType == eStyleSVGPaintType_Color) {
aComputedValue.SetColorValue(paint.mPaint.mColor);
return true;
}
if (paint.mType == eStyleSVGPaintType_Server) {
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -310,16 +310,19 @@ enum nsStyleAnimType {
eStyleAnimType_nscoord,
// float values
eStyleAnimType_float,
// nscolor values
eStyleAnimType_Color,
+ // StyleComplexColor values
+ eStyleAnimType_ComplexColor,
+
// nsStyleSVGPaint values
eStyleAnimType_PaintServer,
// RefPtr<nsCSSShadowArray> values
eStyleAnimType_Shadow,
// discrete values
eStyleAnimType_Discrete,