blob: 2bc75e6aee32e253098bff0626b47e4dcfe0deb4 [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.
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATIONS_H_
#include "base/macros.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_update.h"
#include "third_party/blink/renderer/core/animation/css/css_transition_data.h"
#include "third_party/blink/renderer/core/animation/inert_effect.h"
#include "third_party/blink/renderer/core/animation/interpolation.h"
#include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
class CSSTransitionData;
class Element;
class StylePropertyShorthand;
class StyleResolver;
class CORE_EXPORT CSSAnimations final {
DISALLOW_NEW();
public:
CSSAnimations();
static const StylePropertyShorthand& PropertiesForTransitionAll();
static bool IsAnimationAffectingProperty(const CSSProperty&);
static bool IsAffectedByKeyframesFromScope(const Element&, const TreeScope&);
static bool IsAnimatingCustomProperties(const ElementAnimations*);
static bool IsAnimatingStandardProperties(const ElementAnimations*,
const CSSBitset*,
KeyframeEffect::Priority);
static bool IsAnimatingFontAffectingProperties(const ElementAnimations*);
static bool IsAnimatingRevert(const ElementAnimations*);
static void CalculateAnimationUpdate(CSSAnimationUpdate&,
const Element* animating_element,
Element&,
const ComputedStyle&,
const ComputedStyle* parent_style,
StyleResolver*);
static void CalculateCompositorAnimationUpdate(
CSSAnimationUpdate&,
const Element* animating_element,
Element&,
const ComputedStyle&,
const ComputedStyle* parent_style,
bool was_viewport_changed);
static AnimationEffect::EventDelegate* CreateEventDelegate(
Element* element,
const PropertyHandle& property_handle,
const AnimationEffect::EventDelegate* old_event_delegate);
static AnimationEffect::EventDelegate* CreateEventDelegate(
Element* element,
const AtomicString& animation_name,
const AnimationEffect::EventDelegate* old_event_delegate);
// Specifies whether to process custom or standard CSS properties.
enum class PropertyPass { kCustom, kStandard };
static void CalculateTransitionUpdate(CSSAnimationUpdate&,
PropertyPass,
Element* animating_element,
const ComputedStyle&);
static void SnapshotCompositorKeyframes(Element&,
CSSAnimationUpdate&,
const ComputedStyle&,
const ComputedStyle* parent_style);
void SetPendingUpdate(const CSSAnimationUpdate& update) {
ClearPendingUpdate();
pending_update_.Copy(update);
}
void ClearPendingUpdate() { pending_update_.Clear(); }
void MaybeApplyPendingUpdate(Element*);
bool IsEmpty() const {
return running_animations_.IsEmpty() && transitions_.IsEmpty() &&
pending_update_.IsEmpty();
}
void Cancel();
void Trace(Visitor*) const;
private:
class RunningAnimation final : public GarbageCollected<RunningAnimation> {
public:
RunningAnimation(Animation* animation, NewCSSAnimation new_animation)
: animation(animation),
name(new_animation.name),
name_index(new_animation.name_index),
specified_timing(new_animation.timing),
style_rule(new_animation.style_rule),
style_rule_version(new_animation.style_rule_version),
play_state_list(new_animation.play_state_list) {}
AnimationTimeline* Timeline() const { return animation->timeline(); }
void Update(UpdatedCSSAnimation update) {
DCHECK_EQ(update.animation, animation);
style_rule = update.style_rule;
style_rule_version = update.style_rule_version;
play_state_list = update.play_state_list;
specified_timing = update.specified_timing;
}
void Trace(Visitor* visitor) const {
visitor->Trace(animation);
visitor->Trace(style_rule);
}
Member<Animation> animation;
AtomicString name;
size_t name_index;
Timing specified_timing;
Member<StyleRuleKeyframes> style_rule;
unsigned style_rule_version;
Vector<EAnimPlayState> play_state_list;
};
struct RunningTransition : public GarbageCollected<RunningTransition> {
public:
virtual ~RunningTransition() = default;
void Trace(Visitor* visitor) const { visitor->Trace(animation); }
Member<Animation> animation;
scoped_refptr<const ComputedStyle> from;
scoped_refptr<const ComputedStyle> to;
scoped_refptr<const ComputedStyle> reversing_adjusted_start_value;
double reversing_shortening_factor;
};
HeapVector<Member<RunningAnimation>> running_animations_;
using TransitionMap = HeapHashMap<PropertyHandle, Member<RunningTransition>>;
TransitionMap transitions_;
CSSAnimationUpdate pending_update_;
ActiveInterpolationsMap previous_active_interpolations_for_custom_animations_;
ActiveInterpolationsMap
previous_active_interpolations_for_standard_animations_;
struct TransitionUpdateState {
STACK_ALLOCATED();
public:
CSSAnimationUpdate& update;
Element* animating_element = nullptr;
const ComputedStyle& old_style;
const ComputedStyle& style;
scoped_refptr<const ComputedStyle> before_change_style;
scoped_refptr<const ComputedStyle> cloned_style;
const TransitionMap* active_transitions;
HashSet<PropertyHandle>& listed_properties;
const CSSTransitionData* transition_data;
};
static void CalculateTransitionUpdateForCustomProperty(
TransitionUpdateState&,
const CSSTransitionData::TransitionProperty&,
size_t transition_index);
static void CalculateTransitionUpdateForStandardProperty(
TransitionUpdateState&,
const CSSTransitionData::TransitionProperty&,
size_t transition_index,
const ComputedStyle&);
static void CalculateTransitionUpdateForProperty(TransitionUpdateState&,
const PropertyHandle&,
size_t transition_index);
static void CalculateAnimationActiveInterpolations(
CSSAnimationUpdate&,
const Element* animating_element);
static void CalculateTransitionActiveInterpolations(
CSSAnimationUpdate&,
PropertyPass,
const Element* animating_element);
// The before-change style is defined as the computed values of all properties
// on the element as of the previous style change event, except with any
// styles derived from declarative animations updated to the current time.
// https://drafts.csswg.org/css-transitions-1/#before-change-style
static scoped_refptr<const ComputedStyle> CalculateBeforeChangeStyle(
Element* animating_element,
const ComputedStyle& base_style);
class AnimationEventDelegate final : public AnimationEffect::EventDelegate {
public:
AnimationEventDelegate(
Element* animation_target,
const AtomicString& name,
Timing::Phase previous_phase = Timing::kPhaseNone,
base::Optional<double> previous_iteration = base::nullopt)
: animation_target_(animation_target),
name_(name),
previous_phase_(previous_phase),
previous_iteration_(previous_iteration) {}
bool RequiresIterationEvents(const AnimationEffect&) override;
void OnEventCondition(const AnimationEffect&, Timing::Phase) override;
bool IsAnimationEventDelegate() const override { return true; }
Timing::Phase getPreviousPhase() const { return previous_phase_; }
base::Optional<double> getPreviousIteration() const {
return previous_iteration_;
}
void Trace(Visitor*) const override;
private:
const Element& AnimationTarget() const { return *animation_target_; }
EventTarget* GetEventTarget() const;
Document& GetDocument() const { return animation_target_->GetDocument(); }
void MaybeDispatch(Document::ListenerType,
const AtomicString& event_name,
const AnimationTimeDelta& elapsed_time);
Member<Element> animation_target_;
const AtomicString name_;
Timing::Phase previous_phase_;
base::Optional<double> previous_iteration_;
};
class TransitionEventDelegate final : public AnimationEffect::EventDelegate {
public:
TransitionEventDelegate(Element* transition_target,
const PropertyHandle& property,
Timing::Phase previous_phase = Timing::kPhaseNone)
: transition_target_(transition_target),
property_(property),
previous_phase_(previous_phase) {}
bool RequiresIterationEvents(const AnimationEffect&) override {
return false;
}
void OnEventCondition(const AnimationEffect&, Timing::Phase) override;
bool IsTransitionEventDelegate() const override { return true; }
Timing::Phase getPreviousPhase() const { return previous_phase_; }
void Trace(Visitor*) const override;
private:
void EnqueueEvent(const WTF::AtomicString& type,
const AnimationTimeDelta& elapsed_time);
const Element& TransitionTarget() const { return *transition_target_; }
EventTarget* GetEventTarget() const;
PseudoId GetPseudoId() const { return transition_target_->GetPseudoId(); }
Document& GetDocument() const { return transition_target_->GetDocument(); }
Member<Element> transition_target_;
PropertyHandle property_;
Timing::Phase previous_phase_;
};
DISALLOW_COPY_AND_ASSIGN(CSSAnimations);
};
template <>
struct DowncastTraits<CSSAnimations::AnimationEventDelegate> {
static bool AllowFrom(const AnimationEffect::EventDelegate& delegate) {
return delegate.IsAnimationEventDelegate();
}
};
template <>
struct DowncastTraits<CSSAnimations::TransitionEventDelegate> {
static bool AllowFrom(const AnimationEffect::EventDelegate& delegate) {
return delegate.IsTransitionEventDelegate();
}
};
} // namespace blink
#endif