blob: 1f75362599af9cf2cd74e9677fa20884834f753f [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/core/animation/animation_effect.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
#include "third_party/blink/renderer/core/animation/computed_effect_timing.h"
#include "third_party/blink/renderer/core/animation/optional_effect_timing.h"
#include "third_party/blink/renderer/core/animation/timing_calculations.h"
#include "third_party/blink/renderer/core/animation/timing_input.h"
namespace blink {
AnimationEffect::AnimationEffect(const Timing& timing,
EventDelegate* event_delegate)
: owner_(nullptr),
timing_(timing),
event_delegate_(event_delegate),
calculated_(),
needs_update_(true),
last_update_time_(NullValue()) {
timing_.AssertValid();
}
void AnimationEffect::UpdateSpecifiedTiming(const Timing& timing) {
// FIXME: Test whether the timing is actually different?
timing_ = timing;
InvalidateAndNotifyOwner();
}
EffectTiming* AnimationEffect::getTiming() const {
return SpecifiedTiming().ConvertToEffectTiming();
}
ComputedEffectTiming* AnimationEffect::getComputedTiming() const {
return SpecifiedTiming().getComputedTiming(EnsureCalculated(),
IsKeyframeEffect());
}
void AnimationEffect::updateTiming(OptionalEffectTiming* optional_timing,
ExceptionState& exception_state) {
// TODO(crbug.com/827178): Determine whether we should pass a Document in here
// (and which) to resolve the CSS secure/insecure context against.
if (!TimingInput::Update(timing_, optional_timing, nullptr, exception_state))
return;
InvalidateAndNotifyOwner();
}
void AnimationEffect::UpdateInheritedTime(double inherited_time,
TimingUpdateReason reason) const {
base::Optional<double> playback_rate = base::nullopt;
if (GetAnimation())
playback_rate = GetAnimation()->playbackRate();
const Timing::AnimationDirection direction =
(playback_rate && playback_rate.value() < 0)
? Timing::AnimationDirection::kBackwards
: Timing::AnimationDirection::kForwards;
bool needs_update =
needs_update_ ||
(last_update_time_ != inherited_time &&
!(IsNull(last_update_time_) && IsNull(inherited_time))) ||
(owner_ && owner_->EffectSuppressed());
needs_update_ = false;
last_update_time_ = inherited_time;
const double local_time = inherited_time;
if (needs_update) {
Timing::CalculatedTiming calculated = SpecifiedTiming().CalculateTimings(
local_time, direction, IsKeyframeEffect(), playback_rate);
const bool was_canceled = calculated.phase != calculated_.phase &&
calculated.phase == Timing::kPhaseNone;
// If the animation was canceled, we need to fire the event condition before
// updating the calculated timing so that the cancellation time can be
// determined.
if (was_canceled && event_delegate_) {
event_delegate_->OnEventCondition(*this, calculated.phase);
}
calculated_ = calculated;
}
// Test for events even if timing didn't need an update as the animation may
// have gained a start time.
// FIXME: Refactor so that we can DCHECK(owner_) here, this is currently
// required to be nullable for testing.
if (reason == kTimingUpdateForAnimationFrame &&
(!owner_ || owner_->IsEventDispatchAllowed())) {
if (event_delegate_)
event_delegate_->OnEventCondition(*this, calculated_.phase);
}
if (needs_update) {
// FIXME: This probably shouldn't be recursive.
UpdateChildrenAndEffects();
calculated_.time_to_forwards_effect_change = CalculateTimeToEffectChange(
true, local_time, calculated_.time_to_next_iteration);
calculated_.time_to_reverse_effect_change = CalculateTimeToEffectChange(
false, local_time, calculated_.time_to_next_iteration);
}
}
void AnimationEffect::InvalidateAndNotifyOwner() const {
Invalidate();
if (owner_)
owner_->EffectInvalidated();
}
const Timing::CalculatedTiming& AnimationEffect::EnsureCalculated() const {
if (owner_)
owner_->UpdateIfNecessary();
return calculated_;
}
Animation* AnimationEffect::GetAnimation() {
return owner_ ? owner_->GetAnimation() : nullptr;
}
const Animation* AnimationEffect::GetAnimation() const {
return owner_ ? owner_->GetAnimation() : nullptr;
}
void AnimationEffect::Trace(blink::Visitor* visitor) {
visitor->Trace(owner_);
visitor->Trace(event_delegate_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink