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

Have transforms and filters be CBs for all descendants in layout_2020 #25862

Merged
merged 1 commit into from Mar 2, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Have transforms and filters be CBs for all descendants in layout_2020

This is a feature that was never properly implemented in the previous
layout system. We still need to preserve their in-tree order in the
display list though.
  • Loading branch information
mrobinson committed Mar 2, 2020
commit 8de55695e48bf894aa64f85afb532ae5bf117455
@@ -37,7 +37,12 @@ type ItemTag = (u64, u16);
type HitInfo = Option<ItemTag>;

pub struct DisplayListBuilder<'a> {
/// The current SpatialId and ClipId information for this `DisplayListBuilder`.
current_space_and_clip: wr::SpaceAndClipInfo,

/// The id of the nearest ancestor reference frame for this `DisplayListBuilder`.
nearest_reference_frame: wr::SpatialId,

This comment has been minimized.

Copy link
@pcwalton

pcwalton Feb 28, 2020

Contributor

What is a reference frame defined as? A quick Google search doesn't pull up that term in a CSS spec.

This comment has been minimized.

Copy link
@mrobinson

mrobinson Mar 2, 2020

Author Member

The reference frame is a concept from WebRender. Essentially it is the thing that does transformations and starts new coordinate systems.


pub context: &'a LayoutContext<'a>,
pub wr: wr::DisplayListBuilder,

@@ -56,6 +61,7 @@ impl<'a> DisplayListBuilder<'a> {
) -> Self {
Self {
current_space_and_clip: wr::SpaceAndClipInfo::root_scroll(pipeline_id),
nearest_reference_frame: wr::SpatialId::root_reference_frame(pipeline_id),
is_contentful: false,
context,
wr: wr::DisplayListBuilder::new(pipeline_id, viewport_size),
@@ -68,9 +74,14 @@ impl<'a> DisplayListBuilder<'a> {
}

fn clipping_and_scrolling_scope<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
let previous = self.current_space_and_clip;
let previous_space_and_clip = self.current_space_and_clip;
let previous_nearest_reference_frame = self.nearest_reference_frame;

let result = f(self);
self.current_space_and_clip = previous;

self.current_space_and_clip = previous_space_and_clip;
self.nearest_reference_frame = previous_nearest_reference_frame;

result
}
}
@@ -6,6 +6,7 @@ use crate::display_list::conversions::ToWebRender;
use crate::display_list::DisplayListBuilder;
use crate::fragments::{AnonymousFragment, BoxFragment, Fragment};
use crate::geom::PhysicalRect;
use crate::style_ext::ComputedValuesExt;
use euclid::default::Rect;
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
use std::cmp::Ordering;
@@ -14,7 +15,6 @@ use style::computed_values::float::T as ComputedFloat;
use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
use style::computed_values::overflow_x::T as ComputedOverflow;
use style::computed_values::position::T as ComputedPosition;
use style::computed_values::transform_style::T as ComputedTransformStyle;
use style::values::computed::Length;
use style::values::generics::box_::Perspective;
use style::values::generics::transform;
@@ -96,7 +96,7 @@ impl<'a> StackingContext<'a> {

fn z_index(&self) -> i32 {
match self.initializing_fragment {
Some(fragment) => fragment.effective_z_index(),
Some(fragment) => fragment.style.effective_z_index(),
None => 0,
}
}
@@ -259,7 +259,7 @@ impl Fragment {

impl BoxFragment {
fn get_stacking_context_type(&self) -> Option<StackingContextType> {
if self.establishes_stacking_context() {
if self.style.establishes_stacking_context() {
return Some(StackingContextType::Real);
}

@@ -291,68 +291,6 @@ impl BoxFragment {
StackingContextSection::BlockBackgroundsAndBorders
}

/// Returns true if this fragment establishes a new stacking context and false otherwise.
fn establishes_stacking_context(&self) -> bool {
let effects = self.style.get_effects();
if effects.opacity != 1.0 {
return true;
}

if effects.mix_blend_mode != ComputedMixBlendMode::Normal {
return true;
}

if self.has_transform_or_perspective() {
return true;
}

if !self.style.get_effects().filter.0.is_empty() {
return true;
}

if self.style.get_box().transform_style == ComputedTransformStyle::Preserve3d ||
self.style.overrides_transform_style()
{
return true;
}

// Fixed position and sticky position always create stacking contexts.
// TODO(mrobinson): We need to handle sticky positioning here when we support it.
if self.style.get_box().position == ComputedPosition::Fixed {
return true;
}

// Statically positioned fragments don't establish stacking contexts if the previous
// conditions are not fulfilled. Furthermore, z-index doesn't apply to statically
// positioned fragments.
if self.style.get_box().position == ComputedPosition::Static {
return false;
}

// For absolutely and relatively positioned fragments we only establish a stacking
// context if there is a z-index set.
// See https://www.w3.org/TR/CSS2/visuren.html#z-index
!self.style.get_position().z_index.is_auto()
}

// Get the effective z-index of this fragment. Z-indices only apply to positioned element
// per CSS 2 9.9.1 (http://www.w3.org/TR/CSS2/visuren.html#z-index), so this value may differ
// from the value specified in the style.
fn effective_z_index(&self) -> i32 {
match self.style.get_box().position {
ComputedPosition::Static => {},
_ => return self.style.get_position().z_index.integer_or(0),
}

0
}

/// Returns true if this fragment has a transform, or perspective property set.
fn has_transform_or_perspective(&self) -> bool {
!self.style.get_box().transform.0.is_empty() ||
self.style.get_box().perspective != Perspective::None
}

fn build_stacking_context_tree<'a>(
&'a self,
fragment: &'a Fragment,
@@ -452,8 +390,7 @@ impl BoxFragment {
// TODO(mrobinson): Eventually this should use the spatial id of the reference
// frame that is the parent of this one once we have full support for stacking
// contexts and transforms.
builder.current_space_and_clip.spatial_id =
wr::SpatialId::root_reference_frame(builder.wr.pipeline_id);
builder.current_space_and_clip.spatial_id = builder.nearest_reference_frame;
}

fn build_scroll_frame_if_necessary(
@@ -505,7 +442,7 @@ impl BoxFragment {
builder: &mut DisplayListBuilder,
border_rect: &PhysicalRect<Length>,
) -> bool {
if !self.has_transform_or_perspective() {
if !self.style.has_transform_or_perspective() {
return false;
}
let untyped_border_rect = border_rect.to_untyped();
@@ -535,6 +472,7 @@ impl BoxFragment {
wr::PropertyBinding::Value(reference_frame_transform),
reference_frame_kind,
);
builder.nearest_reference_frame = builder.current_space_and_clip.spatial_id;
true
}

@@ -223,7 +223,8 @@ fn layout_block_level_children<'a>(
})
.collect()
} else {
let has_positioned_ancestor = positioning_context.has_positioned_ancestor();
let collects_for_nearest_positioned_ancestor =
positioning_context.collects_for_nearest_positioned_ancestor();
let mut fragments = child_boxes
.par_iter()
.enumerate()
@@ -238,7 +239,7 @@ fn layout_block_level_children<'a>(
/* float_context = */ None,
)
},
|| PositioningContext::new_for_rayon(has_positioned_ancestor),
|| PositioningContext::new_for_rayon(collects_for_nearest_positioned_ancestor),
PositioningContext::append,
)
.collect();
@@ -275,7 +276,7 @@ impl BlockLevelBox {
tag,
style,
contents,
} => Fragment::Box(positioning_context.for_maybe_position_relative(
} => Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
layout_context,
containing_block,
style,
@@ -293,7 +294,7 @@ impl BlockLevelBox {
},
)),
BlockLevelBox::Independent(contents) => {
Fragment::Box(positioning_context.for_maybe_position_relative(
Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
layout_context,
containing_block,
&contents.style,
@@ -326,8 +327,7 @@ impl BlockLevelBox {
))
},
BlockLevelBox::OutOfFlowFloatBox(_box_) => {
// FIXME: call for_maybe_position_relative here
// TODO
// FIXME: call layout_maybe_position_relative_fragment here
Fragment::Anonymous(AnonymousFragment::no_op(
containing_block.style.writing_mode,
))
@@ -137,15 +137,16 @@ impl BoxTreeRoot {
};

let dummy_tree_rank = 0;
let mut positioning_context = PositioningContext::new_for_initial_containing_block();
let mut positioning_context =
PositioningContext::new_for_containing_block_for_all_descendants();
let mut independent_layout = self.0.layout(
layout_context,
&mut positioning_context,
&(&initial_containing_block).into(),
dummy_tree_rank,
);

positioning_context.layout_in_initial_containing_block(
positioning_context.layout_initial_containing_block_children(
layout_context,
&initial_containing_block,
&mut independent_layout.fragments,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.