зеркало из https://github.com/mozilla/gecko-dev.git
Implement nsStyleAnimation::Add and Interpolate using the same code underneath. (Bug 523193) r=dholbert sr=bzbarsky
This commit is contained in:
Родитель
8461beec27
Коммит
d035804a7a
|
@ -88,83 +88,6 @@ GetCommonUnit(nsStyleAnimation::Unit aFirstUnit,
|
||||||
// CLASS METHODS
|
// CLASS METHODS
|
||||||
// -------------
|
// -------------
|
||||||
|
|
||||||
#define MAX_PACKED_COLOR_COMPONENT 255
|
|
||||||
|
|
||||||
inline PRUint8 ClampColor(PRUint32 aColor)
|
|
||||||
{
|
|
||||||
if (aColor >= MAX_PACKED_COLOR_COMPONENT)
|
|
||||||
return MAX_PACKED_COLOR_COMPONENT;
|
|
||||||
return aColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsStyleAnimation::Add(Value& aDest, const Value& aValueToAdd,
|
|
||||||
PRUint32 aCount)
|
|
||||||
{
|
|
||||||
Unit commonUnit = GetCommonUnit(aDest.GetUnit(), aValueToAdd.GetUnit());
|
|
||||||
PRBool success = PR_TRUE;
|
|
||||||
switch (commonUnit) {
|
|
||||||
case eUnit_Coord: {
|
|
||||||
nscoord destCoord = aDest.GetCoordValue();
|
|
||||||
nscoord valueToAddCoord = aValueToAdd.GetCoordValue();
|
|
||||||
destCoord += aCount * valueToAddCoord;
|
|
||||||
aDest.SetCoordValue(destCoord);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eUnit_Percent: {
|
|
||||||
float destPct = aDest.GetPercentValue();
|
|
||||||
float valueToAddPct = aValueToAdd.GetPercentValue();
|
|
||||||
destPct += aCount * valueToAddPct;
|
|
||||||
aDest.SetPercentValue(destPct);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eUnit_Float: {
|
|
||||||
float destFloat = aDest.GetFloatValue();
|
|
||||||
float valueToAddFloat = aValueToAdd.GetFloatValue();
|
|
||||||
destFloat += aCount * valueToAddFloat;
|
|
||||||
aDest.SetFloatValue(destFloat);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eUnit_Color: {
|
|
||||||
// Since nscolor doesn't allow out-of-sRGB values, by-animations
|
|
||||||
// of colors don't make much sense in our implementation.
|
|
||||||
// FIXME (bug 515919): Animation of colors should really use
|
|
||||||
// floating point colors (and when it does, ClampColor and the
|
|
||||||
// clamping of aCount should go away).
|
|
||||||
// Also, given RGBA colors, it's not clear whether we want
|
|
||||||
// premultiplication. Probably we don't, given that's hard to
|
|
||||||
// premultiply aValueToAdd since it's a difference rather than a
|
|
||||||
// value.
|
|
||||||
nscolor destColor = aDest.GetColorValue();
|
|
||||||
nscolor colorToAdd = aValueToAdd.GetColorValue();
|
|
||||||
if (aCount > MAX_PACKED_COLOR_COMPONENT) {
|
|
||||||
// Given that we're using integers and clamping at 255, we can
|
|
||||||
// clamp aCount to 255 since that's enough to saturate if we're
|
|
||||||
// multiplying it by anything nonzero.
|
|
||||||
aCount = MAX_PACKED_COLOR_COMPONENT;
|
|
||||||
}
|
|
||||||
PRUint8 resultR =
|
|
||||||
ClampColor(NS_GET_R(destColor) + aCount * NS_GET_R(colorToAdd));
|
|
||||||
PRUint8 resultG =
|
|
||||||
ClampColor(NS_GET_G(destColor) + aCount * NS_GET_G(colorToAdd));
|
|
||||||
PRUint8 resultB =
|
|
||||||
ClampColor(NS_GET_B(destColor) + aCount * NS_GET_B(colorToAdd));
|
|
||||||
PRUint8 resultA =
|
|
||||||
ClampColor(NS_GET_A(destColor) + aCount * NS_GET_A(colorToAdd));
|
|
||||||
aDest.SetColorValue(NS_RGBA(resultR, resultG, resultB, resultA));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eUnit_Null:
|
|
||||||
success = PR_FALSE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NS_NOTREACHED("Can't add Values using the given common unit");
|
|
||||||
success = PR_FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsStyleAnimation::ComputeDistance(const Value& aStartValue,
|
nsStyleAnimation::ComputeDistance(const Value& aStartValue,
|
||||||
const Value& aEndValue,
|
const Value& aEndValue,
|
||||||
|
@ -240,15 +163,23 @@ nsStyleAnimation::ComputeDistance(const Value& aStartValue,
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_PACKED_COLOR_COMPONENT 255
|
||||||
|
|
||||||
|
inline PRUint8 ClampColor(double aColor)
|
||||||
|
{
|
||||||
|
if (aColor >= MAX_PACKED_COLOR_COMPONENT)
|
||||||
|
return MAX_PACKED_COLOR_COMPONENT;
|
||||||
|
if (aColor <= 0.0)
|
||||||
|
return 0;
|
||||||
|
return NSToIntRound(aColor);
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsStyleAnimation::Interpolate(const Value& aStartValue,
|
nsStyleAnimation::AddWeighted(double aCoeff1, const Value& aValue1,
|
||||||
const Value& aEndValue,
|
double aCoeff2, const Value& aValue2,
|
||||||
double aPortion,
|
|
||||||
Value& aResultValue)
|
Value& aResultValue)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(aPortion >= 0.0 && aPortion <= 1.0,
|
Unit commonUnit = GetCommonUnit(aValue1.GetUnit(), aValue2.GetUnit());
|
||||||
"aPortion out of bounds");
|
|
||||||
Unit commonUnit = GetCommonUnit(aStartValue.GetUnit(), aEndValue.GetUnit());
|
|
||||||
// Maybe need a followup method to convert the inputs into the common
|
// Maybe need a followup method to convert the inputs into the common
|
||||||
// unit-type, if they don't already match it. (Or would it make sense to do
|
// unit-type, if they don't already match it. (Or would it make sense to do
|
||||||
// that in GetCommonUnit? in which case maybe ConvertToCommonUnit would be
|
// that in GetCommonUnit? in which case maybe ConvertToCommonUnit would be
|
||||||
|
@ -257,31 +188,26 @@ nsStyleAnimation::Interpolate(const Value& aStartValue,
|
||||||
PRBool success = PR_TRUE;
|
PRBool success = PR_TRUE;
|
||||||
switch (commonUnit) {
|
switch (commonUnit) {
|
||||||
case eUnit_Coord: {
|
case eUnit_Coord: {
|
||||||
nscoord startCoord = aStartValue.GetCoordValue();
|
aResultValue.SetCoordValue(NSToCoordRound(
|
||||||
nscoord endCoord = aEndValue.GetCoordValue();
|
aCoeff1 * aValue1.GetCoordValue() +
|
||||||
nscoord resultCoord = startCoord +
|
aCoeff2 * aValue2.GetCoordValue()));
|
||||||
NSToCoordRound(aPortion * (endCoord - startCoord));
|
|
||||||
aResultValue.SetCoordValue(resultCoord);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eUnit_Percent: {
|
case eUnit_Percent: {
|
||||||
float startPct = aStartValue.GetPercentValue();
|
aResultValue.SetPercentValue(
|
||||||
float endPct = aEndValue.GetPercentValue();
|
aCoeff1 * aValue1.GetPercentValue() +
|
||||||
float resultPct = startPct + aPortion * (endPct - startPct);
|
aCoeff2 * aValue2.GetPercentValue());
|
||||||
aResultValue.SetPercentValue(resultPct);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eUnit_Float: {
|
case eUnit_Float: {
|
||||||
float startFloat = aStartValue.GetFloatValue();
|
aResultValue.SetFloatValue(
|
||||||
float endFloat = aEndValue.GetFloatValue();
|
aCoeff1 * aValue1.GetFloatValue() +
|
||||||
float resultFloat = startFloat + aPortion * (endFloat - startFloat);
|
aCoeff2 * aValue2.GetFloatValue());
|
||||||
aResultValue.SetFloatValue(resultFloat);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eUnit_Color: {
|
case eUnit_Color: {
|
||||||
double inv = 1.0 - aPortion;
|
nscolor color1 = aValue1.GetColorValue();
|
||||||
nscolor startColor = aStartValue.GetColorValue();
|
nscolor color2 = aValue2.GetColorValue();
|
||||||
nscolor endColor = aEndValue.GetColorValue();
|
|
||||||
// FIXME (spec): The CSS transitions spec doesn't say whether
|
// FIXME (spec): The CSS transitions spec doesn't say whether
|
||||||
// colors are premultiplied, but things work better when they are,
|
// colors are premultiplied, but things work better when they are,
|
||||||
// so use premultiplication. Spec issue is still open per
|
// so use premultiplication. Spec issue is still open per
|
||||||
|
@ -289,25 +215,28 @@ nsStyleAnimation::Interpolate(const Value& aStartValue,
|
||||||
|
|
||||||
// To save some math, scale the alpha down to a 0-1 scale, but
|
// To save some math, scale the alpha down to a 0-1 scale, but
|
||||||
// leave the color components on a 0-255 scale.
|
// leave the color components on a 0-255 scale.
|
||||||
double startA = NS_GET_A(startColor) * (1.0 / 255.0);
|
double A1 = NS_GET_A(color1) * (1.0 / 255.0);
|
||||||
double startR = NS_GET_R(startColor) * startA;
|
double R1 = NS_GET_R(color1) * A1;
|
||||||
double startG = NS_GET_G(startColor) * startA;
|
double G1 = NS_GET_G(color1) * A1;
|
||||||
double startB = NS_GET_B(startColor) * startA;
|
double B1 = NS_GET_B(color1) * A1;
|
||||||
double endA = NS_GET_A(endColor) * (1.0 / 255.0);
|
double A2 = NS_GET_A(color2) * (1.0 / 255.0);
|
||||||
double endR = NS_GET_R(endColor) * endA;
|
double R2 = NS_GET_R(color2) * A2;
|
||||||
double endG = NS_GET_G(endColor) * endA;
|
double G2 = NS_GET_G(color2) * A2;
|
||||||
double endB = NS_GET_B(endColor) * endA;
|
double B2 = NS_GET_B(color2) * A2;
|
||||||
double resAf = (startA * inv + endA * aPortion);
|
double Aresf = (A1 * aCoeff1 + A2 * aCoeff2);
|
||||||
nscolor resultColor;
|
nscolor resultColor;
|
||||||
if (resAf == 0.0) {
|
if (Aresf <= 0.0) {
|
||||||
resultColor = NS_RGBA(0, 0, 0, 0);
|
resultColor = NS_RGBA(0, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
double factor = 1.0 / resAf;
|
if (Aresf > 1.0) {
|
||||||
PRUint8 resA = NSToIntRound(resAf * 255.0);
|
Aresf = 1.0;
|
||||||
PRUint8 resR = NSToIntRound((startR * inv + endR * aPortion) * factor);
|
}
|
||||||
PRUint8 resG = NSToIntRound((startG * inv + endG * aPortion) * factor);
|
double factor = 1.0 / Aresf;
|
||||||
PRUint8 resB = NSToIntRound((startB * inv + endB * aPortion) * factor);
|
PRUint8 Ares = NSToIntRound(Aresf * 255.0);
|
||||||
resultColor = NS_RGBA(resR, resG, resB, resA);
|
PRUint8 Rres = ClampColor((R1 * aCoeff1 + R2 * aCoeff2) * factor);
|
||||||
|
PRUint8 Gres = ClampColor((G1 * aCoeff1 + G2 * aCoeff2) * factor);
|
||||||
|
PRUint8 Bres = ClampColor((B1 * aCoeff1 + B2 * aCoeff2) * factor);
|
||||||
|
resultColor = NS_RGBA(Rres, Gres, Bres, Ares);
|
||||||
}
|
}
|
||||||
aResultValue.SetColorValue(resultColor);
|
aResultValue.SetColorValue(resultColor);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -75,7 +75,9 @@ public:
|
||||||
* @return PR_TRUE on success, PR_FALSE on failure.
|
* @return PR_TRUE on success, PR_FALSE on failure.
|
||||||
*/
|
*/
|
||||||
static PRBool Add(Value& aDest, const Value& aValueToAdd,
|
static PRBool Add(Value& aDest, const Value& aValueToAdd,
|
||||||
PRUint32 aCount);
|
PRUint32 aCount) {
|
||||||
|
return AddWeighted(1.0, aDest, aCount, aValueToAdd, aDest);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates a measure of 'distance' between two values.
|
* Calculates a measure of 'distance' between two values.
|
||||||
|
@ -113,6 +115,28 @@ public:
|
||||||
static PRBool Interpolate(const Value& aStartValue,
|
static PRBool Interpolate(const Value& aStartValue,
|
||||||
const Value& aEndValue,
|
const Value& aEndValue,
|
||||||
double aPortion,
|
double aPortion,
|
||||||
|
Value& aResultValue) {
|
||||||
|
NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
|
||||||
|
return AddWeighted(1.0 - aPortion, aStartValue, aPortion, aEndValue,
|
||||||
|
aResultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the calculation:
|
||||||
|
* aResultValue = aCoeff1 * aValue1 + aCoeff2 * aValue2
|
||||||
|
*
|
||||||
|
* @param [out] aResultValue The resulting interpolated value. May be
|
||||||
|
* the same as aValue1 or aValue2.
|
||||||
|
* @return PR_TRUE on success, PR_FALSE on failure.
|
||||||
|
*
|
||||||
|
* NOTE: Current callers always pass aCoeff1 and aCoeff2 >= 0. They
|
||||||
|
* are currently permitted to be negative; however, if, as we add
|
||||||
|
* support more value types types, we find that this causes
|
||||||
|
* difficulty, we might change this to restrict them to being
|
||||||
|
* positive.
|
||||||
|
*/
|
||||||
|
static PRBool AddWeighted(double aCoeff1, const Value& aValue1,
|
||||||
|
double aCoeff2, const Value& aValue2,
|
||||||
Value& aResultValue);
|
Value& aResultValue);
|
||||||
|
|
||||||
// Type-conversion methods
|
// Type-conversion methods
|
||||||
|
|
Загрузка…
Ссылка в новой задаче