From 41a41b3d8f176e441f5b7157c9e811fd845eedf5 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 23 Feb 2024 12:34:08 -0500 Subject: [PATCH] Treat video elements as replaced content and render the current frame. (#31412) * Treat video elements as replaced content and render the current frame. * Update test results. --- components/layout_2020/dom.rs | 8 ++++++++ components/layout_2020/replaced.rs | 20 +++++++++++++++++++ .../object-view-box-fit-cover-video.html.ini | 2 ++ ...bject-view-box-writing-mode-video.html.ini | 2 ++ .../video_dynamic_poster_absolute.htm.ini | 2 -- .../video_dynamic_poster_relative.htm.ini | 2 -- 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tests/wpt/meta/css/css-images/object-view-box-fit-cover-video.html.ini create mode 100644 tests/wpt/meta/css/css-images/object-view-box-writing-mode-video.html.ini delete mode 100644 tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm.ini delete mode 100644 tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm.ini diff --git a/components/layout_2020/dom.rs b/components/layout_2020/dom.rs index c569b1f1b46..3843e77f217 100644 --- a/components/layout_2020/dom.rs +++ b/components/layout_2020/dom.rs @@ -93,6 +93,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> { fn as_image(self) -> Option<(Option>, PhysicalSize)>; fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize)>; fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>; + fn as_video(self) -> Option<(webrender_api::ImageKey, PhysicalSize)>; fn style(self, context: &LayoutContext) -> ServoArc; fn get_style_and_layout_data(self) -> Option>; @@ -125,6 +126,13 @@ where Some((resource, PhysicalSize::new(width, height))) } + fn as_video(self) -> Option<(webrender_api::ImageKey, PhysicalSize)> { + let node = self.to_threadsafe(); + let frame_data = node.media_data()?.current_frame?; + let (width, height) = (frame_data.1 as f64, frame_data.2 as f64); + Some((frame_data.0, PhysicalSize::new(width, height))) + } + fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize)> { let node = self.to_threadsafe(); let canvas_data = node.canvas_data()?; diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index 47c208f30a5..2c5276b20b2 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -117,11 +117,17 @@ pub(crate) struct IFrameInfo { pub browsing_context_id: BrowsingContextId, } +#[derive(Debug, Serialize)] +pub(crate) struct VideoInfo { + pub image_key: webrender_api::ImageKey, +} + #[derive(Debug, Serialize)] pub(crate) enum ReplacedContentKind { Image(Option>), IFrame(IFrameInfo), Canvas(CanvasInfo), + Video(VideoInfo), } impl ReplacedContent { @@ -145,6 +151,11 @@ impl ReplacedContent { }), None, ) + } else if let Some((image_key, intrinsic_size_in_dots)) = element.as_video() { + ( + ReplacedContentKind::Video(VideoInfo { image_key }), + Some(intrinsic_size_in_dots), + ) } else { return None; } @@ -263,6 +274,15 @@ impl ReplacedContent { }) .into_iter() .collect(), + ReplacedContentKind::Video(video) => vec![Fragment::Image(ImageFragment { + base: self.base_fragment_info.into(), + style: style.clone(), + rect: LogicalRect { + start_corner: LogicalVec2::zero(), + size: size.into(), + }, + image_key: video.image_key, + })], ReplacedContentKind::IFrame(iframe) => { vec![Fragment::IFrame(IFrameFragment { base: self.base_fragment_info.into(), diff --git a/tests/wpt/meta/css/css-images/object-view-box-fit-cover-video.html.ini b/tests/wpt/meta/css/css-images/object-view-box-fit-cover-video.html.ini new file mode 100644 index 00000000000..bc8e4ad026d --- /dev/null +++ b/tests/wpt/meta/css/css-images/object-view-box-fit-cover-video.html.ini @@ -0,0 +1,2 @@ +[object-view-box-fit-cover-video.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-images/object-view-box-writing-mode-video.html.ini b/tests/wpt/meta/css/css-images/object-view-box-writing-mode-video.html.ini new file mode 100644 index 00000000000..dc30f75ad6f --- /dev/null +++ b/tests/wpt/meta/css/css-images/object-view-box-writing-mode-video.html.ini @@ -0,0 +1,2 @@ +[object-view-box-writing-mode-video.html] + expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm.ini b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm.ini deleted file mode 100644 index c6e20626e6a..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm.ini +++ /dev/null @@ -1,2 +0,0 @@ -[video_dynamic_poster_absolute.htm] - expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm.ini b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm.ini deleted file mode 100644 index 833607a9d64..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm.ini +++ /dev/null @@ -1,2 +0,0 @@ -[video_dynamic_poster_relative.htm] - expected: FAIL