/* * Copyright (c) 2023, Matthew Olsson . * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include namespace Web::Animations { // https://www.w3.org/TR/web-animations-1/#the-animation-interface class Animation : public DOM::EventTarget { WEB_PLATFORM_OBJECT(Animation, DOM::EventTarget); JS_DECLARE_ALLOCATOR(Animation); public: static JS::NonnullGCPtr create(JS::Realm&, JS::GCPtr, JS::GCPtr); static WebIDL::ExceptionOr> construct_impl(JS::Realm&, JS::GCPtr, JS::GCPtr); FlyString const& id() const { return m_id; } void set_id(FlyString value) { m_id = move(value); } JS::GCPtr effect() const { return m_effect; } void set_effect(JS::GCPtr); JS::GCPtr timeline() const { return m_timeline; } void set_timeline(JS::GCPtr); Optional const& start_time() const { return m_start_time; } void set_start_time(Optional const&); Optional current_time() const; WebIDL::ExceptionOr set_current_time(Optional const&); double playback_rate() const { return m_playback_rate; } WebIDL::ExceptionOr set_playback_rate(double value); Bindings::AnimationPlayState play_state() const; Bindings::AnimationReplaceState replace_state() const { return m_replace_state; } // https://www.w3.org/TR/web-animations-1/#dom-animation-pending bool pending() const { return m_pending_pause_task != TaskState::None || m_pending_play_task != TaskState::None; } // https://www.w3.org/TR/web-animations-1/#dom-animation-ready JS::NonnullGCPtr ready() const { return *current_ready_promise()->promise(); } // https://www.w3.org/TR/web-animations-1/#dom-animation-finished JS::NonnullGCPtr finished() const { return *current_finished_promise()->promise(); } Optional convert_an_animation_time_to_timeline_time(Optional) const; Optional convert_a_timeline_time_to_an_origin_relative_time(Optional) const; JS::GCPtr document_for_timing() const; protected: Animation(JS::Realm&); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; private: enum class TaskState { None, Pending, RunAsSoonAsReady, }; enum class DidSeek { Yes, No, }; enum class SynchronouslyNotify { Yes, No, }; double associated_effect_end() const; double effective_playback_rate() const; void apply_any_pending_playback_rate(); WebIDL::ExceptionOr silently_set_current_time(Optional); void update_finished_state(DidSeek, SynchronouslyNotify); JS::NonnullGCPtr current_ready_promise() const; JS::NonnullGCPtr current_finished_promise() const; // https://www.w3.org/TR/web-animations-1/#dom-animation-id FlyString m_id; // https://www.w3.org/TR/web-animations-1/#dom-animation-effect JS::GCPtr m_effect; // https://www.w3.org/TR/web-animations-1/#dom-animation-timeline JS::GCPtr m_timeline; // https://www.w3.org/TR/web-animations-1/#animation-start-time Optional m_start_time {}; // https://www.w3.org/TR/web-animations-1/#animation-hold-time Optional m_hold_time {}; // https://www.w3.org/TR/web-animations-1/#previous-current-time Optional m_previous_current_time {}; // https://www.w3.org/TR/web-animations-1/#playback-rate double m_playback_rate { 1.0 }; // https://www.w3.org/TR/web-animations-1/#pending-playback-rate Optional m_pending_playback_rate {}; // https://www.w3.org/TR/web-animations-1/#dom-animation-replacestate Bindings::AnimationReplaceState m_replace_state { Bindings::AnimationReplaceState::Active }; // Note: The following promises are initialized lazily to avoid constructing them outside of an execution context // https://www.w3.org/TR/web-animations-1/#current-ready-promise mutable JS::GCPtr m_current_ready_promise; // https://www.w3.org/TR/web-animations-1/#current-finished-promise mutable JS::GCPtr m_current_finished_promise; bool m_current_finished_promise_resolved { false }; // https://www.w3.org/TR/web-animations-1/#pending-play-task TaskState m_pending_play_task { TaskState::None }; // https://www.w3.org/TR/web-animations-1/#pending-pause-task TaskState m_pending_pause_task { TaskState::None }; // Flags used to manage the finish notification microtask and ultimately prevent more than one finish notification // microtask from being queued at any given time bool m_should_abort_finish_notification_microtask { false }; bool m_has_finish_notification_microtask_scheduled { false }; }; }