aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEuclid Ye <yezhizhenjiakang@gmail.com>2025-03-03 05:44:59 +0800
committerGitHub <noreply@github.com>2025-03-02 21:44:59 +0000
commit28cea920ec6ab2f3f5f29f2dd0791e516aafa612 (patch)
tree12457b81fb17cb69786b3017dd83ed8e4a2850db
parentb56a3caea0af61465f352a52621cd56355f5a3d5 (diff)
downloadservo-28cea920ec6ab2f3f5f29f2dd0791e516aafa612.tar.gz
servo-28cea920ec6ab2f3f5f29f2dd0791e516aafa612.zip
layout: Merge `BoxFragment::used_overflow` into `ComputedValuesExt::effective_overflow` (#35670) (#35670)
* Update wpt-test * Merge used_overflow to effective_overflow; remove duplicate call * Remove more duplicate calls; update effective_overflow logic * Update reference link&style * Apply final review suggestions Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
-rw-r--r--components/layout_2020/display_list/stacking_context.rs23
-rw-r--r--components/layout_2020/flexbox/layout.rs2
-rw-r--r--components/layout_2020/flow/construct.rs7
-rw-r--r--components/layout_2020/flow/root.rs22
-rw-r--r--components/layout_2020/fragment_tree/box_fragment.rs8
-rw-r--r--components/layout_2020/style_ext.rs37
-rw-r--r--tests/wpt/meta/css/css-overflow/overflow-img-display-table.html.ini2
7 files changed, 54 insertions, 47 deletions
diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs
index 2affc4702c1..be0f46769b5 100644
--- a/components/layout_2020/display_list/stacking_context.rs
+++ b/components/layout_2020/display_list/stacking_context.rs
@@ -39,7 +39,7 @@ use crate::fragment_tree::{
PositioningFragment, SpecificLayoutInfo,
};
use crate::geom::{AuOrAuto, PhysicalRect, PhysicalSides};
-use crate::style_ext::{AxesOverflow, ComputedValuesExt};
+use crate::style_ext::ComputedValuesExt;
#[derive(Clone)]
pub(crate) struct ContainingBlock {
@@ -1372,23 +1372,6 @@ impl BoxFragment {
Some(display_list.define_clip_chain(*parent_clip_chain_id, [clip_id]))
}
- // TODO: merge this function with style.effective_overflow()
- fn used_overflow(&self) -> AxesOverflow {
- let mut overflow = self.style.effective_overflow();
- let is_replaced_element = self.base.flags.contains(FragmentFlags::IS_REPLACED);
-
- if is_replaced_element {
- if overflow.x != ComputedOverflow::Visible {
- overflow.x = ComputedOverflow::Clip;
- }
- if overflow.y != ComputedOverflow::Visible {
- overflow.y = ComputedOverflow::Clip;
- }
- }
-
- overflow
- }
-
fn build_overflow_frame_if_necessary(
&self,
display_list: &mut DisplayList,
@@ -1396,7 +1379,7 @@ impl BoxFragment {
parent_clip_chain_id: &wr::ClipChainId,
containing_block_rect: &PhysicalRect<Au>,
) -> Option<OverflowFrameData> {
- let overflow = self.used_overflow();
+ let overflow = self.style.effective_overflow(self.base.flags);
if overflow.x == ComputedOverflow::Visible && overflow.y == ComputedOverflow::Visible {
return None;
@@ -1483,8 +1466,6 @@ impl BoxFragment {
display_list.wr.pipeline_id,
);
- let overflow = self.style.effective_overflow();
-
let sensitivity = AxesScrollSensitivity {
x: overflow.x.into(),
y: overflow.y.into(),
diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs
index 4546a90346c..cd05aa62d77 100644
--- a/components/layout_2020/flexbox/layout.rs
+++ b/components/layout_2020/flexbox/layout.rs
@@ -2510,7 +2510,7 @@ impl FlexItemBox {
) -> Au {
// FIXME(stshine): Consider more situations when auto min size is not needed.
let style = &self.independent_formatting_context.style();
- if style.establishes_scroll_container() {
+ if style.establishes_scroll_container(self.base_fragment_info().flags) {
return Au::zero();
}
diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs
index f458c5713dc..6c52d23a20d 100644
--- a/components/layout_2020/flow/construct.rs
+++ b/components/layout_2020/flow/construct.rs
@@ -25,6 +25,7 @@ use crate::dom_traversal::{
use crate::flow::float::FloatBox;
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
use crate::formatting_contexts::IndependentFormattingContext;
+use crate::fragment_tree::FragmentFlags;
use crate::layout_box_base::LayoutBoxBase;
use crate::positioned::AbsolutelyPositionedBox;
use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside};
@@ -493,7 +494,11 @@ where
let kind = match contents {
Contents::NonReplaced(contents) => match display_inside {
DisplayInside::Flow { is_list_item }
- if !info.style.establishes_block_formatting_context() =>
+ // Fragment flags are just used to indicate that the element is not replaced, so empty
+ // flags are okay here.
+ if !info.style.establishes_block_formatting_context(
+ FragmentFlags::empty()
+ ) =>
{
BlockLevelCreator::SameFormattingContextBlock(
IntermediateBlockContainer::Deferred {
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index 430ec10b0d0..55c47589a4d 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -54,7 +54,7 @@ impl BoxTree {
// Zero box for `:root { display: none }`, one for the root element otherwise.
assert!(boxes.len() <= 1);
- // From https://drafts.csswg.org/css-overflow/#overflow-propagation:
+ // From https://www.w3.org/TR/css-overflow-3/#overflow-propagation:
// > UAs must apply the overflow-* values set on the root element to the viewport when the
// > root element’s display value is not none. However, when the root element is an [HTML]
// > html element (including XML syntax for HTML) whose overflow value is visible (in both
@@ -63,10 +63,11 @@ impl BoxTree {
// > element to the viewport. The element from which the value is propagated must then have a
// > used overflow value of visible.
let root_style = root_element.style(context);
- let root_overflow = root_style.effective_overflow();
- let mut viewport_overflow = root_overflow;
- if root_overflow.x == Overflow::Visible &&
- root_overflow.y == Overflow::Visible &&
+
+ let mut viewport_overflow_x = root_style.clone_overflow_x();
+ let mut viewport_overflow_y = root_style.clone_overflow_y();
+ if viewport_overflow_x == Overflow::Visible &&
+ viewport_overflow_y == Overflow::Visible &&
!root_style.get_box().display.is_none()
{
for child in iter_child_nodes(root_element) {
@@ -80,7 +81,9 @@ impl BoxTree {
let style = child.style(context);
if !style.get_box().display.is_none() {
- viewport_overflow = style.effective_overflow();
+ viewport_overflow_x = style.clone_overflow_x();
+ viewport_overflow_y = style.clone_overflow_y();
+
break;
}
}
@@ -94,9 +97,12 @@ impl BoxTree {
contains_floats,
},
canvas_background: CanvasBackground::for_root_element(context, root_element),
+ // From https://www.w3.org/TR/css-overflow-3/#overflow-propagation:
+ // > If visible is applied to the viewport, it must be interpreted as auto.
+ // > If clip is applied to the viewport, it must be interpreted as hidden.
viewport_scroll_sensitivity: AxesScrollSensitivity {
- x: viewport_overflow.x.to_scrollable().into(),
- y: viewport_overflow.y.to_scrollable().into(),
+ x: viewport_overflow_x.to_scrollable().into(),
+ y: viewport_overflow_y.to_scrollable().into(),
},
}
}
diff --git a/components/layout_2020/fragment_tree/box_fragment.rs b/components/layout_2020/fragment_tree/box_fragment.rs
index 13ca0f270ae..50353677ff8 100644
--- a/components/layout_2020/fragment_tree/box_fragment.rs
+++ b/components/layout_2020/fragment_tree/box_fragment.rs
@@ -154,7 +154,7 @@ impl BoxFragment {
//
// This applies even if there is no baseline set, so we unconditionally set the value here
// and ignore anything that is set via [`Self::with_baselines`].
- if self.style.establishes_scroll_container() {
+ if self.style.establishes_scroll_container(self.base.flags) {
let content_rect_size = self.content_rect.size.to_logical(writing_mode);
let padding = self.padding.to_logical(writing_mode);
let border = self.border.to_logical(writing_mode);
@@ -228,7 +228,7 @@ impl BoxFragment {
self.clearance,
self.scrollable_overflow(),
self.baselines,
- self.style.effective_overflow(),
+ self.style.effective_overflow(self.base.flags),
));
for child in &self.children {
@@ -239,7 +239,7 @@ impl BoxFragment {
pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
let mut overflow = self.border_rect();
- if self.style.establishes_scroll_container() {
+ if self.style.establishes_scroll_container(self.base.flags) {
return overflow;
}
@@ -251,7 +251,7 @@ impl BoxFragment {
overflow.max_y().max(scrollable_overflow.max_y()),
);
- let overflow_style = self.style.effective_overflow();
+ let overflow_style = self.style.effective_overflow(self.base.flags);
if overflow_style.y == ComputedOverflow::Visible {
overflow.origin.y = overflow.origin.y.min(scrollable_overflow.origin.y);
overflow.size.height = bottom_right.y - overflow.origin.y;
diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs
index 5a0b46f06f8..faf1b142109 100644
--- a/components/layout_2020/style_ext.rs
+++ b/components/layout_2020/style_ext.rs
@@ -285,10 +285,10 @@ pub(crate) trait ComputedValuesExt {
) -> LogicalSides<LengthPercentageOrAuto<'_>>;
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool;
fn effective_z_index(&self, fragment_flags: FragmentFlags) -> i32;
- fn effective_overflow(&self) -> AxesOverflow;
- fn establishes_block_formatting_context(&self) -> bool;
+ fn effective_overflow(&self, fragment_flags: FragmentFlags) -> AxesOverflow;
+ fn establishes_block_formatting_context(&self, fragment_flags: FragmentFlags) -> bool;
fn establishes_stacking_context(&self, fragment_flags: FragmentFlags) -> bool;
- fn establishes_scroll_container(&self) -> bool;
+ fn establishes_scroll_container(&self, fragment_flags: FragmentFlags) -> bool;
fn establishes_containing_block_for_absolute_descendants(
&self,
fragment_flags: FragmentFlags,
@@ -501,10 +501,26 @@ impl ComputedValuesExt for ComputedValues {
/// Get the effective overflow of this box. The property only applies to block containers,
/// flex containers, and grid containers. And some box types only accept a few values.
/// <https://www.w3.org/TR/css-overflow-3/#overflow-control>
- fn effective_overflow(&self) -> AxesOverflow {
+ fn effective_overflow(&self, fragment_flags: FragmentFlags) -> AxesOverflow {
let style_box = self.get_box();
- let overflow_x = style_box.overflow_x;
- let overflow_y = style_box.overflow_y;
+ let mut overflow_x = style_box.overflow_x;
+ let mut overflow_y = style_box.overflow_y;
+
+ // From <https://www.w3.org/TR/css-overflow-4/#overflow-control>:
+ // "On replaced elements, the used values of all computed values other than visible is clip."
+ if fragment_flags.contains(FragmentFlags::IS_REPLACED) {
+ if overflow_x != Overflow::Visible {
+ overflow_x = Overflow::Clip;
+ }
+ if overflow_y != Overflow::Visible {
+ overflow_y = Overflow::Clip;
+ }
+ return AxesOverflow {
+ x: overflow_x,
+ y: overflow_y,
+ };
+ }
+
let ignores_overflow = match style_box.display.inside() {
stylo::DisplayInside::Table => {
// According to <https://drafts.csswg.org/css-tables/#global-style-overrides>,
@@ -530,6 +546,7 @@ impl ComputedValuesExt for ComputedValues {
},
_ => false,
};
+
if ignores_overflow {
AxesOverflow {
x: Overflow::Visible,
@@ -545,8 +562,8 @@ impl ComputedValuesExt for ComputedValues {
/// Return true if this style is a normal block and establishes
/// a new block formatting context.
- fn establishes_block_formatting_context(&self) -> bool {
- if self.establishes_scroll_container() {
+ fn establishes_block_formatting_context(&self, fragment_flags: FragmentFlags) -> bool {
+ if self.establishes_scroll_container(fragment_flags) {
return true;
}
@@ -572,10 +589,10 @@ impl ComputedValuesExt for ComputedValues {
}
/// Whether or not the `overflow` value of this style establishes a scroll container.
- fn establishes_scroll_container(&self) -> bool {
+ fn establishes_scroll_container(&self, fragment_flags: FragmentFlags) -> bool {
// Checking one axis suffices, because the computed value ensures that
// either both axes are scrollable, or none is scrollable.
- self.effective_overflow().x.is_scrollable()
+ self.effective_overflow(fragment_flags).x.is_scrollable()
}
/// Returns true if this fragment establishes a new stacking context and false otherwise.
diff --git a/tests/wpt/meta/css/css-overflow/overflow-img-display-table.html.ini b/tests/wpt/meta/css/css-overflow/overflow-img-display-table.html.ini
deleted file mode 100644
index 1f056d52fe9..00000000000
--- a/tests/wpt/meta/css/css-overflow/overflow-img-display-table.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[overflow-img-display-table.html]
- expected: FAIL