#ifndef CC_ANIMATION_KEYFRAME_EFFECT_H_
#define CC_ANIMATION_KEYFRAME_EFFECT_H_
#include <limits>
#include <memory>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "cc/animation/animation_events.h"
#include "cc/animation/animation_export.h"
#include "cc/animation/element_animations.h"
#include "cc/animation/keyframe_model.h"
#include "cc/paint/element_id.h"
#include "cc/trees/mutator_host_client.h"
#include "cc/trees/target_property.h"
#include "ui/gfx/animation/keyframe/keyframe_effect.h"
#include "ui/gfx/geometry/point_f.h"
namespace cc {
class Animation;
enum class PauseCondition { kUnconditional, kAfterStart };
struct PropertyAnimationState;
inline constexpr ElementId kReservedElementIdForPaintWorklet(
std::numeric_limits<ElementId::InternalValue>::max() - 1);
class CC_ANIMATION_EXPORT KeyframeEffect : public gfx::KeyframeEffect {
public:
explicit KeyframeEffect(Animation* animation);
KeyframeEffect(const KeyframeEffect&) = delete;
virtual ~KeyframeEffect();
KeyframeEffect& operator=(const KeyframeEffect&) = delete;
scoped_refptr<const ElementAnimations> element_animations() const {
return element_animations_;
}
bool has_bound_element_animations() const { return !!element_animations_; }
bool has_attached_element() const { return !!element_id_; }
ElementId element_id() const { return element_id_; }
bool has_any_keyframe_model() const { return !keyframe_models().empty(); }
bool scroll_offset_animation_was_interrupted() const {
return scroll_offset_animation_was_interrupted_;
}
bool needs_push_properties() const { return needs_push_properties_; }
void SetNeedsPushProperties();
void ResetNeedsPushProperties();
void BindElementAnimations(ElementAnimations* element_animations);
void UnbindElementAnimations();
void AttachElement(ElementId element_id);
void DetachElement();
bool Tick(base::TimeTicks monotonic_time) override;
void RemoveFromTicking();
void UpdateState(bool start_ready_keyframe_models, AnimationEvents* events);
void UpdateTickingState();
void Pause(base::TimeTicks timeline_time,
PauseCondition = PauseCondition::kUnconditional);
void AddKeyframeModel(
std::unique_ptr<gfx::KeyframeModel> keyframe_model) override;
void PauseKeyframeModel(int keyframe_model_id, base::TimeDelta time_offset);
void AbortKeyframeModel(int keyframe_model_id);
void AbortKeyframeModelsWithProperty(TargetProperty::Type target_property,
bool needs_completion);
void ActivateKeyframeModels();
void KeyframeModelAdded();
bool DispatchAnimationEventToKeyframeModel(const AnimationEvent& event);
bool HasTickingKeyframeModel() const;
bool RequiresInvalidation() const;
bool AffectsNativeProperty() const;
bool AnimationsPreserveAxisAlignment() const;
float MaximumScale(ElementId, ElementListType) const;
bool IsPotentiallyAnimatingProperty(TargetProperty::Type target_property,
ElementListType list_type) const;
bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property,
ElementListType list_type) const;
void GetPropertyAnimationState(PropertyAnimationState* pending_state,
PropertyAnimationState* active_state) const;
void MarkAbortedKeyframeModelsForDeletion(
KeyframeEffect* element_keyframe_effect_impl);
void PurgeKeyframeModelsMarkedForDeletion(bool impl_only);
void PushNewKeyframeModelsToImplThread(
KeyframeEffect* element_keyframe_effect_impl) const;
void RemoveKeyframeModelsCompletedOnMainThread(
KeyframeEffect* element_keyframe_effect_impl) const;
void PushPropertiesTo(KeyframeEffect* keyframe_effect_impl,
std::optional<base::TimeTicks> replaced_start_time);
std::string KeyframeModelsToString() const;
base::TimeDelta MinimumTickInterval() const;
bool awaiting_deletion() { return awaiting_deletion_; }
void set_replaced_group(int replaced_group) {
replaced_group_ = replaced_group;
}
protected:
void RemoveKeyframeModelRange(
typename KeyframeModels::iterator to_remove_begin,
typename KeyframeModels::iterator to_remove_end) override;
private:
void StartKeyframeModels(base::TimeTicks monotonic_time);
void PromoteStartedKeyframeModels(AnimationEvents* events);
void PurgeDeletedKeyframeModels();
void MarkKeyframeModelsForDeletion(base::TimeTicks, AnimationEvents* events);
void MarkFinishedKeyframeModels(base::TimeTicks monotonic_time);
std::optional<gfx::PointF> ScrollOffsetForAnimation() const;
void GenerateEvent(AnimationEvents* events,
const KeyframeModel& keyframe_model,
AnimationEvent::Type type,
base::TimeTicks monotonic_time);
void GenerateTakeoverEventForScrollAnimation(
AnimationEvents* events,
const KeyframeModel& keyframe_model,
base::TimeTicks monotonic_time);
raw_ptr<Animation> animation_;
ElementId element_id_;
scoped_refptr<ElementAnimations> element_animations_;
std::optional<int> replaced_group_;
bool needs_to_start_keyframe_models_;
bool scroll_offset_animation_was_interrupted_;
bool is_ticking_;
bool awaiting_deletion_;
std::optional<base::TimeTicks> last_tick_time_;
bool needs_push_properties_;
};
}
#endif