/src/serenity/Userland/Libraries/LibWeb/WebVTT/VTTCue.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2024-2025, Jamie Mansfield <jmansfield@cadixdev.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibWeb/Bindings/Intrinsics.h> |
8 | | #include <LibWeb/HTML/Window.h> |
9 | | #include <LibWeb/WebVTT/VTTCue.h> |
10 | | |
11 | | namespace Web::WebVTT { |
12 | | |
13 | | JS_DEFINE_ALLOCATOR(VTTCue); |
14 | | |
15 | | // https://w3c.github.io/webvtt/#dom-vttcue-vttcue |
16 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<VTTCue>> VTTCue::construct_impl(JS::Realm& realm, double start_time, double end_time, String const& text) |
17 | 0 | { |
18 | | // 1. Create a new WebVTT cue. Let cue be that WebVTT cue. |
19 | 0 | auto cue = realm.heap().allocate<VTTCue>(realm, realm, nullptr); |
20 | | |
21 | | // 2. Let cue’s text track cue start time be the value of the startTime argument. |
22 | 0 | cue->m_start_time = start_time; |
23 | | |
24 | | // 3. If the value of the endTime argument is negative Infinity or a Not-a-Number (NaN) value, then throw a TypeError exception. |
25 | | // Otherwise, let cue’s text track cue end time be the value of the endTime argument. |
26 | 0 | if (end_time == -AK::Infinity<double> || isnan(end_time)) |
27 | 0 | return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "End time is negative infinity or NaN"_string }; |
28 | 0 | cue->m_end_time = end_time; |
29 | | |
30 | | // 4. Let cue’s cue text be the value of the text argument, and let the rules for extracting the chapter title be the WebVTT rules |
31 | | // for extracting the chapter title. |
32 | 0 | cue->m_text = text; |
33 | | // FIXME: let the rules for extracting the chapter title be the WebVTT rules for extracting the chapter title. |
34 | | |
35 | | // 5. Let cue’s text track cue identifier be the empty string. |
36 | 0 | cue->m_identifier = ""_string; |
37 | | |
38 | | // 6. Let cue’s text track cue pause-on-exit flag be false. |
39 | 0 | cue->m_pause_on_exit = false; |
40 | | |
41 | | // 7. Let cue’s WebVTT cue region be null. |
42 | 0 | cue->m_region = nullptr; |
43 | | |
44 | | // 8. Let cue’s WebVTT cue writing direction be horizontal. |
45 | 0 | cue->m_writing_direction = WritingDirection::Horizontal; |
46 | | |
47 | | // 9. Let cue’s WebVTT cue snap-to-lines flag be true. |
48 | 0 | cue->m_snap_to_lines = true; |
49 | | |
50 | | // 10. Let cue’s WebVTT cue line be auto. |
51 | 0 | cue->m_line = Bindings::AutoKeyword::Auto; |
52 | | |
53 | | // 11. Let cue’s WebVTT cue line alignment be start alignment. |
54 | 0 | cue->m_line_alignment = Bindings::LineAlignSetting::Start; |
55 | | |
56 | | // 12. Let cue’s WebVTT cue position be auto. |
57 | 0 | cue->m_position = Bindings::AutoKeyword::Auto; |
58 | | |
59 | | // 13. Let cue’s WebVTT cue position alignment be auto. |
60 | 0 | cue->m_position_alignment = Bindings::PositionAlignSetting::Auto; |
61 | | |
62 | | // 14. Let cue’s WebVTT cue size be 100. |
63 | 0 | cue->m_size = 100; |
64 | | |
65 | | // 15. Let cue’s WebVTT cue text alignment be center alignment. |
66 | 0 | cue->m_text_alignment = Bindings::AlignSetting::Center; |
67 | | |
68 | | // 16. Return the VTTCue object representing cue. |
69 | 0 | return cue; |
70 | 0 | } |
71 | | |
72 | | VTTCue::VTTCue(JS::Realm& realm, JS::GCPtr<HTML::TextTrack> track) |
73 | 0 | : HTML::TextTrackCue(realm, track) |
74 | 0 | { |
75 | 0 | } |
76 | | |
77 | | void VTTCue::initialize(JS::Realm& realm) |
78 | 0 | { |
79 | 0 | Base::initialize(realm); |
80 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(VTTCue); |
81 | 0 | } |
82 | | |
83 | | void VTTCue::visit_edges(Visitor& visitor) |
84 | 0 | { |
85 | 0 | Base::visit_edges(visitor); |
86 | 0 | visitor.visit(m_region); |
87 | 0 | } |
88 | | |
89 | | // https://w3c.github.io/webvtt/#dom-vttcue-vertical |
90 | | Bindings::DirectionSetting VTTCue::vertical() const |
91 | 0 | { |
92 | 0 | switch (m_writing_direction) { |
93 | 0 | case WritingDirection::Horizontal: |
94 | 0 | return Bindings::DirectionSetting::Empty; |
95 | 0 | case WritingDirection::VerticalGrowingLeft: |
96 | 0 | return Bindings::DirectionSetting::Rl; |
97 | 0 | case WritingDirection::VerticalGrowingRight: |
98 | 0 | return Bindings::DirectionSetting::Lr; |
99 | 0 | } |
100 | 0 | VERIFY_NOT_REACHED(); |
101 | 0 | } |
102 | | |
103 | | // https://w3c.github.io/webvtt/#dom-vttcue-vertical |
104 | | void VTTCue::set_vertical(Bindings::DirectionSetting vertical) |
105 | 0 | { |
106 | 0 | switch (vertical) { |
107 | 0 | case Bindings::DirectionSetting::Empty: |
108 | 0 | m_writing_direction = WritingDirection::Horizontal; |
109 | 0 | break; |
110 | 0 | case Bindings::DirectionSetting::Rl: |
111 | 0 | m_writing_direction = WritingDirection::VerticalGrowingLeft; |
112 | 0 | break; |
113 | 0 | case Bindings::DirectionSetting::Lr: |
114 | 0 | m_writing_direction = WritingDirection::VerticalGrowingRight; |
115 | 0 | break; |
116 | 0 | } |
117 | 0 | } |
118 | | |
119 | | // https://w3c.github.io/webvtt/#cue-computed-line |
120 | | double VTTCue::computed_line() |
121 | 0 | { |
122 | | // 1. If the line is numeric, the WebVTT cue snap-to-lines flag of the WebVTT cue is false, and the line is negative |
123 | | // or greater than 100, then return 100 and abort these steps. |
124 | 0 | if (m_line.has<double>() && !m_snap_to_lines && (m_line.get<double>() < 0 || m_line.get<double>() > 100)) |
125 | 0 | return 100; |
126 | | |
127 | | // 2. If the line is numeric, return the value of the WebVTT cue line and abort these steps. (Either the WebVTT cue |
128 | | // snap-to-lines flag is true, so any value, not just those in the range 0..100, is valid, or the value is in the |
129 | | // range 0..100 and is thus valid regardless of the value of that flag.) |
130 | 0 | if (m_line.has<double>()) |
131 | 0 | return m_line.get<double>(); |
132 | | |
133 | | // 3. If the WebVTT cue snap-to-lines flag of the WebVTT cue is false, return the value 100 and abort these steps. |
134 | | // (The line is the special value auto.) |
135 | 0 | if (!m_snap_to_lines) |
136 | 0 | return 100; |
137 | | |
138 | | // FIXME: 4. Let cue be the WebVTT cue. |
139 | | |
140 | | // FIXME: 5. If cue is not in a list of cues of a text track, or if that text track is not in the list of text tracks of |
141 | | // a media element, return −1 and abort these steps. |
142 | | |
143 | | // FIXME: 6. Let track be the text track whose list of cues the cue is in. |
144 | | |
145 | | // FIXME: 7. Let n be the number of text tracks whose text track mode is showing and that are in the media element’s list |
146 | | // of text tracks before track. |
147 | 0 | auto n = 0; |
148 | | |
149 | | // 8. Increment n by one. |
150 | 0 | n++; |
151 | | |
152 | | // 9. Negate n. |
153 | 0 | n = -n; |
154 | | |
155 | | // 10. Return n. |
156 | 0 | dbgln("FIXME: Stubbed VTTCue.computed_line()"); |
157 | 0 | return n; |
158 | 0 | } |
159 | | |
160 | | // https://w3c.github.io/webvtt/#cue-computed-position |
161 | | double VTTCue::computed_position() |
162 | 0 | { |
163 | | // 1. If the position is numeric between 0 and 100, then return the value of the position and abort these steps. |
164 | | // (Otherwise, the position is the special value auto.) |
165 | 0 | if (m_position.has<double>() && m_position.get<double>() >= 0 && m_position.get<double>() <= 100) |
166 | 0 | return m_position.get<double>(); |
167 | | |
168 | | // 2. If the cue text alignment is left, return 0 and abort these steps. |
169 | 0 | if (m_text_alignment == Bindings::AlignSetting::Left) |
170 | 0 | return 0; |
171 | | |
172 | | // 3. If the cue text alignment is right, return 100 and abort these steps. |
173 | 0 | if (m_text_alignment == Bindings::AlignSetting::Right) |
174 | 0 | return 100; |
175 | | |
176 | | // 4. Otherwise, return 50 and abort these steps. |
177 | 0 | return 50; |
178 | 0 | } |
179 | | |
180 | | // https://w3c.github.io/webvtt/#cue-computed-position-alignment |
181 | | Bindings::PositionAlignSetting VTTCue::computed_position_alignment() |
182 | 0 | { |
183 | | // 1. If the WebVTT cue position alignment is not auto, then return the value of the WebVTT cue position alignment and abort these |
184 | | // steps. |
185 | 0 | if (m_position_alignment != Bindings::PositionAlignSetting::Auto) |
186 | 0 | return m_position_alignment; |
187 | | |
188 | | // 2. If the WebVTT cue text alignment is left, return line-left and abort these steps. |
189 | 0 | if (m_text_alignment == Bindings::AlignSetting::Left) |
190 | 0 | return Bindings::PositionAlignSetting::LineLeft; |
191 | | |
192 | | // 3. If the WebVTT cue text alignment is right, return line-right and abort these steps. |
193 | 0 | if (m_text_alignment == Bindings::AlignSetting::Right) |
194 | 0 | return Bindings::PositionAlignSetting::LineRight; |
195 | | |
196 | | // FIXME: 4. If the WebVTT cue text alignment is start, return line-left if the base direction of the cue text is left-to-right, line-right |
197 | | // otherwise. |
198 | | |
199 | | // FIXME: 5. If the WebVTT cue text alignment is end, return line-right if the base direction of the cue text is left-to-right, line-left |
200 | | // otherwise. |
201 | | |
202 | | // 6. Otherwise, return center. |
203 | 0 | return Bindings::PositionAlignSetting::Center; |
204 | 0 | } |
205 | | |
206 | | } |