void nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult) { mHasChanged = PR_FALSE; // Skip animations that are inactive or in error if (!IsActiveOrFrozen() || mErrorFlags != 0) return; // Get the animation values nsSMILValueArray values; nsresult rv = GetValues(aSMILAttr, values); if (NS_FAILED(rv)) return; // Check that we have the right number of keySplines and keyTimes CheckValueListDependentAttrs(values.Length()); if (mErrorFlags != 0) return; // If this interval is active, we must have a non-negative mSampleTime NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive, "Negative sample time for active animation"); NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mSimpleDuration.IsIndefinite() || mLastValue, "Unresolved simple duration for active or frozen animation"); nsSMILValue result(aResult.mType); if (mSimpleDuration.IsIndefinite() || (values.Length() == 1 && TreatSingleValueAsStatic())) { // Indefinite duration or only one value set: Always set the first value result = values[0]; } else if (mLastValue) { // Sampling last value const nsSMILValue& last = values[values.Length() - 1]; result = last; // See comment in AccumulateResult: to-animation does not accumulate if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) { // If the target attribute type doesn't support addition Add will // fail leaving result = last result.Add(last, mRepeatIteration); } } else if (!mFrozenValue.IsNull() && !mHasChanged) { // Frozen to animation result = mFrozenValue; } else { // Interpolation if (NS_FAILED(InterpolateResult(values, result, aResult))) return; if (NS_FAILED(AccumulateResult(values, result))) return; if (IsToAnimation() && mIsFrozen) { mFrozenValue = result; } } // If additive animation isn't required or isn't supported, set the value. if (!IsAdditive() || NS_FAILED(aResult.SandwichAdd(result))) { aResult.Swap(result); // Note: The old value of aResult is now in |result|, and it will get // cleaned up when |result| goes out of scope, when this function returns. } }
void nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult) { mHasChanged = false; mPrevSampleWasSingleValueAnimation = false; mWasSkippedInPrevSample = false; // Skip animations that are inactive or in error if (!IsActiveOrFrozen() || mErrorFlags != 0) return; // Get the animation values nsSMILValueArray values; nsresult rv = GetValues(aSMILAttr, values); if (NS_FAILED(rv)) return; // Check that we have the right number of keySplines and keyTimes CheckValueListDependentAttrs(values.Length()); if (mErrorFlags != 0) return; // If this interval is active, we must have a non-negative mSampleTime NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive, "Negative sample time for active animation"); NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mLastValue, "Unresolved simple duration for active or frozen animation"); // If we want to add but don't have a base value then just fail outright. // This can happen when we skipped getting the base value because there's an // animation function in the sandwich that should replace it but that function // failed unexpectedly. bool isAdditive = IsAdditive(); if (isAdditive && aResult.IsNull()) return; nsSMILValue result; if (values.Length() == 1 && !IsToAnimation()) { // Single-valued animation result = values[0]; mPrevSampleWasSingleValueAnimation = true; } else if (mLastValue) { // Sampling last value const nsSMILValue& last = values[values.Length() - 1]; result = last; // See comment in AccumulateResult: to-animation does not accumulate if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) { // If the target attribute type doesn't support addition Add will // fail leaving result = last result.Add(last, mRepeatIteration); } } else { // Interpolation if (NS_FAILED(InterpolateResult(values, result, aResult))) return; if (NS_FAILED(AccumulateResult(values, result))) return; } // If additive animation isn't required or isn't supported, set the value. if (!isAdditive || NS_FAILED(aResult.SandwichAdd(result))) { aResult.Swap(result); // Note: The old value of aResult is now in |result|, and it will get // cleaned up when |result| goes out of scope, when this function returns. } }