diff options
author | Martin Robinson <mrobinson@igalia.com> | 2025-04-25 22:25:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-25 20:25:10 +0000 |
commit | a62f0eaf0a7bfdea47e6132f9042d4b3adb6d3e3 (patch) | |
tree | bdb1d0492a07f613c5baa1b6194c915db05e1b91 /components/layout/fragment_tree | |
parent | 69605d05cfab21824d8ab4777cb371cae38aaeb6 (diff) | |
download | servo-a62f0eaf0a7bfdea47e6132f9042d4b3adb6d3e3.tar.gz servo-a62f0eaf0a7bfdea47e6132f9042d4b3adb6d3e3.zip |
layout: Use box tree `Fragment`s for offset parent queries (#36681)
This change switches `offsetParent`, `offsetLeft`, etc queries to use
the BoxTree fragments instead of walking the entire fragment tree. In
addition, fragments are stored for columns and colgroups. In general,
this greatly simplifies the flow of the query and prevents having to do
expensive tree walks.
Testing: This change is covered by newly passing WPT tests and three new
failures:
- /css/filter-effects/backdrop-filter-edge-clipping-2.html
- /css/filter-effects/backdrop-filter-edge-mirror.html
- /css/filter-effects/backdrop-filter-edge-pixels-2.html
These failures are actually progressions, because now the references
start
to render properly whereas before they did not.
Fixes: This is part of #36525 and #36665.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Diffstat (limited to 'components/layout/fragment_tree')
-rw-r--r-- | components/layout/fragment_tree/base_fragment.rs | 5 | ||||
-rw-r--r-- | components/layout/fragment_tree/box_fragment.rs | 8 | ||||
-rw-r--r-- | components/layout/fragment_tree/fragment.rs | 11 | ||||
-rw-r--r-- | components/layout/fragment_tree/positioning_fragment.rs | 14 |
4 files changed, 26 insertions, 12 deletions
diff --git a/components/layout/fragment_tree/base_fragment.rs b/components/layout/fragment_tree/base_fragment.rs index 48d672a8547..0cf6ee511cb 100644 --- a/components/layout/fragment_tree/base_fragment.rs +++ b/components/layout/fragment_tree/base_fragment.rs @@ -132,11 +132,6 @@ impl Tag { Tag { node, pseudo } } - /// Returns true if this tag is for a pseudo element. - pub(crate) fn is_pseudo(&self) -> bool { - self.pseudo.is_some() - } - pub(crate) fn to_display_list_fragment_id(self) -> u64 { combine_id_with_fragment_type(self.node.id(), self.pseudo.into()) } diff --git a/components/layout/fragment_tree/box_fragment.rs b/components/layout/fragment_tree/box_fragment.rs index 0e83c0d71a6..e87826ec3ca 100644 --- a/components/layout/fragment_tree/box_fragment.rs +++ b/components/layout/fragment_tree/box_fragment.rs @@ -212,6 +212,10 @@ impl BoxFragment { ) } + pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) { + self.cumulative_containing_block_rect = *containing_block; + } + pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> { rect.translate(self.cumulative_containing_block_rect.origin.to_vector()) } @@ -405,8 +409,4 @@ impl BoxFragment { _ => CollapsedBlockMargins::zero(), } } - - pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) { - self.cumulative_containing_block_rect = *containing_block; - } } diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs index ceccd1ec304..7708b0893ee 100644 --- a/components/layout/fragment_tree/fragment.rs +++ b/components/layout/fragment_tree/fragment.rs @@ -134,7 +134,9 @@ impl Fragment { Fragment::Float(float_fragment) => float_fragment .borrow_mut() .set_containing_block(containing_block), - Fragment::Positioning(_) => {}, + Fragment::Positioning(positioning_fragment) => positioning_fragment + .borrow_mut() + .set_containing_block(containing_block), Fragment::AbsoluteOrFixedPositioned(hoisted_shared_fragment) => { if let Some(ref fragment) = hoisted_shared_fragment.borrow().fragment { fragment.set_containing_block(containing_block); @@ -191,13 +193,16 @@ impl Fragment { } } - pub(crate) fn cumulative_content_box_rect(&self) -> Option<PhysicalRect<Au>> { + pub(crate) fn cumulative_border_box_rect(&self) -> Option<PhysicalRect<Au>> { match self { Fragment::Box(fragment) | Fragment::Float(fragment) => { let fragment = fragment.borrow(); Some(fragment.offset_by_containing_block(&fragment.border_rect())) }, - Fragment::Positioning(_) | + Fragment::Positioning(fragment) => { + let fragment = fragment.borrow(); + Some(fragment.offset_by_containing_block(&fragment.rect)) + }, Fragment::Text(_) | Fragment::AbsoluteOrFixedPositioned(_) | Fragment::Image(_) | diff --git a/components/layout/fragment_tree/positioning_fragment.rs b/components/layout/fragment_tree/positioning_fragment.rs index 853caed6709..1fe968eb484 100644 --- a/components/layout/fragment_tree/positioning_fragment.rs +++ b/components/layout/fragment_tree/positioning_fragment.rs @@ -20,12 +20,17 @@ pub(crate) struct PositioningFragment { pub base: BaseFragment, pub rect: PhysicalRect<Au>, pub children: Vec<Fragment>, + /// The scrollable overflow of this anonymous fragment's children. pub scrollable_overflow: PhysicalRect<Au>, /// If this fragment was created with a style, the style of the fragment. #[conditional_malloc_size_of] pub style: Option<ServoArc<ComputedValues>>, + + /// This [`PositioningFragment`]'s containing block rectangle in coordinates relative to + /// the initial containing block, but not taking into account any transforms. + pub cumulative_containing_block_rect: PhysicalRect<Au>, } impl PositioningFragment { @@ -61,9 +66,18 @@ impl PositioningFragment { rect, children, scrollable_overflow, + cumulative_containing_block_rect: PhysicalRect::zero(), }) } + pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) { + self.cumulative_containing_block_rect = *containing_block; + } + + pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> { + rect.translate(self.cumulative_containing_block_rect.origin.to_vector()) + } + pub fn print(&self, tree: &mut PrintTree) { tree.new_level(format!( "PositioningFragment\ |