예제 #1
0
PRInt8
nsSMILAnimationFunction::CompareTo(const nsSMILAnimationFunction* aOther) const
{
  NS_ENSURE_TRUE(aOther, 0);

  NS_ASSERTION(aOther != this, "Trying to compare to self");

  // Inactive animations sort first
  if (!IsActiveOrFrozen() && aOther->IsActiveOrFrozen())
    return -1;

  if (IsActiveOrFrozen() && !aOther->IsActiveOrFrozen())
    return 1;

  // Sort based on begin time
  if (mBeginTime != aOther->GetBeginTime())
    return mBeginTime > aOther->GetBeginTime() ? 1 : -1;

  // Next sort based on syncbase dependencies: the dependent element sorts after
  // its syncbase
  const nsSMILTimedElement& thisTimedElement =
    mAnimationElement->TimedElement();
  const nsSMILTimedElement& otherTimedElement =
    aOther->mAnimationElement->TimedElement();
  if (thisTimedElement.IsTimeDependent(otherTimedElement))
    return 1;
  if (otherTimedElement.IsTimeDependent(thisTimedElement))
    return -1;

  // Animations that appear later in the document sort after those earlier in
  // the document
  nsIContent& thisContent = mAnimationElement->AsElement();
  nsIContent& otherContent = aOther->mAnimationElement->AsElement();

  NS_ABORT_IF_FALSE(&thisContent != &otherContent,
      "Two animations cannot have the same animation content element!");

  return (nsContentUtils::PositionIsBefore(&thisContent, &otherContent))
          ? -1 : 1;
}
예제 #2
0
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.
    }
}