aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/fragment_tree/containing_block.rs
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2025-04-19 12:17:03 +0200
committerGitHub <noreply@github.com>2025-04-19 10:17:03 +0000
commit7787cab521ccc6b4d8533ebe9b45563046e0463d (patch)
treed1277fa3846f24cc99859310da3d7f099c73bfc5 /components/layout/fragment_tree/containing_block.rs
parent3ab5b8c4472129798b63cfb40b63ae672763b653 (diff)
downloadservo-7787cab521ccc6b4d8533ebe9b45563046e0463d.tar.gz
servo-7787cab521ccc6b4d8533ebe9b45563046e0463d.zip
layout: Combine `layout_2020` and `layout_thread_2020` into a crate called `layout` (#36613)
Now that legacy layout has been removed, the name `layout_2020` doesn't make much sense any longer, also it's 2025 now for better or worse. The split between the "layout thread" and "layout" also doesn't make as much sense since layout doesn't run on it's own thread. There's a possibility that it will in the future, but that should be something that the user of the crate controls rather than layout iself. This is part of the larger layout interface cleanup and optimization that @Looriool and I are doing. Testing: Covered by existing tests as this is just code movement. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/layout/fragment_tree/containing_block.rs')
-rw-r--r--components/layout/fragment_tree/containing_block.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/components/layout/fragment_tree/containing_block.rs b/components/layout/fragment_tree/containing_block.rs
new file mode 100644
index 00000000000..6edd9bb379b
--- /dev/null
+++ b/components/layout/fragment_tree/containing_block.rs
@@ -0,0 +1,101 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use style::computed_values::position::T as ComputedPosition;
+
+use crate::fragment_tree::Fragment;
+
+/// A data structure used to track the containing block when recursing
+/// through the Fragment tree. It tracks the three types of containing
+/// blocks (for all descendants, for absolute and fixed position
+/// descendants, and for fixed position descendants).
+pub(crate) struct ContainingBlockManager<'a, T> {
+ /// The containing block for all non-absolute descendants. "...if the element's
+ /// position is 'relative' or 'static', the containing block is formed by the
+ /// content edge of the nearest block container ancestor box." This is also
+ /// the case for 'position: sticky' elements.
+ /// <https://www.w3.org/TR/CSS2/visudet.html#containing-block-details>
+ pub for_non_absolute_descendants: &'a T,
+
+ /// The containing block for absolute descendants. "If the element has
+ /// 'position: absolute', the containing block is
+ /// established by the nearest ancestor with a 'position' of 'absolute',
+ /// 'relative' or 'fixed', in the following way:
+ /// 1. In the case that the ancestor is an inline element, the containing
+ /// block is the bounding box around the padding boxes of the first and the
+ /// last inline boxes generated for that element. In CSS 2.1, if the inline
+ /// element is split across multiple lines, the containing block is
+ /// undefined.
+ /// 2. Otherwise, the containing block is formed by the padding edge of the
+ /// ancestor.
+ ///
+ /// <https://www.w3.org/TR/CSS2/visudet.html#containing-block-details>
+ /// If the ancestor forms a containing block for all descendants (see below),
+ /// this value will be None and absolute descendants will use the containing
+ /// block for fixed descendants.
+ pub for_absolute_descendants: Option<&'a T>,
+
+ /// The containing block for fixed and absolute descendants.
+ /// "For elements whose layout is governed by the CSS box model, any value
+ /// other than none for the transform property also causes the element to
+ /// establish a containing block for all descendants. Its padding box will be
+ /// used to layout for all of its absolute-position descendants,
+ /// fixed-position descendants, and descendant fixed background attachments."
+ /// <https://w3c.github.io/csswg-drafts/css-transforms-1/#containing-block-for-all-descendants>
+ /// See `ComputedValues::establishes_containing_block_for_all_descendants`
+ /// for a list of conditions where an element forms a containing block for
+ /// all descendants.
+ pub for_absolute_and_fixed_descendants: &'a T,
+}
+
+impl<'a, T> ContainingBlockManager<'a, T> {
+ pub(crate) fn get_containing_block_for_fragment(&self, fragment: &Fragment) -> &T {
+ if let Fragment::Box(box_fragment) = fragment {
+ match box_fragment.borrow().style.clone_position() {
+ ComputedPosition::Fixed => self.for_absolute_and_fixed_descendants,
+ ComputedPosition::Absolute => self
+ .for_absolute_descendants
+ .unwrap_or(self.for_absolute_and_fixed_descendants),
+ _ => self.for_non_absolute_descendants,
+ }
+ } else {
+ self.for_non_absolute_descendants
+ }
+ }
+
+ pub(crate) fn new_for_non_absolute_descendants(
+ &self,
+ for_non_absolute_descendants: &'a T,
+ ) -> Self {
+ ContainingBlockManager {
+ for_non_absolute_descendants,
+ for_absolute_descendants: self.for_absolute_descendants,
+ for_absolute_and_fixed_descendants: self.for_absolute_and_fixed_descendants,
+ }
+ }
+
+ pub(crate) fn new_for_absolute_descendants(
+ &self,
+ for_non_absolute_descendants: &'a T,
+ for_absolute_descendants: &'a T,
+ ) -> Self {
+ ContainingBlockManager {
+ for_non_absolute_descendants,
+ for_absolute_descendants: Some(for_absolute_descendants),
+ for_absolute_and_fixed_descendants: self.for_absolute_and_fixed_descendants,
+ }
+ }
+
+ pub(crate) fn new_for_absolute_and_fixed_descendants(
+ &self,
+ for_non_absolute_descendants: &'a T,
+ for_absolute_and_fixed_descendants: &'a T,
+ ) -> Self {
+ ContainingBlockManager {
+ for_non_absolute_descendants,
+ for_absolute_descendants: None,
+ for_absolute_and_fixed_descendants,
+ }
+ }
+}