Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve containing block creation for position:absolute flows #18123

Merged
merged 1 commit into from Aug 18, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

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.
  • Loading branch information
mrobinson committed Aug 17, 2017
commit 57704b04816d7851dd484077ca3156c5f198b755
@@ -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 ==
@@ -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<Au> {
self.block_flow.generated_containing_block_size(flow)
}
@@ -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()
@@ -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
}

@@ -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()
}
@@ -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<Au> {
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<Au> {
self.block_flow.generated_containing_block_size(flow)
}
@@ -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<Au> {
self.block_flow.generated_containing_block_size(flow)
}
@@ -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<Au> {
self.block_flow.generated_containing_block_size(flow)
}
@@ -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<Au> {
self.block_flow.generated_containing_block_size(flow)
}
@@ -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<Au> {
self.block_flow.generated_containing_block_size(flow)
}

This file was deleted.

This file was deleted.

"reftest"
],
"css/translate_clip_nested.html": [
"319619a3ae8d8d1f935fedfecf41f895cb205033",
"11adf8b4fa7c3176b002b32f8309c12bfb40043d",
"reftest"
],
"css/translate_clip_nested_ref.html": [
"2f0dc9fe89d71550e1acc76865e950bbb9f2db79",
"7481c266d32dc59034490a89321e45a86b47bb1b",
"support"
],
"css/translate_clip_ref.html": [
@@ -10,7 +10,14 @@
<div style="position: relative; overflow: hidden; background: red;">
<div style="transform: translateX(-100px);">
<div style="position: absolute; right: -100px; background: green;">
1 2 3 4 5 6 7 8 9 10 11 12 13
</div>
</div>
</div>

<!-- Repeat the same test, but this time make the outer div a stacking context. -->
<div style="position: relative; z-index: 1; overflow: hidden; background: red;">
<div style="transform: translateX(-100px);">
<div style="position: absolute; right: -100px; background: green;">
</div>
</div>
</div>
@@ -6,8 +6,5 @@
width: 200px;
}
</style>
<div style="position: relative; overflow: hidden; background: red;">
<div style="position: absolute; right: 0; background: green;">
1 2 3 4 5 6 7 8 9 10 11 12 13
</div>
</div>
<div style="position: relative; overflow: hidden; background: green;"> </div>
<div style="position: relative; overflow: hidden; background: green;"> </div>
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.