diff options
author | eri <epazos@igalia.com> | 2024-10-29 22:42:22 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-29 22:42:22 +0000 |
commit | 01820e2a8a28bcf3b8e1b17863984d8f729ca79b (patch) | |
tree | 99df04833606ca839535daff4b0e75488556a18a | |
parent | 43d1601016e03fe83fe9b8a526357de1d5fc4122 (diff) | |
download | servo-01820e2a8a28bcf3b8e1b17863984d8f729ca79b.tar.gz servo-01820e2a8a28bcf3b8e1b17863984d8f729ca79b.zip |
Improve how intrinsic sizes work for videos (#31746)
* feat: patch for video layout sizes
added rebase from main 2024/10/05
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Signed-off-by: eri <epazos@igalia.com>
* feat: take width and height parameters if provided
Signed-off-by: eri <epazos@igalia.com>
* chore: tidy the code and update test expectations
Signed-off-by: eri <epazos@igalia.com>
* feat: handle removing poster
Signed-off-by: eri <epazos@igalia.com>
* chore: update test expectations and remove debug code
Signed-off-by: eri <epazos@igalia.com>
* fix: issues after rebasing to main
Signed-off-by: eri <epazos@igalia.com>
* feat: pass src remove test and tidy
Signed-off-by: eri <epazos@igalia.com>
* chore: clippy fixes
Signed-off-by: eri <epazos@igalia.com>
* chore: update passing test expectations
Signed-off-by: eri <epazos@igalia.com>
* fix object-position-svg test
Signed-off-by: eri <epazos@igalia.com>
* fix unintentional override of video size and resize events
Signed-off-by: eri <epazos@igalia.com>
* change how resize events are sent to better match the spec
Signed-off-by: eri <epazos@igalia.com>
* simplify poster mutation handling
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Signed-off-by: eri <eri@inventati.org>
* improved handling of intrinsic sizes
- differentiate between natural size and css size
- presentational attributes
- fallback ratio for video element
- handle more cases where the src/poster are added/removed
- aspect ratio hints
Signed-off-by: eri <epazos@igalia.com>
* update test expectations
Signed-off-by: eri <epazos@igalia.com>
* fix cleaning current frame
Signed-off-by: eri <epazos@igalia.com>
* update test expectations
Signed-off-by: eri <epazos@igalia.com>
* Apply suggestions from code review
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Signed-off-by: eri <eri@inventati.org>
* More code review suggestions
Signed-off-by: eri <epazos@igalia.com>
* Prevent aspect-ratio:auto from pulling the ratio from the default object size
As resolved in https://github.com/w3c/csswg-drafts/issues/7524#issuecomment-1204462924
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
---------
Signed-off-by: eri <epazos@igalia.com>
Signed-off-by: eri <eri@inventati.org>
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
25 files changed, 291 insertions, 361 deletions
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index c09169d25f4..37d9fba2db2 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -1919,14 +1919,14 @@ impl Fragment { } }, SpecificFragmentInfo::Media(ref fragment_info) => { - if let Some((ref image_key, _, _)) = fragment_info.current_frame { + if let Some(ref media_frame) = fragment_info.current_frame { let base = create_base_display_item(state); state.add_image_item( base, webrender_api::ImageDisplayItem { bounds: stacking_relative_content_box.to_layout(), common: items::empty_common_item_properties(), - image_key: *image_key, + image_key: media_frame.image_key, image_rendering: ImageRendering::Auto, alpha_type: webrender_api::AlphaType::PremultipliedAlpha, color: webrender_api::ColorF::WHITE, diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 6daa29325bd..57071548396 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -26,7 +26,9 @@ use range::*; use script_layout_interface::wrapper_traits::{ PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode, }; -use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource, HTMLMediaData, SVGSVGData}; +use script_layout_interface::{ + HTMLCanvasData, HTMLCanvasDataSource, HTMLMediaData, MediaFrame, SVGSVGData, +}; use serde::ser::{Serialize, SerializeStruct, Serializer}; use servo_url::ServoUrl; use style::computed_values::border_collapse::T as BorderCollapse; @@ -381,7 +383,7 @@ impl CanvasFragmentInfo { #[derive(Clone)] pub struct MediaFragmentInfo { - pub current_frame: Option<(webrender_api::ImageKey, i32, i32)>, + pub current_frame: Option<MediaFrame>, } impl MediaFragmentInfo { @@ -1036,13 +1038,9 @@ impl Fragment { Au(0) } }, - SpecificFragmentInfo::Media(ref info) => { - if let Some((_, width, _)) = info.current_frame { - Au::from_px(width) - } else { - Au(0) - } - }, + SpecificFragmentInfo::Media(ref info) => info + .current_frame + .map_or(Au(0), |frame| Au::from_px(frame.width)), SpecificFragmentInfo::Canvas(ref info) => info.dom_width, SpecificFragmentInfo::Svg(ref info) => info.dom_width, // Note: Currently for replaced element with no intrinsic size, @@ -1066,13 +1064,9 @@ impl Fragment { Au(0) } }, - SpecificFragmentInfo::Media(ref info) => { - if let Some((_, _, height)) = info.current_frame { - Au::from_px(height) - } else { - Au(0) - } - }, + SpecificFragmentInfo::Media(ref info) => info + .current_frame + .map_or(Au(0), |frame| Au::from_px(frame.height)), SpecificFragmentInfo::Canvas(ref info) => info.dom_height, SpecificFragmentInfo::Svg(ref info) => info.dom_height, SpecificFragmentInfo::Iframe(_) => Au::from_px(DEFAULT_REPLACED_HEIGHT), diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index 11131d85e2b..baf0cd890be 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -291,14 +291,16 @@ impl Fragment { .to_webrender(); let common = builder.common_properties(clip, &image.style); - builder.wr().push_image( - &common, - rect, - image_rendering, - wr::AlphaType::PremultipliedAlpha, - image.image_key, - wr::ColorF::WHITE, - ); + if let Some(image_key) = image.image_key { + builder.wr().push_image( + &common, + rect, + image_rendering, + wr::AlphaType::PremultipliedAlpha, + image_key, + wr::ColorF::WHITE, + ); + } }, Visibility::Hidden => (), Visibility::Collapse => (), diff --git a/components/layout_2020/dom.rs b/components/layout_2020/dom.rs index 205d2db5c2a..e742b7e663a 100644 --- a/components/layout_2020/dom.rs +++ b/components/layout_2020/dom.rs @@ -102,7 +102,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> { fn as_image(self) -> Option<(Option<Arc<Image>>, PhysicalSize<f64>)>; fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>; fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>; - fn as_video(self) -> Option<(webrender_api::ImageKey, PhysicalSize<f64>)>; + fn as_video(self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)>; fn as_typeless_object_with_data_attribute(self) -> Option<String>; fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>; @@ -136,11 +136,19 @@ where Some((resource, PhysicalSize::new(width, height))) } - fn as_video(self) -> Option<(webrender_api::ImageKey, PhysicalSize<f64>)> { + fn as_video(self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)> { 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))) + let data = node.media_data()?; + let natural_size = if let Some(frame) = data.current_frame { + Some(PhysicalSize::new(frame.width.into(), frame.height.into())) + } else { + data.metadata + .map(|meta| PhysicalSize::new(meta.width.into(), meta.height.into())) + }; + Some(( + data.current_frame.map(|frame| frame.image_key), + natural_size, + )) } fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)> { diff --git a/components/layout_2020/fragment_tree/fragment.rs b/components/layout_2020/fragment_tree/fragment.rs index 28b2799d681..69e87df1e11 100644 --- a/components/layout_2020/fragment_tree/fragment.rs +++ b/components/layout_2020/fragment_tree/fragment.rs @@ -85,7 +85,7 @@ pub(crate) struct ImageFragment { pub rect: PhysicalRect<Au>, pub clip: PhysicalRect<Au>, #[serde(skip_serializing)] - pub image_key: ImageKey, + pub image_key: Option<ImageKey>, } #[derive(Serialize)] diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index ed740e9fc3b..0f65d30f822 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -137,7 +137,7 @@ pub(crate) enum ReplacedContentKind { Image(Option<Arc<Image>>), IFrame(IFrameInfo), Canvas(CanvasInfo), - Video(VideoInfo), + Video(Option<VideoInfo>), } impl ReplacedContent { @@ -173,24 +173,25 @@ impl ReplacedContent { ) } else if let Some((image_key, natural_size_in_dots)) = element.as_video() { ( - ReplacedContentKind::Video(VideoInfo { image_key }), - Some(natural_size_in_dots), + ReplacedContentKind::Video(image_key.map(|key| VideoInfo { image_key: key })), + natural_size_in_dots, ) } else { return None; } }; - let natural_size = - natural_size_in_dots.map_or_else(NaturalSizes::empty, |naturalc_size_in_dots| { - // FIXME: should 'image-resolution' (when implemented) be used *instead* of - // `script::dom::htmlimageelement::ImageRequest::current_pixel_density`? - // https://drafts.csswg.org/css-images-4/#the-image-resolution - let dppx = 1.0; - let width = (naturalc_size_in_dots.width as CSSFloat) / dppx; - let height = (naturalc_size_in_dots.height as CSSFloat) / dppx; - NaturalSizes::from_width_and_height(width, height) - }); + let natural_size = if let Some(naturalc_size_in_dots) = natural_size_in_dots { + // FIXME: should 'image-resolution' (when implemented) be used *instead* of + // `script::dom::htmlimageelement::ImageRequest::current_pixel_density`? + // https://drafts.csswg.org/css-images-4/#the-image-resolution + let dppx = 1.0; + let width = (naturalc_size_in_dots.width as CSSFloat) / dppx; + let height = (naturalc_size_in_dots.height as CSSFloat) / dppx; + NaturalSizes::from_width_and_height(width, height) + } else { + NaturalSizes::empty() + }; let base_fragment_info = BaseFragmentInfo::new_for_node(element.opaque()); Some(Self { @@ -354,7 +355,7 @@ impl ReplacedContent { style: style.clone(), rect, clip, - image_key, + image_key: Some(image_key), }) }) .into_iter() @@ -364,7 +365,7 @@ impl ReplacedContent { style: style.clone(), rect, clip, - image_key: video.image_key, + image_key: video.as_ref().map(|video| video.image_key), })], ReplacedContentKind::IFrame(iframe) => { vec![Fragment::IFrame(IFrameFragment { @@ -403,7 +404,7 @@ impl ReplacedContent { style: style.clone(), rect, clip, - image_key, + image_key: Some(image_key), })] }, } @@ -449,6 +450,16 @@ impl ReplacedContent { ) } + pub(crate) fn default_object_size() -> PhysicalSize<Au> { + // FIXME: + // https://drafts.csswg.org/css-images/#default-object-size + // “If 300px is too wide to fit the device, UAs should use the width of + // the largest rectangle that has a 2:1 ratio and fits the device instead.” + // “height of the largest rectangle that has a 2:1 ratio, has a height not greater + // than 150px, and has a width not greater than the device width.” + PhysicalSize::new(Au::from_px(300), Au::from_px(150)) + } + /// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width> /// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height> /// @@ -464,20 +475,19 @@ impl ReplacedContent { ) -> LogicalVec2<Au> { let mode = style.writing_mode; let intrinsic_size = self.flow_relative_intrinsic_size(style); - let intrinsic_ratio = self.preferred_aspect_ratio(&containing_block.into(), style); - - let default_object_size = || { - // FIXME: - // https://drafts.csswg.org/css-images/#default-object-size - // “If 300px is too wide to fit the device, UAs should use the width of - // the largest rectangle that has a 2:1 ratio and fits the device instead.” - // “height of the largest rectangle that has a 2:1 ratio, has a height not greater - // than 150px, and has a width not greater than the device width.” - LogicalVec2::from_physical_size( - &PhysicalSize::new(Au::from_px(300), Au::from_px(150)), - mode, - ) - }; + let intrinsic_ratio = self + .preferred_aspect_ratio(&containing_block.into(), style) + .or_else(|| { + matches!(self.kind, ReplacedContentKind::Video(_)).then(|| { + let size = Self::default_object_size(); + AspectRatio::from_content_ratio( + size.width.to_f32_px() / size.height.to_f32_px(), + ) + }) + }); + + let default_object_size = + || LogicalVec2::from_physical_size(&Self::default_object_size(), mode); let get_tentative_size = |LogicalVec2 { inline, block }| -> LogicalVec2<Au> { match (inline, block) { diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index e0a15d99933..093ab9d61c9 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -177,6 +177,13 @@ impl AspectRatio { }, } } + + pub(crate) fn from_content_ratio(i_over_b: CSSFloat) -> Self { + Self { + box_sizing_adjustment: LogicalVec2::zero(), + i_over_b, + } + } } #[derive(Clone)] @@ -905,25 +912,18 @@ impl ComputedValuesExt for ComputedValues { // ratio; otherwise the box has no preferred aspect ratio. Size // calculations involving the aspect ratio work with the content box // dimensions always." - (_, PreferredRatio::None) => natural_aspect_ratio.map(|natural_ratio| AspectRatio { - i_over_b: natural_ratio, - box_sizing_adjustment: LogicalVec2::zero(), - }), + (_, PreferredRatio::None) => natural_aspect_ratio.map(AspectRatio::from_content_ratio), // "If both auto and a <ratio> are specified together, the preferred // aspect ratio is the specified ratio of width / height unless it // is a replaced element with a natural aspect ratio, in which case // that aspect ratio is used instead. In all cases, size // calculations involving the aspect ratio work with the content box // dimensions always." - (true, PreferredRatio::Ratio(preferred_ratio)) => match natural_aspect_ratio { - Some(natural_ratio) => Some(AspectRatio { - i_over_b: natural_ratio, - box_sizing_adjustment: LogicalVec2::zero(), - }), - None => Some(AspectRatio { - i_over_b: (preferred_ratio.0).0 / (preferred_ratio.1).0, - box_sizing_adjustment: LogicalVec2::zero(), - }), + (true, PreferredRatio::Ratio(preferred_ratio)) => { + Some(AspectRatio::from_content_ratio( + natural_aspect_ratio + .unwrap_or_else(|| (preferred_ratio.0).0 / (preferred_ratio.1).0), + )) }, // "The box’s preferred aspect ratio is the specified ratio of width diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d7478dd21c2..bc09d5f8fb7 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -55,6 +55,8 @@ use style::selector_parser::{ use style::shared_lock::{Locked, SharedRwLock}; use style::stylesheets::layer_rule::LayerOrder; use style::stylesheets::{CssRuleType, UrlExtraData}; +use style::values::generics::position::PreferredRatio; +use style::values::generics::ratio::Ratio; use style::values::generics::NonNegative; use style::values::{computed, specified, AtomIdent, AtomString, CSSFloat}; use style::{dom_apis, thread_state, ArcSlice, CaseSensitivityExt}; @@ -132,6 +134,7 @@ use crate::dom::htmltablesectionelement::{ }; use crate::dom::htmltemplateelement::HTMLTemplateElement; use crate::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers}; +use crate::dom::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers}; use crate::dom::mutationobserver::{Mutation, MutationObserver}; use crate::dom::namednodemap::NamedNodeMap; use crate::dom::node::{ @@ -849,6 +852,8 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> { this.get_width() } else if let Some(this) = self.downcast::<HTMLImageElement>() { this.get_width() + } else if let Some(this) = self.downcast::<HTMLVideoElement>() { + this.get_width() } else if let Some(this) = self.downcast::<HTMLTableElement>() { this.get_width() } else if let Some(this) = self.downcast::<HTMLTableCellElement>() { @@ -891,6 +896,8 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> { this.get_height() } else if let Some(this) = self.downcast::<HTMLImageElement>() { this.get_height() + } else if let Some(this) = self.downcast::<HTMLVideoElement>() { + this.get_height() } else if let Some(this) = self.downcast::<HTMLTableElement>() { this.get_height() } else if let Some(this) = self.downcast::<HTMLTableCellElement>() { @@ -927,6 +934,27 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> { }, } + // Aspect ratio when providing both width and height. + // https://html.spec.whatwg.org/multipage/#attributes-for-embedded-content-and-images + if self.downcast::<HTMLImageElement>().is_some() || + self.downcast::<HTMLVideoElement>().is_some() + { + if let LengthOrPercentageOrAuto::Length(width) = width { + if let LengthOrPercentageOrAuto::Length(height) = height { + let width_value = NonNegative(specified::Number::new(width.to_f32_px())); + let height_value = NonNegative(specified::Number::new(height.to_f32_px())); + let aspect_ratio = specified::position::AspectRatio { + auto: true, + ratio: PreferredRatio::Ratio(Ratio(width_value, height_value)), + }; + hints.push(from_declaration( + shared_lock, + PropertyDeclaration::AspectRatio(aspect_ratio), + )); + } + } + } + let cols = if let Some(this) = self.downcast::<HTMLTextAreaElement>() { match this.get_cols() { 0 => None, diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index dfaa895429c..8a9d095dcf7 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -27,7 +27,7 @@ use net_traits::{ ResourceTimingType, }; use pixels::Image; -use script_layout_interface::HTMLMediaData; +use script_layout_interface::MediaFrame; use servo_config::pref; use servo_media::player::audio::AudioRenderer; use servo_media::player::video::{VideoFrame, VideoFrameRenderer}; @@ -68,7 +68,7 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::DomObject; -use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom}; +use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::blob::Blob; use crate::dom::document::Document; @@ -158,7 +158,7 @@ impl FrameHolder { pub struct MediaFrameRenderer { player_id: Option<u64>, compositor_api: CrossProcessCompositorApi, - current_frame: Option<(ImageKey, i32, i32)>, + current_frame: Option<MediaFrame>, old_frame: Option<ImageKey>, very_old_frame: Option<ImageKey>, current_frame_holder: Option<FrameHolder>, @@ -179,8 +179,12 @@ impl MediaFrameRenderer { } fn render_poster_frame(&mut self, image: Arc<Image>) { - if let Some(image_id) = image.id { - self.current_frame = Some((image_id, image.width as i32, image.height as i32)); + if let Some(image_key) = image.id { + self.current_frame = Some(MediaFrame { + image_key, + width: image.width as i32, + height: image.height as i32, + }); self.show_poster = true; } } @@ -206,13 +210,14 @@ impl VideoFrameRenderer for MediaFrameRenderer { ImageDescriptorFlags::empty(), ); - match self.current_frame { - Some((ref image_key, ref mut width, ref mut height)) - if *width == frame.get_width() && *height == frame.get_height() => + match &mut self.current_frame { + Some(ref mut current_frame) + if current_frame.width == frame.get_width() && + current_frame.height == frame.get_height() => { if !frame.is_gl_texture() { updates.push(ImageUpdate::UpdateImage( - *image_key, + current_frame.image_key, descriptor, SerializableImageData::Raw(IpcSharedMemory::from_bytes(&frame.get_data())), )); @@ -226,17 +231,17 @@ impl VideoFrameRenderer for MediaFrameRenderer { updates.push(ImageUpdate::DeleteImage(old_image_key)); } }, - Some((ref mut image_key, ref mut width, ref mut height)) => { - self.old_frame = Some(*image_key); + Some(ref mut current_frame) => { + self.old_frame = Some(current_frame.image_key); let Some(new_image_key) = self.compositor_api.generate_image_key() else { return; }; /* update current_frame */ - *image_key = new_image_key; - *width = frame.get_width(); - *height = frame.get_height(); + current_frame.image_key = new_image_key; + current_frame.width = frame.get_width(); + current_frame.height = frame.get_height(); let image_data = if frame.is_gl_texture() && self.player_id.is_some() { let texture_target = if frame.is_external_oes() { @@ -264,7 +269,12 @@ impl VideoFrameRenderer for MediaFrameRenderer { let Some(image_key) = self.compositor_api.generate_image_key() else { return; }; - self.current_frame = Some((image_key, frame.get_width(), frame.get_height())); + + self.current_frame = Some(MediaFrame { + image_key, + width: frame.get_width(), + height: frame.get_height(), + }); let image_data = if frame.is_gl_texture() && self.player_id.is_some() { let texture_target = if frame.is_external_oes() { @@ -1320,6 +1330,7 @@ impl HTMLMediaElement { } // Step 6. + self.handle_resize(Some(image.width), Some(image.height)); self.video_renderer .lock() .unwrap() @@ -1584,6 +1595,10 @@ impl HTMLMediaElement { }, PlayerEvent::VideoFrameUpdated => { self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); + // Check if the frame was resized + if let Some(frame) = self.video_renderer.lock().unwrap().current_frame { + self.handle_resize(Some(frame.width as u32), Some(frame.height as u32)); + } }, PlayerEvent::MetadataUpdated(ref metadata) => { // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list @@ -1727,18 +1742,7 @@ impl HTMLMediaElement { } // Step 5. - if self.is::<HTMLVideoElement>() { - let video_elem = self.downcast::<HTMLVideoElement>().unwrap(); - if video_elem.get_video_width() != metadata.width || - video_elem.get_video_height() != metadata.height - { - video_elem.set_video_width(metadata.width); - video_elem.set_video_height(metadata.height); - let window = window_from_node(self); - let task_source = window.task_manager().media_element_task_source(); - task_source.queue_simple_event(self.upcast(), atom!("resize"), &window); - } - } + self.handle_resize(Some(metadata.width), Some(metadata.height)); // Step 6. self.change_ready_state(ReadyState::HaveMetadata); @@ -1971,6 +1975,21 @@ impl HTMLMediaElement { .map(|holder| holder.get_frame()) } + pub fn get_current_frame_data(&self) -> Option<MediaFrame> { + self.video_renderer.lock().unwrap().current_frame + } + + pub fn clear_current_frame_data(&self) { + self.handle_resize(None, None); + self.video_renderer.lock().unwrap().current_frame = None + } + + fn handle_resize(&self, width: Option<u32>, height: Option<u32>) { + if let Some(video_elem) = self.downcast::<HTMLVideoElement>() { + video_elem.resize(width, height); + } + } + /// By default the audio is rendered through the audio sink automatically /// selected by the servo-media Player instance. However, in some cases, like /// the WebAudio MediaElementAudioSourceNode, we need to set a custom audio @@ -1998,13 +2017,11 @@ impl HTMLMediaElement { self.duration.set(duration); } - /// Sets a new value for the show_poster propperty. If the poster is being hidden - /// because new frames should render, updates video_renderer to allow it. - fn set_show_poster(&self, show_poster: bool) { + /// Sets a new value for the show_poster propperty. Updates video_rederer + /// with the new value. + pub fn set_show_poster(&self, show_poster: bool) { self.show_poster.set(show_poster); - if !show_poster { - self.video_renderer.lock().unwrap().show_poster = false; - } + self.video_renderer.lock().unwrap().show_poster = show_poster; } pub fn reset(&self) { @@ -2478,6 +2495,7 @@ impl VirtualMethods for HTMLMediaElement { }, local_name!("src") => { if mutation.new_value(attr).is_none() { + self.clear_current_frame_data(); return; } self.media_element_load_algorithm(CanGc::note()); @@ -2508,23 +2526,6 @@ impl VirtualMethods for HTMLMediaElement { } } -pub trait LayoutHTMLMediaElementHelpers { - fn data(self) -> HTMLMediaData; -} - -impl LayoutHTMLMediaElementHelpers for LayoutDom<'_, HTMLMediaElement> { - fn data(self) -> HTMLMediaData { - HTMLMediaData { - current_frame: self - .unsafe_get() - .video_renderer - .lock() - .unwrap() - .current_frame, - } - } -} - #[derive(JSTraceable, MallocSizeOf)] pub enum MediaElementMicrotask { ResourceSelection { diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs index 937b4216f71..24614f5b8a0 100644 --- a/components/script/dom/htmlvideoelement.rs +++ b/components/script/dom/htmlvideoelement.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use dom_struct::dom_struct; use euclid::default::Size2D; -use html5ever::{local_name, LocalName, Prefix}; +use html5ever::{local_name, namespace_url, ns, LocalName, Prefix}; use ipc_channel::ipc; use js::rust::HandleObject; use net_traits::image_cache::{ @@ -19,8 +19,10 @@ use net_traits::{ FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ResourceFetchTiming, ResourceTimingType, }; +use script_layout_interface::{HTMLMediaData, MediaMetadata}; use servo_media::player::video::VideoFrame; use servo_url::ServoUrl; +use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use crate::document_loader::{LoadBlocker, LoadType}; use crate::dom::attr::Attr; @@ -29,10 +31,10 @@ use crate::dom::bindings::codegen::Bindings::HTMLVideoElementBinding::HTMLVideoE use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::DomObject; -use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::root::{DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; use crate::dom::document::Document; -use crate::dom::element::{AttributeMutation, Element}; +use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers}; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlmediaelement::{HTMLMediaElement, ReadyState}; use crate::dom::node::{document_from_node, window_from_node, Node}; @@ -43,16 +45,13 @@ use crate::image_listener::{generate_cache_listener_for_element, ImageCacheListe use crate::network_listener::{self, PreInvoke, ResourceTimingListener}; use crate::script_runtime::CanGc; -const DEFAULT_WIDTH: u32 = 300; -const DEFAULT_HEIGHT: u32 = 150; - #[dom_struct] pub struct HTMLVideoElement { htmlmediaelement: HTMLMediaElement, /// <https://html.spec.whatwg.org/multipage/#dom-video-videowidth> - video_width: Cell<u32>, + video_width: Cell<Option<u32>>, /// <https://html.spec.whatwg.org/multipage/#dom-video-videoheight> - video_height: Cell<u32>, + video_height: Cell<Option<u32>>, /// Incremented whenever tasks associated with this element are cancelled. generation_id: Cell<u32>, /// Poster frame fetch request canceller. @@ -64,6 +63,8 @@ pub struct HTMLVideoElement { #[ignore_malloc_size_of = "VideoFrame"] #[no_trace] last_frame: DomRefCell<Option<VideoFrame>>, + /// Indicates if it has already sent a resize event for a given size + sent_resize: Cell<Option<(u32, u32)>>, } impl HTMLVideoElement { @@ -74,12 +75,13 @@ impl HTMLVideoElement { ) -> HTMLVideoElement { HTMLVideoElement { htmlmediaelement: HTMLMediaElement::new_inherited(local_name, prefix, document), - video_width: Cell::new(DEFAULT_WIDTH), - video_height: Cell::new(DEFAULT_HEIGHT), + video_width: Cell::new(None), + video_height: Cell::new(None), generation_id: Cell::new(0), poster_frame_canceller: DomRefCell::new(Default::default()), load_blocker: Default::default(), last_frame: Default::default(), + sent_resize: Cell::new(None), } } @@ -101,20 +103,36 @@ impl HTMLVideoElement { ) } - pub fn get_video_width(&self) -> u32 { + pub fn get_video_width(&self) -> Option<u32> { self.video_width.get() } - pub fn set_video_width(&self, width: u32) { - self.video_width.set(width); - } - - pub fn get_video_height(&self) -> u32 { + pub fn get_video_height(&self) -> Option<u32> { self.video_height.get() } - pub fn set_video_height(&self, height: u32) { + /// <https://html.spec.whatwg.org/multipage#event-media-resize> + pub fn resize(&self, width: Option<u32>, height: Option<u32>) -> Option<(u32, u32)> { + self.video_width.set(width); self.video_height.set(height); + + let width = width?; + let height = height?; + if self.sent_resize.get() == Some((width, height)) { + return None; + } + + let sent_resize = if self.htmlmediaelement.get_ready_state() == ReadyState::HaveNothing { + None + } else { + let window = window_from_node(self); + let task_source = window.task_manager().media_element_task_source(); + task_source.queue_simple_event(self.upcast(), atom!("resize"), &window); + Some((width, height)) + }; + + self.sent_resize.set(sent_resize); + sent_resize } pub fn get_current_frame_data(&self) -> Option<(Option<ipc::IpcSharedMemory>, Size2D<u32>)> { @@ -228,7 +246,7 @@ impl HTMLVideoElementMethods for HTMLVideoElement { if self.htmlmediaelement.get_ready_state() == ReadyState::HaveNothing { return 0; } - self.video_width.get() + self.video_width.get().unwrap_or(0) } // https://html.spec.whatwg.org/multipage/#dom-video-videoheight @@ -236,7 +254,7 @@ impl HTMLVideoElementMethods for HTMLVideoElement { if self.htmlmediaelement.get_ready_state() == ReadyState::HaveNothing { return 0; } - self.video_height.get() + self.video_height.get().unwrap_or(0) } // https://html.spec.whatwg.org/multipage/#dom-video-poster @@ -258,10 +276,25 @@ impl VirtualMethods for HTMLVideoElement { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { self.super_type().unwrap().attribute_mutated(attr, mutation); - if let Some(new_value) = mutation.new_value(attr) { - if attr.local_name() == &local_name!("poster") { - self.fetch_poster_frame(&new_value, CanGc::note()); + if attr.local_name() == &local_name!("poster") { + if let Some(new_value) = mutation.new_value(attr) { + self.fetch_poster_frame(&new_value, CanGc::note()) + } else { + self.htmlmediaelement.clear_current_frame_data(); + self.htmlmediaelement.set_show_poster(false); } + }; + } + + fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue { + match name { + &local_name!("width") | &local_name!("height") => { + AttrValue::from_dimension(value.into()) + }, + _ => self + .super_type() + .unwrap() + .parse_plain_attribute(name, value), } } } @@ -408,3 +441,55 @@ impl PosterFrameFetchContext { } } } + +pub trait LayoutHTMLVideoElementHelpers { + fn data(self) -> HTMLMediaData; + fn get_width(self) -> LengthOrPercentageOrAuto; + fn get_height(self) -> LengthOrPercentageOrAuto; +} + +impl LayoutDom<'_, HTMLVideoElement> { + fn width_attr(self) -> Option<LengthOrPercentageOrAuto> { + self.upcast::<Element>() + .get_attr_for_layout(&ns!(), &local_name!("width")) + .map(AttrValue::as_dimension) + .cloned() + } + + fn height_attr(self) -> Option<LengthOrPercentageOrAuto> { + self.upcast::<Element>() + .get_attr_for_layout(&ns!(), &local_name!("height")) + .map(AttrValue::as_dimension) + .cloned() + } +} + +impl LayoutHTMLVideoElementHelpers for LayoutDom<'_, HTMLVideoElement> { + fn data(self) -> HTMLMediaData { + let video = self.unsafe_get(); + + // Get the current frame being rendered. + let current_frame = video.htmlmediaelement.get_current_frame_data(); + + // This value represents the natural width and height of the video. + // It may exist even if there is no current frame (for example, after the + // metadata of the video is loaded). + let metadata = video + .get_video_width() + .zip(video.get_video_height()) + .map(|(width, height)| MediaMetadata { width, height }); + + HTMLMediaData { + current_frame, + metadata, + } + } + + fn get_width(self) -> LengthOrPercentageOrAuto { + self.width_attr().unwrap_or(LengthOrPercentageOrAuto::Auto) + } + + fn get_height(self) -> LengthOrPercentageOrAuto { + self.height_attr().unwrap_or(LengthOrPercentageOrAuto::Auto) + } +} diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index b8334b9f4e9..4d3037dd55e 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -88,9 +88,9 @@ use crate::dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMe use crate::dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use crate::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; use crate::dom::htmllinkelement::HTMLLinkElement; -use crate::dom::htmlmediaelement::{HTMLMediaElement, LayoutHTMLMediaElementHelpers}; use crate::dom::htmlstyleelement::HTMLStyleElement; use crate::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers}; +use crate::dom::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers}; use crate::dom::mouseevent::MouseEvent; use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver}; use crate::dom::nodelist::NodeList; @@ -1553,7 +1553,7 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> { } fn media_data(self) -> Option<HTMLMediaData> { - self.downcast::<HTMLMediaElement>() + self.downcast::<HTMLVideoElement>() .map(|media| media.data()) } diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs index 228fd03556e..6963c98acc0 100644 --- a/components/shared/script_layout/lib.rs +++ b/components/shared/script_layout/lib.rs @@ -163,8 +163,21 @@ pub struct PendingImage { pub origin: ImmutableOrigin, } +#[derive(Clone, Copy, Debug)] +pub struct MediaFrame { + pub image_key: webrender_api::ImageKey, + pub width: i32, + pub height: i32, +} + +pub struct MediaMetadata { + pub width: u32, + pub height: u32, +} + pub struct HTMLMediaData { - pub current_frame: Option<(ImageKey, i32, i32)>, + pub current_frame: Option<MediaFrame>, + pub metadata: Option<MediaMetadata>, } pub struct LayoutConfig { diff --git a/tests/wpt/meta/css/css-content/element-replacement-on-replaced-element.tentative.html.ini b/tests/wpt/meta/css/css-content/element-replacement-on-replaced-element.tentative.html.ini deleted file mode 100644 index 7bd1c2d4164..00000000000 --- a/tests/wpt/meta/css/css-content/element-replacement-on-replaced-element.tentative.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[element-replacement-on-replaced-element.tentative.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-overflow/overflow-video.html.ini b/tests/wpt/meta/css/css-overflow/overflow-video.html.ini deleted file mode 100644 index 1d0a9d754d6..00000000000 --- a/tests/wpt/meta/css/css-overflow/overflow-video.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[overflow-video.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-replaced.html.ini b/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-replaced.html.ini index f0582a774ea..a7002aa4d58 100644 --- a/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-replaced.html.ini +++ b/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-replaced.html.ini @@ -1,16 +1,10 @@ [intrinsic-size-fallback-replaced.html] - [.test 2] - expected: FAIL - [.test 3: undefined] expected: FAIL [.test 4] expected: FAIL - [.test 6] - expected: FAIL - [.test 7: undefined] expected: FAIL diff --git a/tests/wpt/meta/html/rendering/dimension-attributes.html.ini b/tests/wpt/meta/html/rendering/dimension-attributes.html.ini index 77e01e40099..9edae9ec0d1 100644 --- a/tests/wpt/meta/html/rendering/dimension-attributes.html.ini +++ b/tests/wpt/meta/html/rendering/dimension-attributes.html.ini @@ -227,120 +227,6 @@ [<marquee height="0px"> mapping to <marquee> height property] expected: FAIL - [<video width="200"> mapping to <video> width property] - expected: FAIL - - [<video width="1007"> mapping to <video> width property] - expected: FAIL - - [<video width=" 00523 "> mapping to <video> width property] - expected: FAIL - - [<video width="200.25"> mapping to <video> width property] - expected: FAIL - - [<video width="200.7"> mapping to <video> width property] - expected: FAIL - - [<video width="200."> mapping to <video> width property] - expected: FAIL - - [<video width="200in"> mapping to <video> width property] - expected: FAIL - - [<video width="200.25in"> mapping to <video> width property] - expected: FAIL - - [<video width="200 %"> mapping to <video> width property] - expected: FAIL - - [<video width="200 abc"> mapping to <video> width property] - expected: FAIL - - [<video width="200%"> mapping to <video> width property] - expected: FAIL - - [<video width="200%abc"> mapping to <video> width property] - expected: FAIL - - [<video width="200.25%"> mapping to <video> width property] - expected: FAIL - - [<video width="200.%"> mapping to <video> width property] - expected: FAIL - - [<video width="20.25e2"> mapping to <video> width property] - expected: FAIL - - [<video width="20.25E2"> mapping to <video> width property] - expected: FAIL - - [<video width="0"> mapping to <video> width property] - expected: FAIL - - [<video width="0%"> mapping to <video> width property] - expected: FAIL - - [<video width="0px"> mapping to <video> width property] - expected: FAIL - - [<video height="200"> mapping to <video> height property] - expected: FAIL - - [<video height="1007"> mapping to <video> height property] - expected: FAIL - - [<video height=" 00523 "> mapping to <video> height property] - expected: FAIL - - [<video height="200.25"> mapping to <video> height property] - expected: FAIL - - [<video height="200.7"> mapping to <video> height property] - expected: FAIL - - [<video height="200."> mapping to <video> height property] - expected: FAIL - - [<video height="200in"> mapping to <video> height property] - expected: FAIL - - [<video height="200.25in"> mapping to <video> height property] - expected: FAIL - - [<video height="200 %"> mapping to <video> height property] - expected: FAIL - - [<video height="200 abc"> mapping to <video> height property] - expected: FAIL - - [<video height="200%"> mapping to <video> height property] - expected: FAIL - - [<video height="200%abc"> mapping to <video> height property] - expected: FAIL - - [<video height="200.25%"> mapping to <video> height property] - expected: FAIL - - [<video height="200.%"> mapping to <video> height property] - expected: FAIL - - [<video height="20.25e2"> mapping to <video> height property] - expected: FAIL - - [<video height="20.25E2"> mapping to <video> height property] - expected: FAIL - - [<video height="0"> mapping to <video> height property] - expected: FAIL - - [<video height="0%"> mapping to <video> height property] - expected: FAIL - - [<video height="0px"> mapping to <video> height property] - expected: FAIL - [<object width="200"> mapping to <object> width property] expected: FAIL diff --git a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html.ini b/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html.ini deleted file mode 100644 index f1d9d954f5c..00000000000 --- a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[img-aspect-ratio-lazy.html] - [Image width and height attributes are used to infer aspect-ratio for lazy-loaded images] - expected: FAIL diff --git a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html.ini b/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html.ini index c86bf3cd3ca..b6a9c0f3c08 100644 --- a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html.ini +++ b/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html.ini @@ -2,50 +2,20 @@ [Computed style] expected: FAIL - [Create, append and test immediately: <img> with attributes width=250, height=100] - expected: FAIL - - [Create, append and test immediately: <img> with attributes width=0.8, height=0.2] - expected: FAIL - - [Create, append and test immediately: <img> with invalid trailing attributes width=50pp height=25xx] - expected: FAIL - - [Computed style test: img with {"width":"10","height":"20"}] - expected: FAIL - [Computed style test: input with {"type":"image","width":"10","height":"20"}] expected: FAIL - [Computed style test: img with {"width":"0","height":"1"}] - expected: FAIL - [Computed style test: input with {"type":"image","width":"0","height":"1"}] expected: FAIL - [Computed style test: img with {"width":"1","height":"0"}] - expected: FAIL - [Computed style test: input with {"type":"image","width":"1","height":"0"}] expected: FAIL - [Computed style test: img with {"width":"0","height":"0"}] - expected: FAIL - [Computed style test: input with {"type":"image","width":"0","height":"0"}] expected: FAIL - [Computed style test: img with {"width":"0.5","height":"1.5"}] - expected: FAIL - [Computed style test: input with {"type":"image","width":"0.5","height":"1.5"}] expected: FAIL - [Loaded images test: <img> with width, height and empty src attributes] - expected: FAIL - - [Loaded images test: Error image with width and height attributes] - expected: FAIL - [Loaded images test: Error image with width, height and alt attributes] expected: FAIL diff --git a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html.ini b/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html.ini index b896e0912e9..5a433f19108 100644 --- a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html.ini +++ b/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html.ini @@ -8,15 +8,9 @@ [Source width/height should take precedence over img attributes.] expected: FAIL - [Make sure style gets invalidated correctly when the source gets removed.] - expected: FAIL - [If the <source> has only one of width/height, we don't get an aspect ratio, even if the <img> has both.] expected: FAIL - [If we don't have width/height on the source, we fall back to width/height on the <img>.] - expected: FAIL - [If we only have one width/height attribute, we should get that attribute mapped but no aspect ratio, even if <img> has attributes.] expected: FAIL diff --git a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html.ini b/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html.ini deleted file mode 100644 index 91492a24a22..00000000000 --- a/tests/wpt/meta/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html.ini +++ /dev/null @@ -1,24 +0,0 @@ -[video-aspect-ratio.html] - [Video width and height attributes are not used to infer aspect-ratio] - expected: FAIL - - [Computed style] - expected: FAIL - - [Computed style test: video with {"width":"10","height":"20"}] - expected: FAIL - - [Computed style test: video with {"width":"0.5","height":"1.5"}] - expected: FAIL - - [Computed style test: video with {"width":"0","height":"1"}] - expected: FAIL - - [Computed style test: video with {"width":"1","height":"0"}] - expected: FAIL - - [Computed style test: video with {"width":"0","height":"0"}] - expected: FAIL - - [Video width and height attributes are used to infer aspect-ratio] - expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/image-loading-lazy-slow-aspect-ratio.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-img-element/image-loading-lazy-slow-aspect-ratio.html.ini deleted file mode 100644 index b63c1b1d0d3..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/image-loading-lazy-slow-aspect-ratio.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[image-loading-lazy-slow-aspect-ratio.html] - expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm.ini b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm.ini deleted file mode 100644 index db806d2f7dc..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm.ini +++ /dev/null @@ -1,15 +0,0 @@ -[intrinsic_sizes.htm] - [default object size is 300x150] - expected: FAIL - - [default height is half the width] - expected: FAIL - - [default width is twice the height] - expected: FAIL - - [default object size after src is removed] - expected: FAIL - - [default object size after poster is removed] - expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/resize-during-playback.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/resize-during-playback.html.ini index b1efee1da4b..b8abf202ffa 100644 --- a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/resize-during-playback.html.ini +++ b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/resize-during-playback.html.ini @@ -1,6 +1,3 @@ [resize-during-playback.html] - [webm video] - expected: FAIL - [mp4 video] expected: PRECONDITION_FAILED diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_content_image.htm.ini b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_content_image.htm.ini deleted file mode 100644 index aff443ebe1e..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_content_image.htm.ini +++ /dev/null @@ -1,2 +0,0 @@ -[video_content_image.htm] - expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_content_text.htm.ini b/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_content_text.htm.ini deleted file mode 100644 index f1f13b23181..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-video-element/video_content_text.htm.ini +++ /dev/null @@ -1,2 +0,0 @@ -[video_content_text.htm] - expected: FAIL |