aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/fragment_tree
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2025-04-25 22:25:10 +0200
committerGitHub <noreply@github.com>2025-04-25 20:25:10 +0000
commita62f0eaf0a7bfdea47e6132f9042d4b3adb6d3e3 (patch)
treebdb1d0492a07f613c5baa1b6194c915db05e1b91 /components/layout/fragment_tree
parent69605d05cfab21824d8ab4777cb371cae38aaeb6 (diff)
downloadservo-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.rs5
-rw-r--r--components/layout/fragment_tree/box_fragment.rs8
-rw-r--r--components/layout/fragment_tree/fragment.rs11
-rw-r--r--components/layout/fragment_tree/positioning_fragment.rs14
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\