2023-11-04 12:16:37 -03:00
/*
2024-02-02 19:01:30 -03:00
* Copyright ( c ) 2023 - 2024 , Matthew Olsson < mattco @ serenityos . org > .
2023-11-04 12:16:37 -03:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2023-11-04 15:58:09 -03:00
# include <LibWeb/Animations/Animation.h>
2023-11-04 12:16:37 -03:00
# include <LibWeb/Animations/AnimationTimeline.h>
2026-04-18 05:54:06 -03:00
# include <LibWeb/Bindings/AnimationTimeline.h>
2023-11-04 12:16:37 -03:00
# include <LibWeb/DOM/Document.h>
namespace Web : : Animations {
2024-11-14 12:01:23 -03:00
GC_DEFINE_ALLOCATOR ( AnimationTimeline ) ;
2023-11-19 15:47:52 -03:00
2025-07-29 05:15:12 -03:00
// https://drafts.csswg.org/web-animations-1/#dom-animationtimeline-currenttime
2025-11-30 04:31:57 -03:00
Optional < TimeValue > AnimationTimeline : : current_time ( ) const
2025-07-29 05:15:12 -03:00
{
// Returns the current time for this timeline or null if this timeline is inactive.
if ( is_inactive ( ) )
return { } ;
return m_current_time ;
}
2025-11-30 04:31:57 -03:00
void AnimationTimeline : : set_current_time ( Optional < TimeValue > value )
2023-11-04 12:16:37 -03:00
{
2025-07-29 05:15:12 -03:00
if ( m_is_monotonically_increasing & & m_current_time . has_value ( ) & & ( ! value . has_value ( ) | | * value < * m_current_time ) ) {
dbgln ( " AnimationTimeline::set_current_time({}): monotonically increasing timeline can only move forward " , value ) ;
return ;
2023-11-04 12:16:37 -03:00
}
2025-07-29 05:15:12 -03:00
2025-12-15 22:01:48 -03:00
m_current_time = value ;
2026-04-23 05:52:16 -03:00
2026-05-04 04:08:12 -03:00
update_associated_animations ( ) ;
2026-04-23 05:52:16 -03:00
}
2026-05-04 04:08:12 -03:00
void AnimationTimeline : : update_associated_animations ( )
2026-04-23 05:52:16 -03:00
{
// https://drafts.csswg.org/web-animations-1/#animation-frame-loop
// Note: Due to the hierarchical nature of the timing model, updating the current time of a timeline also involves:
// - Updating the current time of any animations associated with the timeline.
// - Running the update an animation's finished state procedure for any animations whose current time has been
// updated.
// - Queueing animation events for any such animations.
2026-05-04 04:08:12 -03:00
// NB: Since we dispatch events for all animations regardless of whether they have a timeline we handle them all together in Document::update_animations_and_send_events()
2026-04-23 05:52:16 -03:00
for ( auto & animation : m_associated_animations )
animation . update ( ) ;
2023-11-04 12:16:37 -03:00
}
2025-11-28 04:07:13 -03:00
// https://drafts.csswg.org/web-animations-2/#timeline-duration
NullableCSSNumberish AnimationTimeline : : duration_for_bindings ( ) const
{
// The duration of a timeline gives the maximum value a timeline may generate for its current time. This value is
// used to calculate the intrinsic iteration duration for the target effect of an animation that is associated with
// the timeline when the effect’ s iteration duration is "auto". The value is computed such that the effect fills the
// available time. For a monotonic timeline, there is no upper bound on current time, and timeline duration is
// unresolved. For a non-monotonic (e.g. scroll) timeline, the duration has a fixed upper bound. In this case, the
// timeline is a progress-based timeline, and its timeline duration is 100%.
2025-12-12 19:12:03 -03:00
return NullableCSSNumberish : : from_optional_css_numberish_time ( realm ( ) , duration ( ) ) ;
2025-11-28 04:07:13 -03:00
}
2025-07-29 05:15:12 -03:00
// https://drafts.csswg.org/web-animations-1/#timeline
2023-11-04 12:16:37 -03:00
bool AnimationTimeline : : is_inactive ( ) const
{
2025-07-29 05:15:12 -03:00
// A timeline is considered to be inactive when its time value is unresolved, and active otherwise.
2023-11-04 12:16:37 -03:00
return ! m_current_time . has_value ( ) ;
}
2026-04-23 02:05:53 -03:00
AnimationTimeline : : AnimationTimeline ( JS : : Realm & realm , GC : : Ref < DOM : : Document > document )
2023-11-04 12:16:37 -03:00
: Bindings : : PlatformObject ( realm )
2026-04-23 02:05:53 -03:00
, m_associated_document ( document )
2023-11-04 12:16:37 -03:00
{
}
2024-03-11 11:17:17 -03:00
void AnimationTimeline : : finalize ( )
2023-11-04 12:43:10 -03:00
{
2026-01-29 16:46:37 -03:00
Base : : finalize ( ) ;
2026-04-23 02:05:53 -03:00
m_associated_document - > disassociate_with_timeline ( * this ) ;
2023-11-04 12:43:10 -03:00
}
2023-11-04 12:16:37 -03:00
void AnimationTimeline : : initialize ( JS : : Realm & realm )
{
2024-03-16 09:13:08 -03:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( AnimationTimeline ) ;
2025-04-20 11:22:57 -03:00
Base : : initialize ( realm ) ;
2026-04-23 02:05:53 -03:00
m_associated_document - > associate_with_timeline ( * this ) ;
2023-11-04 12:16:37 -03:00
}
void AnimationTimeline : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_associated_document ) ;
2025-12-17 21:53:21 -03:00
// We intentionally don't visit m_associated_animations here to avoid keeping Animations alive solely because they
// are associated with a timeline. Animations are disassociated from timelines in Animation::finalize() so we don't
// need to worry about dangling references.
2023-11-04 12:16:37 -03:00
}
}