/src/serenity/Userland/Libraries/LibWeb/Animations/DocumentTimeline.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2023, Matthew Olsson <mattco@serenityos.org>. |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibJS/Heap/Heap.h> |
8 | | #include <LibJS/Runtime/Realm.h> |
9 | | #include <LibWeb/Animations/DocumentTimeline.h> |
10 | | #include <LibWeb/Bindings/DocumentTimelinePrototype.h> |
11 | | #include <LibWeb/DOM/Document.h> |
12 | | #include <LibWeb/HTML/Window.h> |
13 | | #include <LibWeb/HighResolutionTime/Performance.h> |
14 | | #include <LibWeb/WebIDL/ExceptionOr.h> |
15 | | |
16 | | namespace Web::Animations { |
17 | | |
18 | | JS_DEFINE_ALLOCATOR(DocumentTimeline); |
19 | | |
20 | | JS::NonnullGCPtr<DocumentTimeline> DocumentTimeline::create(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time) |
21 | 0 | { |
22 | 0 | auto timeline = realm.heap().allocate<DocumentTimeline>(realm, realm, document, origin_time); |
23 | 0 | auto current_time = document.last_animation_frame_timestamp(); |
24 | 0 | if (!current_time.has_value()) { |
25 | | // The document hasn't processed an animation frame yet, so just use the exact current time |
26 | 0 | auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object()); |
27 | 0 | VERIFY(window_or_worker); |
28 | 0 | current_time = window_or_worker->performance()->now(); |
29 | 0 | } |
30 | 0 | timeline->set_current_time(current_time); |
31 | 0 | return timeline; |
32 | 0 | } |
33 | | |
34 | | // https://www.w3.org/TR/web-animations-1/#dom-documenttimeline-documenttimeline |
35 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<DocumentTimeline>> DocumentTimeline::construct_impl(JS::Realm& realm, DocumentTimelineOptions options) |
36 | 0 | { |
37 | | // Creates a new DocumentTimeline. The Document with which the timeline is associated is the Document associated |
38 | | // with the Window that is the current global object. |
39 | 0 | auto& window = verify_cast<HTML::Window>(realm.global_object()); |
40 | 0 | return create(realm, window.associated_document(), options.origin_time); |
41 | 0 | } |
42 | | |
43 | | // https://www.w3.org/TR/web-animations-1/#ref-for-timeline-time-to-origin-relative-time |
44 | | Optional<double> DocumentTimeline::convert_a_timeline_time_to_an_origin_relative_time(Optional<double> timeline_time) |
45 | 0 | { |
46 | | // To convert a timeline time, timeline time, to an origin-relative time for a document timeline, timeline, return |
47 | | // the sum of the timeline time and timeline’s origin time. If timeline is inactive, return an unresolved time |
48 | | // value. |
49 | 0 | if (is_inactive() || !timeline_time.has_value()) |
50 | 0 | return {}; |
51 | 0 | return timeline_time.value() + m_origin_time; |
52 | 0 | } |
53 | | |
54 | | // https://www.w3.org/TR/web-animations-1/#origin-time |
55 | | void DocumentTimeline::set_current_time(Optional<double> current_time) |
56 | 0 | { |
57 | | // A document timeline is a type of timeline that is associated with a document and whose current time is calculated |
58 | | // as a fixed offset from the now timestamp provided each time the update animations and send events procedure is |
59 | | // run. This fixed offset is referred to as the document timeline’s origin time. |
60 | 0 | if (!current_time.has_value()) |
61 | 0 | Base::set_current_time({}); |
62 | 0 | else |
63 | 0 | Base::set_current_time(current_time.value() - m_origin_time); |
64 | | |
65 | | // After a document timeline becomes active, it is monotonically increasing. |
66 | 0 | if (!is_inactive()) |
67 | 0 | VERIFY(is_monotonically_increasing()); |
68 | 0 | } |
69 | | |
70 | | // https://www.w3.org/TR/web-animations-1/#document-timelines |
71 | | bool DocumentTimeline::is_inactive() const |
72 | 0 | { |
73 | | // A document timeline that is associated with a Document which is not an active document is also considered to be |
74 | | // inactive. |
75 | 0 | return Base::is_inactive() || !associated_document()->is_active(); |
76 | 0 | } |
77 | | |
78 | | DocumentTimeline::DocumentTimeline(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time) |
79 | 0 | : AnimationTimeline(realm) |
80 | 0 | , m_origin_time(origin_time) |
81 | 0 | { |
82 | 0 | set_associated_document(document); |
83 | 0 | } |
84 | | |
85 | | void DocumentTimeline::initialize(JS::Realm& realm) |
86 | 0 | { |
87 | 0 | Base::initialize(realm); |
88 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(DocumentTimeline); |
89 | 0 | } |
90 | | |
91 | | } |