mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-31 06:38:22 +00:00
LibWeb: Don't clip descendants outside stacking context root rect
Skia allows you to pass a bounding rect to its saveLayer() function as an optimization when you know that you won't paint outside those bounds. Unfortunately, we were passing a too-small rectangle that didn't take into account transformed descendants, etc. For now, simply pass null instead of a bounding rect. This way, Skia figures it out internally. It may allocate larger temporary bitmaps than needed this way, but at least we get more correct results. I've left re-enabling the optimization as a FIXME in the code. This fixes unwanted clipping in various parts of the Discord UI.
This commit is contained in:
parent
b1c3ce807b
commit
b4435bd50c
Notes:
github-actions[bot]
2025-07-24 15:17:25 +00:00
Author: https://github.com/awesomekling
Commit: b4435bd50c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5588
Reviewed-by: https://github.com/kalenikaliaksandr ✅
7 changed files with 29 additions and 11 deletions
|
@ -130,15 +130,12 @@ struct PushStackingContext {
|
||||||
float opacity;
|
float opacity;
|
||||||
Gfx::CompositingAndBlendingOperator compositing_and_blending_operator;
|
Gfx::CompositingAndBlendingOperator compositing_and_blending_operator;
|
||||||
bool isolate;
|
bool isolate;
|
||||||
// The bounding box of the source paintable (pre-transform).
|
|
||||||
Gfx::IntRect source_paintable_rect;
|
|
||||||
// A translation to be applied after the stacking context has been transformed.
|
// A translation to be applied after the stacking context has been transformed.
|
||||||
StackingContextTransform transform;
|
StackingContextTransform transform;
|
||||||
Optional<Gfx::Path> clip_path = {};
|
Optional<Gfx::Path> clip_path = {};
|
||||||
|
|
||||||
void translate_by(Gfx::IntPoint const& offset)
|
void translate_by(Gfx::IntPoint const& offset)
|
||||||
{
|
{
|
||||||
source_paintable_rect.translate_by(offset);
|
|
||||||
transform.origin.translate_by(offset.to_type<float>());
|
transform.origin.translate_by(offset.to_type<float>());
|
||||||
if (clip_path.has_value()) {
|
if (clip_path.has_value()) {
|
||||||
clip_path.value().transform(Gfx::AffineTransform().translate(offset.to_type<float>()));
|
clip_path.value().transform(Gfx::AffineTransform().translate(offset.to_type<float>()));
|
||||||
|
|
|
@ -211,14 +211,13 @@ void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& com
|
||||||
auto matrix = to_skia_matrix(new_transform);
|
auto matrix = to_skia_matrix(new_transform);
|
||||||
|
|
||||||
if (command.opacity < 1 || command.compositing_and_blending_operator != Gfx::CompositingAndBlendingOperator::Normal || command.isolate) {
|
if (command.opacity < 1 || command.compositing_and_blending_operator != Gfx::CompositingAndBlendingOperator::Normal || command.isolate) {
|
||||||
auto source_paintable_rect = to_skia_rect(command.source_paintable_rect);
|
|
||||||
SkRect dest;
|
|
||||||
matrix.mapRect(&dest, source_paintable_rect);
|
|
||||||
|
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setAlphaf(command.opacity);
|
paint.setAlphaf(command.opacity);
|
||||||
paint.setBlender(Gfx::to_skia_blender(command.compositing_and_blending_operator));
|
paint.setBlender(Gfx::to_skia_blender(command.compositing_and_blending_operator));
|
||||||
canvas.saveLayer(&dest, &paint);
|
|
||||||
|
// FIXME: If we knew the bounds of the stacking context including any transformed descendants etc,
|
||||||
|
// we could use saveLayer with a bounds rect. For now, we pass nullptr and let Skia figure it out.
|
||||||
|
canvas.saveLayer(nullptr, &paint);
|
||||||
} else {
|
} else {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,7 +330,6 @@ void DisplayListRecorder::push_stacking_context(PushStackingContextParams params
|
||||||
.opacity = params.opacity,
|
.opacity = params.opacity,
|
||||||
.compositing_and_blending_operator = params.compositing_and_blending_operator,
|
.compositing_and_blending_operator = params.compositing_and_blending_operator,
|
||||||
.isolate = params.isolate,
|
.isolate = params.isolate,
|
||||||
.source_paintable_rect = params.source_paintable_rect,
|
|
||||||
.transform = {
|
.transform = {
|
||||||
.origin = params.transform.origin,
|
.origin = params.transform.origin,
|
||||||
.matrix = params.transform.matrix,
|
.matrix = params.transform.matrix,
|
||||||
|
|
|
@ -124,7 +124,6 @@ public:
|
||||||
Gfx::CompositingAndBlendingOperator compositing_and_blending_operator;
|
Gfx::CompositingAndBlendingOperator compositing_and_blending_operator;
|
||||||
bool isolate;
|
bool isolate;
|
||||||
bool is_fixed_position;
|
bool is_fixed_position;
|
||||||
Gfx::IntRect source_paintable_rect;
|
|
||||||
StackingContextTransform transform;
|
StackingContextTransform transform;
|
||||||
Optional<Gfx::Path> clip_path = {};
|
Optional<Gfx::Path> clip_path = {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -324,7 +324,6 @@ void StackingContext::paint(PaintContext& context) const
|
||||||
.compositing_and_blending_operator = compositing_and_blending_operator,
|
.compositing_and_blending_operator = compositing_and_blending_operator,
|
||||||
.isolate = paintable_box().computed_values().isolation() == CSS::Isolation::Isolate,
|
.isolate = paintable_box().computed_values().isolation() == CSS::Isolation::Isolate,
|
||||||
.is_fixed_position = paintable_box().is_fixed_position(),
|
.is_fixed_position = paintable_box().is_fixed_position(),
|
||||||
.source_paintable_rect = source_paintable_rect,
|
|
||||||
.transform = {
|
.transform = {
|
||||||
.origin = transform_origin.scaled(to_device_pixels_scale),
|
.origin = transform_origin.scaled(to_device_pixels_scale),
|
||||||
.matrix = matrix_with_scaled_translation(transform_matrix, to_device_pixels_scale),
|
.matrix = matrix_with_scaled_translation(transform_matrix, to_device_pixels_scale),
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!doctype html><style>
|
||||||
|
html {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: red;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
translate: 30px 30px;
|
||||||
|
}
|
||||||
|
</style><body>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!doctype html>
|
||||||
|
<link rel="match" href="../../expected/css/stacking-context-with-unclipped-transformed-descendant-ref.html" />
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
isolation: isolate;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color: red;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
translate: 30px 30px;
|
||||||
|
}
|
||||||
|
</style><body>
|
Loading…
Add table
Add a link
Reference in a new issue