LibWeb: Call saveLayer() after applying matrix in PushStackingContext

This is required because bounding rect used in `saveLayer()` is computed
in stacking context's coordinate space.

Fixes regression introduced in ba2926f
This commit is contained in:
Aliaksandr Kalenik 2025-09-25 03:02:50 +02:00 committed by Alexander Kalenik
parent 892e75ddfb
commit 90432f35d5
3 changed files with 44 additions and 5 deletions

View File

@ -211,6 +211,11 @@ void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& com
.translate(-command.transform.origin);
auto matrix = to_skia_matrix(new_transform);
surface().canvas().save();
if (command.clip_path.has_value())
canvas.clipPath(to_skia_path(command.clip_path.value()), true);
canvas.concat(matrix);
if (command.opacity < 1 || command.compositing_and_blending_operator != Gfx::CompositingAndBlendingOperator::Normal || command.isolate) {
SkPaint paint;
paint.setAlphaf(command.opacity);
@ -218,6 +223,8 @@ void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& com
if (command.bounding_rect.has_value()) {
auto bounds = to_skia_rect(command.bounding_rect.value());
// NOTE: saveLayer() is invoked after transform matrix application because bounding rect is computed
// in stacking context's coordinate space.
canvas.saveLayer(bounds, &paint);
} else {
canvas.saveLayer(nullptr, &paint);
@ -225,15 +232,13 @@ void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& com
} else {
canvas.save();
}
if (command.clip_path.has_value())
canvas.clipPath(to_skia_path(command.clip_path.value()), true);
canvas.concat(matrix);
}
void DisplayListPlayerSkia::pop_stacking_context(PopStackingContext const&)
{
// Restore corresponding for save() for transform and clip path application
surface().canvas().restore();
// Restore corresponding for saveLayer() required for opacity/blending/isolate
surface().canvas().restore();
}

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<style>
#outer {
position: relative;
}
#inner {
top: 100px;
left: 100px;
width: 100px;
height: 100px;
opacity: 0.5;
position: relative;
background-color: green;
}
</style>
<div id="outer">
<div id="inner"></div>
</div>

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<link rel="match" href="../expected/transform-and-opacity-ref.html" />
<style>
#outer {
opacity: 0.5;
transform: translate(100px, 100px);
}
#inner {
width: 100px;
height: 100px;
background-color: green;
}
</style>
<div id="outer">
<div id="inner"></div>
</div>