示例#1
0
void
KeyframeEffect::SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget)
{
  Maybe<OwningAnimationTarget> newTarget = ConvertTarget(aTarget);
  if (mTarget == newTarget) {
    // Assign the same target, skip it.
    return;
  }

  if (mTarget) {
    UnregisterTarget();
    ResetIsRunningOnCompositor();
    // We don't need to reset the mWinsInCascade member since it will be updated
    // when we later associate with a different target (and until that time this
    // flag is not used).

    RequestRestyle(EffectCompositor::RestyleType::Layer);

    nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc());
    if (mAnimation) {
      nsNodeUtils::AnimationRemoved(mAnimation);
    }
  }

  mTarget = newTarget;

  if (mTarget) {
    UpdateTargetRegistration();
    RefPtr<nsStyleContext> styleContext = GetTargetStyleContext();
    if (styleContext) {
      UpdateProperties(styleContext);
    } else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
      KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
    }

    MaybeUpdateFrameForCompositor();

    RequestRestyle(EffectCompositor::RestyleType::Layer);

    nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc());
    if (mAnimation) {
      nsNodeUtils::AnimationAdded(mAnimation);
    }
  } else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
    // New target is null, so fall back to distribute spacing.
    KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
  }
}
示例#2
0
void
KeyframeEffect::NotifySpecifiedTimingUpdated()
{
  // Use the same document for a pseudo element and its parent element.
  // Use nullptr if we don't have mTarget, so disable the mutation batch.
  nsAutoAnimationMutationBatch mb(mTarget ? mTarget->mElement->OwnerDoc()
                                          : nullptr);

  if (mAnimation) {
    mAnimation->NotifyEffectTimingUpdated();

    if (mAnimation->IsRelevant()) {
      nsNodeUtils::AnimationChanged(mAnimation);
    }

    RequestRestyle(EffectCompositor::RestyleType::Layer);
  }
}
void
KeyframeEffectReadOnly::SetAnimation(Animation* aAnimation)
{
  if (mAnimation == aAnimation) {
    return;
  }

  // Restyle for the old animation.
  RequestRestyle(EffectCompositor::RestyleType::Layer);

  mAnimation = aAnimation;

  // The order of these function calls is important:
  // NotifyAnimationTimingUpdated() need the updated mIsRelevant flag to check
  // if it should create the effectSet or not, and MarkCascadeNeedsUpdate()
  // needs a valid effectSet, so we should call them in this order.
  if (mAnimation) {
    mAnimation->UpdateRelevance();
  }
  NotifyAnimationTimingUpdated();
  if (mAnimation) {
    MarkCascadeNeedsUpdate();
  }
}
void
KeyframeEffectReadOnly::UpdateProperties(nsStyleContext* aStyleContext)
{
  MOZ_ASSERT(aStyleContext);

  nsTArray<AnimationProperty> properties = BuildProperties(aStyleContext);

  if (mProperties == properties) {
    return;
  }

  // Preserve the state of the mIsRunningOnCompositor flag.
  nsCSSPropertyIDSet runningOnCompositorProperties;

  for (const AnimationProperty& property : mProperties) {
    if (property.mIsRunningOnCompositor) {
      runningOnCompositorProperties.AddProperty(property.mProperty);
    }
  }

  mProperties = Move(properties);

  for (AnimationProperty& property : mProperties) {
    property.mIsRunningOnCompositor =
      runningOnCompositorProperties.HasProperty(property.mProperty);
  }

  // FIXME (bug 1303235): Do this for Servo too
  if (aStyleContext->PresContext()->StyleSet()->IsGecko()) {
    CalculateCumulativeChangeHint(aStyleContext);
  }

  MarkCascadeNeedsUpdate();

  RequestRestyle(EffectCompositor::RestyleType::Layer);
}
void
KeyframeEffectReadOnly::UpdateProperties(nsStyleContext* aStyleContext)
{
  MOZ_ASSERT(aStyleContext);

  nsTArray<AnimationProperty> properties;
  if (mTarget) {
    // When GetComputedKeyframeValues or GetAnimationPropertiesFromKeyframes
    // calculate computed values from |mKeyframes|, they could possibly
    // trigger a subsequent restyle in which we rebuild animations. If that
    // happens we could find that |mKeyframes| is overwritten while it is
    // being iterated over. Normally that shouldn't happen but just in case we
    // make a copy of |mKeyframes| first and iterate over that instead.
    auto keyframesCopy(mKeyframes);

    nsTArray<ComputedKeyframeValues> computedValues =
      KeyframeUtils::GetComputedKeyframeValues(keyframesCopy,
                                               mTarget->mElement,
                                               aStyleContext);

    if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
      KeyframeUtils::ApplySpacing(keyframesCopy, SpacingMode::paced,
                                  mEffectOptions.mPacedProperty,
                                  computedValues);
    }

    properties =
      KeyframeUtils::GetAnimationPropertiesFromKeyframes(keyframesCopy,
                                                         computedValues,
                                                         aStyleContext);

#ifdef DEBUG
    MOZ_ASSERT(SpecifiedKeyframeArraysAreEqual(mKeyframes, keyframesCopy),
               "Apart from the computed offset members, the keyframes array"
               " should not be modified");
#endif

    mKeyframes.SwapElements(keyframesCopy);
  }

  if (mProperties == properties) {
    return;
  }

  // Preserve the state of mWinsInCascade and mIsRunningOnCompositor flags.
  nsCSSPropertyIDSet winningInCascadeProperties;
  nsCSSPropertyIDSet runningOnCompositorProperties;

  for (const AnimationProperty& property : mProperties) {
    if (property.mWinsInCascade) {
      winningInCascadeProperties.AddProperty(property.mProperty);
    }
    if (property.mIsRunningOnCompositor) {
      runningOnCompositorProperties.AddProperty(property.mProperty);
    }
  }

  mProperties = Move(properties);

  for (AnimationProperty& property : mProperties) {
    property.mWinsInCascade =
      winningInCascadeProperties.HasProperty(property.mProperty);
    property.mIsRunningOnCompositor =
      runningOnCompositorProperties.HasProperty(property.mProperty);
  }

  CalculateCumulativeChangeHint(aStyleContext);

  MarkCascadeNeedsUpdate();

  RequestRestyle(EffectCompositor::RestyleType::Layer);
}