Bug 1564128 part 1 - Add clone function for Animation and constructor for KeyframeEffect to copy properties but not the target. r=hiro

This is needed for copying animations from an original document to a static
clone during printing/print preview.

Differential Revision: https://phabricator.services.mozilla.com/D73139
This commit is contained in:
Emily McDonough
2020-05-14 19:41:01 +00:00
parent e971984db0
commit a6dea63c4c
4 changed files with 61 additions and 16 deletions

View File

@@ -83,6 +83,37 @@ class MOZ_RAII AutoMutationBatchForAnimation {
//
// ---------------------------------------------------------------------------
/* static */
already_AddRefed<Animation> Animation::ClonePausedAnimation(
nsIGlobalObject* aGlobal, const Animation& aOther, AnimationEffect& aEffect,
AnimationTimeline& aTimeline) {
RefPtr<Animation> animation = new Animation(aGlobal);
// Setup the timing.
animation->mTimeline = &aTimeline;
const Nullable<TimeDuration> timelineTime =
aTimeline.GetCurrentTimeAsDuration();
MOZ_ASSERT(!timelineTime.IsNull(), "Timeline not yet set");
const Nullable<TimeDuration> currentTime = aOther.GetCurrentTimeAsDuration();
animation->mHoldTime = currentTime;
if (!currentTime.IsNull()) {
animation->mPreviousCurrentTime = timelineTime;
}
animation->mPlaybackRate = aOther.mPlaybackRate;
// Setup the effect's link to this.
animation->mEffect = &aEffect;
animation->mEffect->SetAnimation(animation);
// We expect our relevance to be the same as the orginal.
animation->mIsRelevant = aOther.mIsRelevant;
animation->PostUpdate();
animation->mTimeline->NotifyAnimationUpdated(*animation);
return animation.forget();
}
NonOwningAnimationTarget Animation::GetTargetForAnimation() const {
AnimationEffect* effect = GetEffect();
NonOwningAnimationTarget target;

View File

@@ -50,6 +50,14 @@ class Animation : public DOMEventTargetHelper,
explicit Animation(nsIGlobalObject* aGlobal)
: DOMEventTargetHelper(aGlobal), mAnimationIndex(sNextAnimationIndex++) {}
// Constructs a copy of |aOther| with a new effect and timeline.
// This is only intended to be used while making a static clone of a document
// during printing, and does not assume that |aOther| is in the same document
// as any of the other arguments.
static already_AddRefed<Animation> ClonePausedAnimation(
nsIGlobalObject* aGlobal, const Animation& aOther,
AnimationEffect& aEffect, AnimationTimeline& aTimeline);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Animation, DOMEventTargetHelper)

View File

@@ -90,8 +90,22 @@ KeyframeEffect::KeyframeEffect(Document* aDocument,
const KeyframeEffectParams& aOptions)
: AnimationEffect(aDocument, std::move(aTiming)),
mTarget(std::move(aTarget)),
mEffectOptions(aOptions),
mCumulativeChangeHint(nsChangeHint(0)) {}
mEffectOptions(aOptions) {}
KeyframeEffect::KeyframeEffect(Document* aDocument,
OwningAnimationTarget&& aTarget,
const KeyframeEffect& aOther)
: AnimationEffect(aDocument, TimingParams{aOther.SpecifiedTiming()}),
mTarget(std::move(aTarget)),
mEffectOptions{aOther.IterationComposite(), aOther.Composite(),
mTarget.mPseudoType},
mKeyframes(aOther.mKeyframes.Clone()),
mProperties(aOther.mProperties.Clone()),
mBaseValues(aOther.mBaseValues.Count()) {
for (auto iter = aOther.mBaseValues.ConstIter(); !iter.Done(); iter.Next()) {
mBaseValues.Put(iter.Key(), RefPtr{iter.Data()});
}
}
JSObject* KeyframeEffect::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@@ -1033,23 +1047,12 @@ already_AddRefed<KeyframeEffect> KeyframeEffect::Constructor(
// aSource's TimingParams.
// Note: we don't need to re-throw exceptions since the value specified on
// aSource's timing object can be assumed valid.
RefPtr<KeyframeEffect> effect = new KeyframeEffect(
doc, OwningAnimationTarget(aSource.mTarget),
TimingParams(aSource.SpecifiedTiming()), aSource.mEffectOptions);
RefPtr<KeyframeEffect> effect =
new KeyframeEffect(doc, OwningAnimationTarget{aSource.mTarget}, aSource);
// Copy cumulative change hint. mCumulativeChangeHint should be the same as
// the source one because both of targets are the same.
effect->mCumulativeChangeHint = aSource.mCumulativeChangeHint;
// Copy aSource's keyframes and animation properties.
// Note: We don't call SetKeyframes directly, which might revise the
// computed offsets and rebuild the animation properties.
effect->mKeyframes = aSource.mKeyframes.Clone();
effect->mProperties = aSource.mProperties.Clone();
for (auto iter = aSource.mBaseValues.ConstIter(); !iter.Done(); iter.Next()) {
// XXX Should this use non-const Iter() and then pass
// std::move(iter.Data())? Otherwise aSource might be a const&...
effect->mBaseValues.Put(iter.Key(), RefPtr{iter.Data()});
}
return effect.forget();
}

View File

@@ -111,6 +111,9 @@ class KeyframeEffect : public AnimationEffect {
KeyframeEffect(Document* aDocument, OwningAnimationTarget&& aTarget,
TimingParams&& aTiming, const KeyframeEffectParams& aOptions);
KeyframeEffect(Document* aDocument, OwningAnimationTarget&& aTarget,
const KeyframeEffect& aOther);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffect,
AnimationEffect)
@@ -454,7 +457,7 @@ class KeyframeEffect : public AnimationEffect {
BaseValuesHashmap mBaseValues;
private:
nsChangeHint mCumulativeChangeHint;
nsChangeHint mCumulativeChangeHint = nsChangeHint{0};
void ComposeStyleRule(RawServoAnimationValueMap& aAnimationValues,
const AnimationProperty& aProperty,