mirror of
https://github.com/servo/servo.git
synced 2025-06-12 18:34:39 +00:00
Fix transform assertion failures in Layout 2013 and Layout 2020 (#30713)
Layout asserts that it never creates stacking contexts that have a zero scale, yet it doesn't prevent the creation of those stacking contexts. This change stops their creation at an earlier stage. Fixes #30118.
This commit is contained in:
parent
1915032f66
commit
72cb34dc3d
8 changed files with 19 additions and 17 deletions
|
@ -1573,7 +1573,7 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this fragment takes up no space, we don't need to build any display items for it.
|
// If this fragment takes up no space, we don't need to build any display items for it.
|
||||||
if self.has_non_invertible_transform() {
|
if self.has_non_invertible_transform_or_zero_scale() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2419,7 +2419,7 @@ impl BlockFlow {
|
||||||
flags: StackingContextCollectionFlags,
|
flags: StackingContextCollectionFlags,
|
||||||
) {
|
) {
|
||||||
// This block flow produces no stacking contexts if it takes up no space.
|
// This block flow produces no stacking contexts if it takes up no space.
|
||||||
if self.has_non_invertible_transform() {
|
if self.has_non_invertible_transform_or_zero_scale() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ 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 {
|
fn has_non_invertible_transform_or_zero_scale(&self) -> bool {
|
||||||
if !self.class().is_block_like() ||
|
if !self.class().is_block_like() ||
|
||||||
self.as_block()
|
self.as_block()
|
||||||
.fragment
|
.fragment
|
||||||
|
@ -290,7 +290,9 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.as_block().fragment.has_non_invertible_transform()
|
self.as_block()
|
||||||
|
.fragment
|
||||||
|
.has_non_invertible_transform_or_zero_scale()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_overflow_in_parent_coordinates(&self) -> Overflow {
|
fn get_overflow_in_parent_coordinates(&self) -> Overflow {
|
||||||
|
@ -1176,7 +1178,7 @@ 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() {
|
if !kid.has_non_invertible_transform_or_zero_scale() {
|
||||||
kid.collect_stacking_contexts(state);
|
kid.collect_stacking_contexts(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2760,9 +2760,11 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this fragment has a transform applied that causes it to take up no space.
|
/// 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 {
|
pub fn has_non_invertible_transform_or_zero_scale(&self) -> bool {
|
||||||
self.transform_matrix(&Rect::default())
|
self.transform_matrix(&Rect::default())
|
||||||
.map_or(false, |matrix| !matrix.is_invertible())
|
.map_or(false, |matrix| {
|
||||||
|
!matrix.is_invertible() || matrix.m11 == 0. || matrix.m22 == 0.
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
|
|
|
@ -1882,7 +1882,7 @@ impl Flow for InlineFlow {
|
||||||
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
|
// 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.
|
// applied that causes it to take up no space, we can skip it entirely.
|
||||||
if fragment.has_non_invertible_transform() {
|
if fragment.has_non_invertible_transform_or_zero_scale() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
|
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
|
||||||
|
|
|
@ -345,7 +345,7 @@ 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() {
|
if flow.has_non_invertible_transform_or_zero_scale() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -787,8 +787,10 @@ impl Fragment {
|
||||||
|
|
||||||
// If this fragment has a transform applied that makes it take up no space
|
// If this fragment has a transform applied that makes it take up no space
|
||||||
// then we don't need to create any stacking contexts for it.
|
// then we don't need to create any stacking contexts for it.
|
||||||
let has_non_invertible_transform =
|
let has_non_invertible_transform = fragment
|
||||||
fragment.has_non_invertible_transform(&containing_block.rect.to_untyped());
|
.has_non_invertible_transform_or_zero_scale(
|
||||||
|
&containing_block.rect.to_untyped(),
|
||||||
|
);
|
||||||
if has_non_invertible_transform {
|
if has_non_invertible_transform {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1258,10 +1260,10 @@ impl BoxFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the given style contains a transform that is not invertible.
|
/// Returns true if the given style contains a transform that is not invertible.
|
||||||
fn has_non_invertible_transform(&self, containing_block: &Rect<Length>) -> bool {
|
fn has_non_invertible_transform_or_zero_scale(&self, containing_block: &Rect<Length>) -> bool {
|
||||||
let list = &self.style.get_box().transform;
|
let list = &self.style.get_box().transform;
|
||||||
match list.to_transform_3d_matrix(Some(containing_block)) {
|
match list.to_transform_3d_matrix(Some(containing_block)) {
|
||||||
Ok(t) => !t.0.is_invertible(),
|
Ok(t) => !t.0.is_invertible() || t.0.m11 == 0. || t.0.m22 == 0.,
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[preserve3d-scene-001.html]
|
|
||||||
expected: CRASH
|
|
|
@ -1,2 +0,0 @@
|
||||||
[preserve3d-scene-002.html]
|
|
||||||
expected: CRASH
|
|
Loading…
Add table
Add a link
Reference in a new issue