aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/display_list
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/display_list')
-rw-r--r--components/layout/display_list/background.rs18
-rw-r--r--components/layout/display_list/mod.rs60
-rw-r--r--components/layout/display_list/stacking_context.rs31
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