mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
layout: Fix logic for transforms with non-invertible matrix (#37147)
When the the current transformation matrix of a box isn't invertible, the box and its content shouldn't be displayed. However, the logic was broken: - It was only checking the `transform` property, but not individual transform properties like `scale`. - It was treating matrices with m₁₁=0 or m₂₂=0 and non-invertible, even when they can still be invertible and have a visible outcome. - When m₁₁=0 or m₂₂=0 weren't caused by `transform`, it was replacing the matrix with the identity. Testing: Adding new WPT Fixes: #37146 Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
fef1dd9ea0
commit
ac06b1cfcf
4 changed files with 114 additions and 24 deletions
|
@ -834,16 +834,6 @@ impl Fragment {
|
|||
_ => text_decorations,
|
||||
};
|
||||
|
||||
// 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.
|
||||
let has_non_invertible_transform = fragment
|
||||
.has_non_invertible_transform_or_zero_scale(
|
||||
&containing_block.rect.to_untyped(),
|
||||
);
|
||||
if has_non_invertible_transform {
|
||||
return;
|
||||
}
|
||||
|
||||
fragment.build_stacking_context_tree(
|
||||
fragment_clone,
|
||||
stacking_context_tree,
|
||||
|
@ -991,6 +981,13 @@ impl BoxFragment {
|
|||
},
|
||||
};
|
||||
|
||||
// <https://drafts.csswg.org/css-transforms/#transform-function-lists>
|
||||
// > If a transform function causes the current transformation matrix of an object
|
||||
// > to be non-invertible, the object and its content do not get displayed.
|
||||
if !reference_frame_data.transform.is_invertible() {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_spatial_id = stacking_context_tree.push_reference_frame(
|
||||
reference_frame_data.origin.to_webrender(),
|
||||
&containing_block.scroll_node_id,
|
||||
|
@ -1622,15 +1619,6 @@ impl BoxFragment {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns true if the given style contains a transform that is not invertible.
|
||||
fn has_non_invertible_transform_or_zero_scale(&self, containing_block: &Rect<Au>) -> bool {
|
||||
let list = &self.style.get_box().transform;
|
||||
match list.to_transform_3d_matrix(Some(&au_rect_to_length_rect(containing_block))) {
|
||||
Ok(t) => !t.0.is_invertible() || t.0.m11 == 0. || t.0.m22 == 0.,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the 4D matrix representing this fragment's transform.
|
||||
pub fn calculate_transform_matrix(&self, border_rect: &Rect<Au>) -> Option<LayoutTransform> {
|
||||
let list = &self.style.get_box().transform;
|
||||
|
@ -1660,11 +1648,6 @@ impl BoxFragment {
|
|||
.then_rotate(rotate.0, rotate.1, rotate.2, angle)
|
||||
.then_scale(scale.0, scale.1, scale.2)
|
||||
.then(&translation);
|
||||
// WebRender will end up dividing by the scale value of this transform, so we
|
||||
// want to ensure we don't feed it a divisor of 0.
|
||||
if transform.m11 == 0. || transform.m22 == 0. {
|
||||
return Some(LayoutTransform::identity());
|
||||
}
|
||||
|
||||
let transform_origin = &self.style.get_box().transform_origin;
|
||||
let transform_origin_x = transform_origin
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue