Bug 1358966 - Make an argument of ComputePacedTotalDistances an array of double. r?birtles
MozReview-Commit-ID: F6nwbcFQQuj
--- a/dom/smil/nsSMILAnimationFunction.cpp
+++ b/dom/smil/nsSMILAnimationFunction.cpp
@@ -486,16 +486,25 @@ nsSMILAnimationFunction::AccumulateResul
// If the target attribute type doesn't support addition, Add will
// fail and we leave aResult untouched.
aResult.Add(lastValue, mRepeatIteration);
}
return NS_OK;
}
+static void
+ClampDistances(AutoTArray<double, 1>& aDistances)
+{
+ for (size_t i = 0; i < aDistances.Length(); i++) {
+ MOZ_ASSERT(aDistances[i] >= 0.0f, "distance values must be non-negative");
+ aDistances[i] = std::max(aDistances[i], 0.0);
+ }
+}
+
/*
* Given the simple progress for a paced animation, this method:
* - determines which two elements of the values array we're in between
* (returned as aFrom and aTo)
* - determines where we are between them
* (returned as aIntervalProgress)
*
* Returns NS_OK, or NS_ERROR_FAILURE if our values don't support distance
@@ -519,114 +528,133 @@ nsSMILAnimationFunction::ComputePacedPos
// same as our overall progress.
if (aValues.Length() == 2) {
aIntervalProgress = aSimpleProgress;
aFrom = &aValues[0];
aTo = &aValues[1];
return NS_OK;
}
- double totalDistance = ComputePacedTotalDistance(aValues);
- if (totalDistance == COMPUTE_DISTANCE_ERROR)
- return NS_ERROR_FAILURE;
-
- // If we have 0 total distance, then it's unclear where our "paced" position
- // should be. We can just fail, which drops us into discrete animation mode.
- // (That's fine, since our values are apparently indistinguishable anyway.)
- if (totalDistance == 0.0) {
+ AutoTArray<double, 1> totalDistances;
+ if (!ComputePacedTotalDistances(aValues, totalDistances)) {
return NS_ERROR_FAILURE;
}
// total distance we should have moved at this point in time.
// (called 'remainingDist' due to how it's used in loop below)
- double remainingDist = aSimpleProgress * totalDistance;
-
- // Must be satisfied, because totalDistance is a sum of (non-negative)
- // distances, and aSimpleProgress is non-negative
- NS_ASSERTION(remainingDist >= 0, "distance values must be non-negative");
+ AutoTArray<double, 1> remainingDists;
+ size_t len = totalDistances.Length();
+ remainingDists.SetLength(len);
+ for (size_t i = 0; i < len; i++) {
+ // If we have 0 total distance, then it's unclear where our "paced" position
+ // should be. We can just fail, which drops us into discrete animation mode.
+ // (That's fine, since our values are apparently indistinguishable anyway.)
+ if (totalDistances[i] == 0.0f) {
+ return NS_ERROR_FAILURE;
+ }
+ remainingDists[i] = aSimpleProgress * totalDistances[i];
+ // Must be satisfied, because totalDistance is a sum of (non-negative)
+ // distances, and aSimpleProgress is non-negative
+ NS_ASSERTION(remainingDists[i] >= 0, "distance values must be non-negative");
+ }
// Find where remainingDist puts us in the list of values
// Note: We could optimize this next loop by caching the
// interval-distances in an array, but maybe that's excessive.
for (uint32_t i = 0; i < aValues.Length() - 1; i++) {
// Note: The following assertion is valid because remainingDist should
// start out non-negative, and this loop never shaves off more than its
// current value.
- NS_ASSERTION(remainingDist >= 0, "distance values must be non-negative");
+ for (size_t j = 0; j < len; j++) {
+ NS_ASSERTION(remainingDists[j] >= 0, "distance values must be non-negative");
+ }
AutoTArray<double, 1> curIntervalDists;
#ifdef DEBUG
nsresult rv =
#endif
aValues[i].ComputeDistance(aValues[i+1], curIntervalDists);
MOZ_ASSERT(NS_SUCCEEDED(rv),
- "If we got through ComputePacedTotalDistance, we should "
+ "If we got through ComputePacedTotalDistances, we should "
"be able to recompute each sub-distance without errors");
- NS_ASSERTION(curIntervalDists[0] >= 0,
- "distance values must be non-negative");
- // Clamp distance value at 0, just in case ComputeDistance is evil.
- curIntervalDists[0] = std::max(curIntervalDists[0], 0.0);
+ ClampDistances(curIntervalDists);
- if (remainingDist >= curIntervalDists[0]) {
- remainingDist -= curIntervalDists[0];
+ if (remainingDists[0] >= curIntervalDists[0]) {
+ remainingDists[0] -= curIntervalDists[0];
} else {
// NOTE: If we get here, then curIntervalDist necessarily is not 0. Why?
// Because this clause is only hit when remainingDist < curIntervalDist,
// and if curIntervalDist were 0, that would mean remainingDist would
// have to be < 0. But that can't happen, because remainingDist (as
// a distance) is non-negative by definition.
NS_ASSERTION(curIntervalDists[0] != 0,
"We should never get here with this set to 0...");
// We found the right spot -- an interpolated position between
// values i and i+1.
aFrom = &aValues[i];
aTo = &aValues[i+1];
- aIntervalProgress = remainingDist / curIntervalDists[0];
+ aIntervalProgress = remainingDists[0] / curIntervalDists[0];
return NS_OK;
}
}
NS_NOTREACHED("shouldn't complete loop & get here -- if we do, "
"then aSimpleProgress was probably out of bounds");
return NS_ERROR_FAILURE;
}
+static void
+AccumulateDistances(AutoTArray<double, 1>& aTotalDistances,
+ AutoTArray<double, 1>& aDistances)
+{
+ MOZ_ASSERT(aDistances.Length() == aTotalDistances.Length());
+
+ for (size_t i = 0; i < aDistances.Length(); i++) {
+ aTotalDistances[i] += aDistances[i];
+ }
+}
+
/*
* Computes the total distance to be travelled by a paced animation.
*
- * Returns the total distance, or returns COMPUTE_DISTANCE_ERROR if
- * our values don't support distance computation.
+ * Returns false if our values don't support distance computation.
*/
-double
-nsSMILAnimationFunction::ComputePacedTotalDistance(
- const nsSMILValueArray& aValues) const
+bool
+nsSMILAnimationFunction::ComputePacedTotalDistances(
+ const nsSMILValueArray& aValues,
+ AutoTArray<double, 1>& aTotalDistances) const
{
NS_ASSERTION(GetCalcMode() == CALC_PACED,
"Calling paced-specific function, but not in paced mode");
- double totalDistance = 0.0;
for (uint32_t i = 0; i < aValues.Length() - 1; i++) {
AutoTArray<double, 1> tmpDists;
nsresult rv = aValues[i].ComputeDistance(aValues[i+1], tmpDists);
if (NS_FAILED(rv)) {
- return COMPUTE_DISTANCE_ERROR;
+ return false;
}
// Clamp distance value to 0, just in case we have an evil ComputeDistance
// implementation somewhere
- MOZ_ASSERT(tmpDists[0] >= 0.0f, "distance values must be non-negative");
- tmpDists[0] = std::max(tmpDists[0], 0.0);
+ ClampDistances(tmpDists);
- totalDistance += tmpDists[0];
+ if (i == 0) {
+ size_t len = tmpDists.Length();
+ aTotalDistances.SetLength(len);
+ for (size_t j = 0; j < len; j++) {
+ aTotalDistances[i] = 0.0;
+ }
+ }
+ AccumulateDistances(aTotalDistances, tmpDists);
}
- return totalDistance;
+ return true;
}
double
nsSMILAnimationFunction::ScaleSimpleProgress(double aProgress,
nsSMILCalcMode aCalcMode)
{
if (!HasAttr(nsGkAtoms::keyTimes))
return aProgress;
--- a/dom/smil/nsSMILAnimationFunction.h
+++ b/dom/smil/nsSMILAnimationFunction.h
@@ -308,17 +308,18 @@ protected:
nsresult AccumulateResult(const nsSMILValueArray& aValues,
nsSMILValue& aResult);
nsresult ComputePacedPosition(const nsSMILValueArray& aValues,
double aSimpleProgress,
double& aIntervalProgress,
const nsSMILValue*& aFrom,
const nsSMILValue*& aTo);
- double ComputePacedTotalDistance(const nsSMILValueArray& aValues) const;
+ bool ComputePacedTotalDistances(const nsSMILValueArray& aValues,
+ AutoTArray<double, 1>& aTotalDistances) const;
/**
* Adjust the simple progress, that is, the point within the simple duration,
* by applying any keyTimes.
*/
double ScaleSimpleProgress(double aProgress, nsSMILCalcMode aCalcMode);
/**
* Adjust the progress within an interval, that is, between two animation