mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
layout: Don't built stacking contexts or display lists for empty blocks.
This commit is contained in:
parent
4094d16323
commit
08427ccee5
6 changed files with 50 additions and 1 deletions
|
@ -1571,6 +1571,11 @@ impl Fragment {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this fragment takes up no space, we don't need to build any display items for it.
|
||||||
|
if self.has_non_invertible_transform() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Fragment::build_display_list at rel={:?}, abs={:?}: {:?}",
|
"Fragment::build_display_list at rel={:?}, abs={:?}: {:?}",
|
||||||
self.border_box, stacking_relative_border_box, self
|
self.border_box, stacking_relative_border_box, self
|
||||||
|
@ -2376,6 +2381,11 @@ impl BlockFlow {
|
||||||
state: &mut StackingContextCollectionState,
|
state: &mut StackingContextCollectionState,
|
||||||
flags: StackingContextCollectionFlags,
|
flags: StackingContextCollectionFlags,
|
||||||
) {
|
) {
|
||||||
|
// This block flow produces no stacking contexts if it takes up no space.
|
||||||
|
if self.has_non_invertible_transform() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut preserved_state = SavedStackingContextCollectionState::new(state);
|
let mut preserved_state = SavedStackingContextCollectionState::new(state);
|
||||||
|
|
||||||
let stacking_context_type = self.stacking_context_type(flags);
|
let stacking_context_type = self.stacking_context_type(flags);
|
||||||
|
|
|
@ -217,6 +217,12 @@ impl StackingContext {
|
||||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||||
) -> StackingContext {
|
) -> StackingContext {
|
||||||
|
if let Some(ref t) = transform {
|
||||||
|
// These are used as scale values by webrender, and it can't handle
|
||||||
|
// divisors of 0 when scaling.
|
||||||
|
assert_ne!(t.m11, 0.);
|
||||||
|
assert_ne!(t.m22, 0.);
|
||||||
|
}
|
||||||
StackingContext {
|
StackingContext {
|
||||||
id,
|
id,
|
||||||
context_type,
|
context_type,
|
||||||
|
|
|
@ -273,6 +273,22 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
|
||||||
might_have_floats_in_or_out
|
might_have_floats_in_or_out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_non_invertible_transform(&self) -> bool {
|
||||||
|
if !self.class().is_block_like() ||
|
||||||
|
self.as_block()
|
||||||
|
.fragment
|
||||||
|
.style
|
||||||
|
.get_box()
|
||||||
|
.transform
|
||||||
|
.0
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.as_block().fragment.has_non_invertible_transform()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_overflow_in_parent_coordinates(&self) -> Overflow {
|
fn get_overflow_in_parent_coordinates(&self) -> Overflow {
|
||||||
// FIXME(#2795): Get the real container size.
|
// FIXME(#2795): Get the real container size.
|
||||||
let container_size = Size2D::zero();
|
let container_size = Size2D::zero();
|
||||||
|
@ -1160,9 +1176,11 @@ impl BaseFlow {
|
||||||
state: &mut StackingContextCollectionState,
|
state: &mut StackingContextCollectionState,
|
||||||
) {
|
) {
|
||||||
for kid in self.children.iter_mut() {
|
for kid in self.children.iter_mut() {
|
||||||
|
if !kid.has_non_invertible_transform() {
|
||||||
kid.collect_stacking_contexts(state);
|
kid.collect_stacking_contexts(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn might_have_floats_in(&self) -> bool {
|
pub fn might_have_floats_in(&self) -> bool {
|
||||||
|
|
|
@ -2730,6 +2730,12 @@ impl Fragment {
|
||||||
self.style().get_box().perspective != Perspective::None
|
self.style().get_box().perspective != Perspective::None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if this fragment has a transform applied that causes it to take up no space.
|
||||||
|
pub fn has_non_invertible_transform(&self) -> bool {
|
||||||
|
self.transform_matrix(&Rect::default())
|
||||||
|
.map_or(false, |matrix| !matrix.is_invertible())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if this fragment establishes a new stacking context and false otherwise.
|
/// Returns true if this fragment establishes a new stacking context and false otherwise.
|
||||||
pub fn establishes_stacking_context(&self) -> bool {
|
pub fn establishes_stacking_context(&self) -> bool {
|
||||||
// Text fragments shouldn't create stacking contexts.
|
// Text fragments shouldn't create stacking contexts.
|
||||||
|
|
|
@ -1871,6 +1871,11 @@ impl Flow for InlineFlow {
|
||||||
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
|
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
|
||||||
|
|
||||||
for fragment in self.fragments.fragments.iter_mut() {
|
for fragment in self.fragments.fragments.iter_mut() {
|
||||||
|
// If a particular fragment would establish a stacking context but has a transform
|
||||||
|
// applied that causes it to take up no space, we can skip it entirely.
|
||||||
|
if fragment.has_non_invertible_transform() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
|
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
|
||||||
|
|
||||||
let abspos_containing_block = fragment.style.get_box().position != Position::Static;
|
let abspos_containing_block = fragment.style.get_box().position != Position::Static;
|
||||||
|
|
|
@ -346,6 +346,10 @@ pub struct BuildDisplayList<'a> {
|
||||||
impl<'a> BuildDisplayList<'a> {
|
impl<'a> BuildDisplayList<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn traverse(&mut self, flow: &mut dyn Flow) {
|
pub fn traverse(&mut self, flow: &mut dyn Flow) {
|
||||||
|
if flow.has_non_invertible_transform() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let parent_stacking_context_id = self.state.current_stacking_context_id;
|
let parent_stacking_context_id = self.state.current_stacking_context_id;
|
||||||
self.state.current_stacking_context_id = flow.base().stacking_context_id;
|
self.state.current_stacking_context_id = flow.base().stacking_context_id;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue