1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use js::rust::HandleObject;
10use script_bindings::cell::DomRefCell;
11use script_bindings::reflector::reflect_dom_object_with_proto_and_cx;
12use servo_webvtt::{
13 WebVttCue, WebVttCueSize, WebVttLineAlignment, WebVttLineAndPositionSetting,
14 WebVttPositionAlignment, WebVttSnapToLines, WebVttTextAlignment, WebVttWritingDirection,
15};
16
17use crate::conversions::Convert;
18use crate::dom::bindings::codegen::Bindings::VTTCueBinding::{
19 self, AlignSetting, AutoKeyword, DirectionSetting, LineAlignSetting, PositionAlignSetting,
20 VTTCueMethods,
21};
22use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
23use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
24use crate::dom::bindings::num::Finite;
25use crate::dom::bindings::reflector::DomGlobal;
26use crate::dom::bindings::root::{Dom, DomRoot};
27use crate::dom::bindings::str::DOMString;
28use crate::dom::documentfragment::DocumentFragment;
29use crate::dom::texttrack::TextTrack;
30use crate::dom::texttrackcue::TextTrackCue;
31use crate::dom::vttregion::VTTRegion;
32use crate::dom::window::Window;
33
34#[dom_struct]
35pub(crate) struct VTTCue {
36 texttrackcue: TextTrackCue,
37 region: DomRefCell<Option<Dom<VTTRegion>>>,
38 vertical: Cell<DirectionSetting>,
39 snap_to_lines: Cell<bool>,
40 line: DomRefCell<LineAndPositionSetting>,
41 line_align: Cell<LineAlignSetting>,
42 position: DomRefCell<LineAndPositionSetting>,
43 position_align: Cell<PositionAlignSetting>,
44 size: Cell<f64>,
45 align: Cell<AlignSetting>,
46 text: DomRefCell<DOMString>,
47}
48
49impl VTTCue {
50 #[expect(clippy::too_many_arguments)]
51 fn new_inherited(
52 start_time: f64,
53 end_time: f64,
54 text: DOMString,
55 id: DOMString,
56 vertical: DirectionSetting,
57 snap_to_lines: bool,
58 line: LineAndPositionSetting,
59 line_align: LineAlignSetting,
60 position: LineAndPositionSetting,
61 position_align: PositionAlignSetting,
62 size: f64,
63 align: AlignSetting,
64 track: Option<&TextTrack>,
65 ) -> Self {
66 VTTCue {
67 texttrackcue: TextTrackCue::new_inherited(id, start_time, end_time, track),
68 text: DomRefCell::new(text),
69 region: DomRefCell::new(None),
70 vertical: Cell::new(vertical),
71 snap_to_lines: Cell::new(snap_to_lines),
72 line: DomRefCell::new(line),
73 line_align: Cell::new(line_align),
74 position: DomRefCell::new(position),
75 position_align: Cell::new(position_align),
76 size: Cell::new(size),
77 align: Cell::new(align),
78 }
79 }
80
81 #[expect(clippy::too_many_arguments)]
82 fn new(
83 cx: &mut JSContext,
84 window: &Window,
85 proto: Option<HandleObject>,
86 start_time: f64,
87 end_time: f64,
88 text: DOMString,
89 id: DOMString,
90 vertical: DirectionSetting,
91 snap_to_lines: bool,
92 line: LineAndPositionSetting,
93 line_align: LineAlignSetting,
94 position: LineAndPositionSetting,
95 position_align: PositionAlignSetting,
96 size: f64,
97 align: AlignSetting,
98 track: Option<&TextTrack>,
99 ) -> DomRoot<Self> {
100 reflect_dom_object_with_proto_and_cx(
101 Box::new(Self::new_inherited(
102 start_time,
103 end_time,
104 text,
105 id,
106 vertical,
107 snap_to_lines,
108 line,
109 line_align,
110 position,
111 position_align,
112 size,
113 align,
114 track,
115 )),
116 window,
117 proto,
118 cx,
119 )
120 }
121
122 pub(crate) fn create_from_vtt(
123 cx: &mut JSContext,
124 vtt_cue: WebVttCue,
125 window: &Window,
126 track: Option<&TextTrack>,
127 ) -> DomRoot<VTTCue> {
128 Self::new(
129 cx,
130 window,
131 None,
132 vtt_cue.start_time,
133 vtt_cue.end_time,
134 vtt_cue.text.into(),
135 vtt_cue.identifier.into(),
136 vtt_cue.writing_direction.convert(),
137 vtt_cue.snap_to_lines.convert(),
138 vtt_cue.line.convert(),
139 vtt_cue.line_alignment.convert(),
140 vtt_cue.position.convert(),
141 vtt_cue.position_alignment.convert(),
142 vtt_cue.size.convert(),
143 vtt_cue.text_alignment.convert(),
144 track,
145 )
146 }
147}
148
149impl VTTCueMethods<crate::DomTypeHolder> for VTTCue {
150 fn Constructor(
152 cx: &mut JSContext,
153 window: &Window,
154 proto: Option<HandleObject>,
155 start_time: Finite<f64>,
156 end_time: Finite<f64>,
157 text: DOMString,
158 ) -> Fallible<DomRoot<Self>> {
159 if (end_time.is_infinite() && end_time.is_sign_negative()) || end_time.is_nan() {
163 return Err(Error::Type(
164 c"End time is negative Infinity or Not-a-Number".to_owned(),
165 ));
166 }
167 Ok(VTTCue::new(
170 cx,
171 window,
172 proto,
173 *start_time,
175 *end_time,
176 text,
181 Default::default(),
183 DirectionSetting::_empty,
185 true,
187 LineAndPositionSetting::Auto,
189 LineAlignSetting::Start,
191 LineAndPositionSetting::Auto,
193 PositionAlignSetting::Auto,
195 100.,
197 AlignSetting::Center,
199 None,
200 ))
201 }
202
203 fn GetRegion(&self) -> Option<DomRoot<VTTRegion>> {
205 self.region
206 .borrow()
207 .as_ref()
208 .map(|r| DomRoot::from_ref(&**r))
209 }
210
211 fn SetRegion(&self, value: Option<&VTTRegion>) {
213 *self.region.borrow_mut() = value.map(Dom::from_ref)
214 }
215
216 fn Vertical(&self) -> DirectionSetting {
218 self.vertical.get()
219 }
220
221 fn SetVertical(&self, value: DirectionSetting) {
223 self.vertical.set(value);
224 }
225
226 fn SnapToLines(&self) -> bool {
228 self.snap_to_lines.get()
229 }
230
231 fn SetSnapToLines(&self, value: bool) {
233 self.snap_to_lines.set(value)
234 }
235
236 fn Line(&self) -> VTTCueBinding::LineAndPositionSetting {
238 VTTCueBinding::LineAndPositionSetting::from(self.line.borrow().clone())
239 }
240
241 fn SetLine(&self, value: VTTCueBinding::LineAndPositionSetting) {
243 *self.line.borrow_mut() = value.into();
244 }
245
246 fn LineAlign(&self) -> LineAlignSetting {
248 self.line_align.get()
249 }
250
251 fn SetLineAlign(&self, value: LineAlignSetting) {
253 self.line_align.set(value);
254 }
255
256 fn Position(&self) -> VTTCueBinding::LineAndPositionSetting {
258 VTTCueBinding::LineAndPositionSetting::from(self.position.borrow().clone())
259 }
260
261 fn SetPosition(&self, value: VTTCueBinding::LineAndPositionSetting) -> ErrorResult {
263 if let VTTCueBinding::LineAndPositionSetting::Double(x) = value &&
264 (*x < 0_f64 || *x > 100_f64)
265 {
266 return Err(Error::IndexSize(None));
267 }
268
269 *self.position.borrow_mut() = value.into();
270 Ok(())
271 }
272
273 fn PositionAlign(&self) -> PositionAlignSetting {
275 self.position_align.get()
276 }
277
278 fn SetPositionAlign(&self, value: PositionAlignSetting) {
280 self.position_align.set(value);
281 }
282
283 fn Size(&self) -> Finite<f64> {
285 Finite::wrap(self.size.get())
286 }
287
288 fn SetSize(&self, value: Finite<f64>) -> ErrorResult {
290 if *value < 0_f64 || *value > 100_f64 {
291 return Err(Error::IndexSize(None));
292 }
293
294 self.size.set(*value);
295 Ok(())
296 }
297
298 fn Align(&self) -> AlignSetting {
300 self.align.get()
301 }
302
303 fn SetAlign(&self, value: AlignSetting) {
305 self.align.set(value);
306 }
307
308 fn Text(&self) -> DOMString {
310 self.text.borrow().clone()
311 }
312
313 fn SetText(&self, value: DOMString) {
315 *self.text.borrow_mut() = value;
316 }
317
318 fn GetCueAsHTML(&self, cx: &mut JSContext) -> DomRoot<DocumentFragment> {
320 let global = self.global();
322 let window = global.as_window();
323 let document = window.Document();
324 DocumentFragment::new(cx, &document)
325 }
326}
327
328#[derive(Clone, JSTraceable, MallocSizeOf)]
329enum LineAndPositionSetting {
330 Double(f64),
331 Auto,
332}
333
334impl From<VTTCueBinding::LineAndPositionSetting> for LineAndPositionSetting {
335 fn from(value: VTTCueBinding::LineAndPositionSetting) -> Self {
336 match value {
337 VTTCueBinding::LineAndPositionSetting::Double(x) => LineAndPositionSetting::Double(*x),
338 VTTCueBinding::LineAndPositionSetting::AutoKeyword(_) => LineAndPositionSetting::Auto,
339 }
340 }
341}
342
343impl From<LineAndPositionSetting> for VTTCueBinding::LineAndPositionSetting {
344 fn from(value: LineAndPositionSetting) -> Self {
345 match value {
346 LineAndPositionSetting::Double(x) => {
347 VTTCueBinding::LineAndPositionSetting::Double(Finite::wrap(x))
348 },
349 LineAndPositionSetting::Auto => {
350 VTTCueBinding::LineAndPositionSetting::AutoKeyword(AutoKeyword::Auto)
351 },
352 }
353 }
354}
355
356impl Convert<LineAndPositionSetting> for WebVttLineAndPositionSetting {
357 fn convert(self) -> LineAndPositionSetting {
358 match self {
359 WebVttLineAndPositionSetting::Double(x) => LineAndPositionSetting::Double(x),
360 WebVttLineAndPositionSetting::Auto => LineAndPositionSetting::Auto,
361 }
362 }
363}
364
365impl Convert<DirectionSetting> for WebVttWritingDirection {
366 fn convert(self) -> DirectionSetting {
367 match self {
368 WebVttWritingDirection::Horizontal => DirectionSetting::_empty,
369 WebVttWritingDirection::VerticalGrowingLeft => DirectionSetting::Rl,
370 WebVttWritingDirection::VerticalGrowingRight => DirectionSetting::Lr,
371 }
372 }
373}
374
375impl Convert<AlignSetting> for WebVttTextAlignment {
376 fn convert(self) -> AlignSetting {
377 match self {
378 WebVttTextAlignment::Start => AlignSetting::Start,
379 WebVttTextAlignment::Center => AlignSetting::Center,
380 WebVttTextAlignment::End => AlignSetting::End,
381 WebVttTextAlignment::Left => AlignSetting::Left,
382 WebVttTextAlignment::Right => AlignSetting::Right,
383 }
384 }
385}
386
387impl Convert<LineAlignSetting> for WebVttLineAlignment {
388 fn convert(self) -> LineAlignSetting {
389 match self {
390 WebVttLineAlignment::Start => LineAlignSetting::Start,
391 WebVttLineAlignment::Center => LineAlignSetting::Center,
392 WebVttLineAlignment::End => LineAlignSetting::End,
393 }
394 }
395}
396
397impl Convert<PositionAlignSetting> for WebVttPositionAlignment {
398 fn convert(self) -> PositionAlignSetting {
399 match self {
400 WebVttPositionAlignment::LineLeft => PositionAlignSetting::Line_left,
401 WebVttPositionAlignment::Center => PositionAlignSetting::Center,
402 WebVttPositionAlignment::LineRight => PositionAlignSetting::Line_right,
403 WebVttPositionAlignment::Auto => PositionAlignSetting::Auto,
404 }
405 }
406}
407
408impl Convert<bool> for WebVttSnapToLines {
409 fn convert(self) -> bool {
410 match self {
411 WebVttSnapToLines::Yes => true,
412 WebVttSnapToLines::No => false,
413 }
414 }
415}
416
417impl Convert<f64> for WebVttCueSize {
418 fn convert(self) -> f64 {
419 self.0
420 }
421}