diff options
Diffstat (limited to 'components/layout/display_list')
-rw-r--r-- | components/layout/display_list/background.rs | 18 | ||||
-rw-r--r-- | components/layout/display_list/mod.rs | 60 | ||||
-rw-r--r-- | components/layout/display_list/stacking_context.rs | 31 |
3 files changed, 52 insertions, 57 deletions
diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs index 563bce28450..f1099fdab2b 100644 --- a/components/layout/display_list/background.rs +++ b/components/layout/display_list/background.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use app_units::Au; -use euclid::{Point2D, Size2D, Vector2D}; +use euclid::{Size2D, Vector2D}; use style::computed_values::background_attachment::SingleComputedValue as BackgroundAttachment; use style::computed_values::background_clip::single_value::T as Clip; use style::computed_values::background_origin::single_value::T as Origin; @@ -15,7 +15,6 @@ use style::values::specified::background::{ }; use webrender_api::{self as wr, units}; use wr::ClipChainId; -use wr::units::LayoutSize; use crate::replaced::NaturalSizes; @@ -66,8 +65,7 @@ impl<'a> BackgroundPainter<'a> { if &BackgroundAttachment::Fixed == get_cyclic(&background.background_attachment.0, layer_index) { - let viewport_size = builder.compositor_info.viewport_size; - return units::LayoutRect::from_origin_and_size(Point2D::origin(), viewport_size); + return builder.compositor_info.viewport_size.into(); } match get_cyclic(&background.background_clip.0, layer_index) { @@ -132,6 +130,7 @@ impl<'a> BackgroundPainter<'a> { pub(super) fn positioning_area( &self, fragment_builder: &'a super::BuilderForBoxFragment, + builder: &mut super::DisplayListBuilder, layer_index: usize, ) -> units::LayoutRect { if let Some(positioning_area_override) = self.positioning_area_override { @@ -150,14 +149,7 @@ impl<'a> BackgroundPainter<'a> { Origin::PaddingBox => *fragment_builder.padding_rect(), Origin::BorderBox => fragment_builder.border_rect, }, - BackgroundAttachment::Fixed => { - // This isn't the viewport size because that rects larger than the viewport might be - // transformed down into areas smaller than the viewport. - units::LayoutRect::from_origin_and_size( - Point2D::origin(), - LayoutSize::new(f32::MAX, f32::MAX), - ) - }, + BackgroundAttachment::Fixed => builder.compositor_info.viewport_size.into(), } } } @@ -170,7 +162,7 @@ pub(super) fn layout_layer( natural_sizes: NaturalSizes, ) -> Option<BackgroundLayer> { let painting_area = painter.painting_area(fragment_builder, builder, layer_index); - let positioning_area = painter.positioning_area(fragment_builder, layer_index); + let positioning_area = painter.positioning_area(fragment_builder, builder, layer_index); let common = painter.common_properties(fragment_builder, builder, layer_index, painting_area); // https://drafts.csswg.org/css-backgrounds/#background-size diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs index 3716ff35b2c..0659a8b3b3b 100644 --- a/components/layout/display_list/mod.rs +++ b/components/layout/display_list/mod.rs @@ -14,6 +14,7 @@ use embedder_traits::Cursor; use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit, Vector2D}; use fonts::GlyphStore; use gradient::WebRenderGradient; +use net_traits::image_cache::Image as CachedImage; use range::Range as ServoRange; use servo_arc::Arc as ServoArc; use servo_config::opts::DebugOptions; @@ -37,7 +38,7 @@ use style::values::generics::rect::Rect; use style::values::specified::text::TextDecorationLine; use style::values::specified::ui::CursorKind; use style_traits::CSSPixel; -use webrender_api::units::{DevicePixel, LayoutPixel, LayoutRect, LayoutSize}; +use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel, LayoutRect, LayoutSize}; use webrender_api::{ self as wr, BorderDetails, BoxShadowClipMode, BuiltDisplayList, ClipChainId, ClipMode, CommonItemProperties, ComplexClipRegion, ImageRendering, NinePatchBorder, @@ -68,12 +69,6 @@ mod stacking_context; use background::BackgroundPainter; pub use stacking_context::*; -#[derive(Clone, Copy)] -pub struct WebRenderImageInfo { - pub size: Size2D<u32, UnknownUnit>, - pub key: Option<wr::ImageKey>, -} - // webrender's `ItemTag` is private. type ItemTag = (u64, u16); type HitInfo = Option<ItemTag>; @@ -1280,20 +1275,41 @@ impl<'a> BuilderForBoxFragment<'a> { }, } }, - Ok(ResolvedImage::Image(image_info)) => { + Ok(ResolvedImage::Image { image, size }) => { // FIXME: https://drafts.csswg.org/css-images-4/#the-image-resolution let dppx = 1.0; - let intrinsic = NaturalSizes::from_width_and_height( - image_info.size.width as f32 / dppx, - image_info.size.height as f32 / dppx, - ); - let Some(image_key) = image_info.key else { + let intrinsic = + NaturalSizes::from_width_and_height(size.width / dppx, size.height / dppx); + let layer = background::layout_layer(self, painter, builder, index, intrinsic); + let image_wr_key = match image { + CachedImage::Raster(raster_image) => raster_image.id, + CachedImage::Vector(vector_image) => { + let scale = builder.context.shared_context().device_pixel_ratio().0; + let default_size: DeviceIntSize = + Size2D::new(size.width * scale, size.height * scale).to_i32(); + let layer_size = layer.as_ref().map(|layer| { + Size2D::new( + layer.tile_size.width * scale, + layer.tile_size.height * scale, + ) + .to_i32() + }); + + node.and_then(|node| { + let size = layer_size.unwrap_or(default_size); + builder + .context + .rasterize_vector_image(vector_image.id, size, node) + }) + .and_then(|rasterized_image| rasterized_image.id) + }, + }; + + let Some(image_key) = image_wr_key else { continue; }; - if let Some(layer) = - background::layout_layer(self, painter, builder, index, intrinsic) - { + if let Some(layer) = layer { if layer.repeat { builder.wr().push_repeating_image( &layer.common, @@ -1469,13 +1485,17 @@ impl<'a> BuilderForBoxFragment<'a> { .resolve_image(node, &border.border_image_source) { Err(_) => return false, - Ok(ResolvedImage::Image(image_info)) => { - let Some(key) = image_info.key else { + Ok(ResolvedImage::Image { image, size }) => { + let Some(image) = image.as_raster_image() else { + return false; + }; + + let Some(key) = image.id else { return false; }; - width = image_info.size.width as f32; - height = image_info.size.height as f32; + width = size.width; + height = size.height; NinePatchBorderSource::Image(key, ImageRendering::Auto) }, Ok(ResolvedImage::Gradient(gradient)) => { diff --git a/components/layout/display_list/stacking_context.rs b/components/layout/display_list/stacking_context.rs index d22a2b6656a..66d8421e5f7 100644 --- a/components/layout/display_list/stacking_context.rs +++ b/components/layout/display_list/stacking_context.rs @@ -834,16 +834,6 @@ impl Fragment { _ => text_decorations, }; - // If this fragment has a transform applied that makes it take up no space - // then we don't need to create any stacking contexts for it. - let has_non_invertible_transform = fragment - .has_non_invertible_transform_or_zero_scale( - &containing_block.rect.to_untyped(), - ); - if has_non_invertible_transform { - return; - } - fragment.build_stacking_context_tree( fragment_clone, stacking_context_tree, @@ -991,6 +981,13 @@ impl BoxFragment { }, }; + // <https://drafts.csswg.org/css-transforms/#transform-function-lists> + // > If a transform function causes the current transformation matrix of an object + // > to be non-invertible, the object and its content do not get displayed. + if !reference_frame_data.transform.is_invertible() { + return; + } + let new_spatial_id = stacking_context_tree.push_reference_frame( reference_frame_data.origin.to_webrender(), &containing_block.scroll_node_id, @@ -1622,15 +1619,6 @@ impl BoxFragment { }) } - /// Returns true if the given style contains a transform that is not invertible. - fn has_non_invertible_transform_or_zero_scale(&self, containing_block: &Rect<Au>) -> bool { - let list = &self.style.get_box().transform; - match list.to_transform_3d_matrix(Some(&au_rect_to_length_rect(containing_block))) { - Ok(t) => !t.0.is_invertible() || t.0.m11 == 0. || t.0.m22 == 0., - Err(_) => false, - } - } - /// Returns the 4D matrix representing this fragment's transform. pub fn calculate_transform_matrix(&self, border_rect: &Rect<Au>) -> Option<LayoutTransform> { let list = &self.style.get_box().transform; @@ -1660,11 +1648,6 @@ impl BoxFragment { .then_rotate(rotate.0, rotate.1, rotate.2, angle) .then_scale(scale.0, scale.1, scale.2) .then(&translation); - // WebRender will end up dividing by the scale value of this transform, so we - // want to ensure we don't feed it a divisor of 0. - if transform.m11 == 0. || transform.m22 == 0. { - return Some(LayoutTransform::identity()); - } let transform_origin = &self.style.get_box().transform_origin; let transform_origin_x = transform_origin |