From 57704b04816d7851dd484077ca3156c5f198b755 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 17 Aug 2017 11:44:19 +0200 Subject: [PATCH] Improve containing block creation for position:absolute flows Instead of only promoting flows with positioned fragments to containing blocks, also do this for flows which have the transform, perspective or filter properties set. This is what the spec requires and also fixes some failing tests. It will allow us to stop creating stacking contexts for overflow:hidden and overflow:scroll flows. Fixes #18091. --- components/layout/block.rs | 29 ++++++++++++------- components/layout/flex.rs | 8 +++++ components/layout/flow.rs | 13 ++++----- components/layout/fragment.rs | 22 +++++++------- components/layout/list_item.rs | 4 +++ components/layout/multicol.rs | 16 ++++++++++ components/layout/table_caption.rs | 8 +++++ components/layout/table_cell.rs | 8 +++++ components/layout/table_row.rs | 8 +++++ components/layout/table_rowgroup.rs | 8 +++++ .../html/transform-abspos-001.htm.ini | 3 -- .../html/transform-abspos-004.htm.ini | 3 -- tests/wpt/mozilla/meta/MANIFEST.json | 4 +-- .../tests/css/translate_clip_nested.html | 9 +++++- .../tests/css/translate_clip_nested_ref.html | 7 ++--- 15 files changed, 107 insertions(+), 43 deletions(-) delete mode 100644 tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-001.htm.ini delete mode 100644 tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-004.htm.ini diff --git a/components/layout/block.rs b/components/layout/block.rs index e0dcc4b68c7..d868e1fe914 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -448,20 +448,16 @@ pub struct AbsoluteAssignBSizesTraversal<'a>(pub &'a SharedStyleContext<'a>); impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> { #[inline] fn process(&self, flow: &mut Flow) { - { - // The root of the absolute flow tree is definitely not absolutely - // positioned. Nothing to process here. - let flow: &Flow = flow; - if flow.contains_roots_of_absolute_flow_tree() { - return; - } - if !flow.is_block_like() { - return - } + if !flow.is_block_like() { + return } + // This flow might not be an absolutely positioned flow if it is the root of the tree. let block = flow.as_mut_block(); - debug_assert!(block.base.flags.contains(IS_ABSOLUTELY_POSITIONED)); + if !block.base.flags.contains(IS_ABSOLUTELY_POSITIONED) { + return; + } + if !block.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) { return } @@ -2106,6 +2102,17 @@ impl Flow for BlockFlow { (self.fragment.border_box - self.fragment.style().logical_border_width()).size } + /// Returns true if this flow contains fragments that are roots of an absolute flow tree. + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.contains_relatively_positioned_fragments() || self.is_root() || + self.fragment.has_filter_transform_or_perspective() + } + + /// Returns true if this is an absolute containing block. + fn is_absolute_containing_block(&self) -> bool { + self.contains_positioned_fragments() || self.fragment.has_filter_transform_or_perspective() + } + fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) && self.fragment.style().logical_position().inline_start == diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 92f23e9b7fb..24a377483d1 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -981,6 +981,14 @@ impl Flow for FlexFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } diff --git a/components/layout/flow.rs b/components/layout/flow.rs index d4716fb02a9..b683dd0d2d1 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -407,6 +407,11 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { self.contains_positioned_fragments() } + /// Returns true if this flow contains fragments that are roots of an absolute flow tree. + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.contains_relatively_positioned_fragments() || self.is_root() + } + /// Updates the inline position of a child flow during the assign-height traversal. At present, /// this is only used for absolutely-positioned inline-blocks. fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au); @@ -502,9 +507,6 @@ pub trait ImmutableFlowUtils { /// Returns true if this flow is one of table-related flows. fn is_table_kind(self) -> bool; - /// Returns true if this flow contains fragments that are roots of an absolute flow tree. - fn contains_roots_of_absolute_flow_tree(&self) -> bool; - /// Returns true if this flow has no children. fn is_leaf(self) -> bool; @@ -1198,11 +1200,6 @@ impl<'a> ImmutableFlowUtils for &'a Flow { } } - /// Returns true if this flow contains fragments that are roots of an absolute flow tree. - fn contains_roots_of_absolute_flow_tree(&self) -> bool { - self.contains_relatively_positioned_fragments() || self.is_root() - } - /// Returns true if this flow has no children. fn is_leaf(self) -> bool { base(self).children.is_empty() diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index f4928262e99..fb3fd23b613 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -2487,6 +2487,13 @@ impl Fragment { stacking_relative_border_box.size.height - border_padding.vertical())) } + /// Returns true if this fragment has a filter, transform, or perspective property set. + pub fn has_filter_transform_or_perspective(&self) -> bool { + self.style().get_box().transform.0.is_some() || + !self.style().get_effects().filter.0.is_empty() || + self.style().get_box().perspective != Either::Second(values::None_) + } + /// Returns true if this fragment establishes a new stacking context and false otherwise. pub fn establishes_stacking_context(&self) -> bool { // Text fragments shouldn't create stacking contexts. @@ -2500,22 +2507,17 @@ impl Fragment { if self.style().get_effects().opacity != 1.0 { return true } - if !self.style().get_effects().filter.0.is_empty() { - return true - } + if self.style().get_effects().mix_blend_mode != mix_blend_mode::T::normal { return true } - if self.style().get_box().transform.0.is_some() || - self.style().get_box().transform_style == transform_style::T::preserve_3d || - self.style().overrides_transform_style() { - return true + if self.has_filter_transform_or_perspective() { + return true; } - // TODO(mrobinson): Determine if this is necessary, since blocks with - // transformations already create stacking contexts. - if let Either::First(ref _length) = self.style().get_box().perspective { + if self.style().get_box().transform_style == transform_style::T::preserve_3d || + self.style().overrides_transform_style() { return true } diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 8f3f017f513..22d2f8786d0 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -127,6 +127,10 @@ impl Flow for ListItemFlow { self.block_flow.place_float_if_applicable() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + fn is_absolute_containing_block(&self) -> bool { self.block_flow.is_absolute_containing_block() } diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 6ebe48d78d0..3e7cb66c2c9 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -201,6 +201,14 @@ impl Flow for MulticolFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } @@ -283,6 +291,14 @@ impl Flow for MulticolColumnFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index 6fc188ce71a..8e5fa302028 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -91,6 +91,14 @@ impl Flow for TableCaptionFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index db92b71f078..0a19adb2430 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -271,6 +271,14 @@ impl Flow for TableCellFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 3c2eaf25d62..5536c103b0e 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -489,6 +489,14 @@ impl Flow for TableRowFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 2ca1862004a..760a20a72fc 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -194,6 +194,14 @@ impl Flow for TableRowGroupFlow { self.block_flow.compute_overflow() } + fn contains_roots_of_absolute_flow_tree(&self) -> bool { + self.block_flow.contains_roots_of_absolute_flow_tree() + } + + fn is_absolute_containing_block(&self) -> bool { + self.block_flow.is_absolute_containing_block() + } + fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { self.block_flow.generated_containing_block_size(flow) } diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-001.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-001.htm.ini deleted file mode 100644 index b492b96c13f..00000000000 --- a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-001.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transform-abspos-001.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-004.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-004.htm.ini deleted file mode 100644 index 466f0337c0b..00000000000 --- a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-abspos-004.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transform-abspos-004.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index a17f094b697..3e492f1050e 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -26120,11 +26120,11 @@ "reftest" ], "css/translate_clip_nested.html": [ - "319619a3ae8d8d1f935fedfecf41f895cb205033", + "11adf8b4fa7c3176b002b32f8309c12bfb40043d", "reftest" ], "css/translate_clip_nested_ref.html": [ - "2f0dc9fe89d71550e1acc76865e950bbb9f2db79", + "7481c266d32dc59034490a89321e45a86b47bb1b", "support" ], "css/translate_clip_ref.html": [ diff --git a/tests/wpt/mozilla/tests/css/translate_clip_nested.html b/tests/wpt/mozilla/tests/css/translate_clip_nested.html index fc3baf2affd..2b6296cc048 100644 --- a/tests/wpt/mozilla/tests/css/translate_clip_nested.html +++ b/tests/wpt/mozilla/tests/css/translate_clip_nested.html @@ -10,7 +10,14 @@
- 1 2 3 4 5 6 7 8 9 10 11 12 13 +
+
+
+ + +
+
+
diff --git a/tests/wpt/mozilla/tests/css/translate_clip_nested_ref.html b/tests/wpt/mozilla/tests/css/translate_clip_nested_ref.html index 4ae8afe85d4..edaef9186ce 100644 --- a/tests/wpt/mozilla/tests/css/translate_clip_nested_ref.html +++ b/tests/wpt/mozilla/tests/css/translate_clip_nested_ref.html @@ -6,8 +6,5 @@ width: 200px; } -
-
- 1 2 3 4 5 6 7 8 9 10 11 12 13 -
-
+
+