🐛 Fix mask erros on save/restore optimizations

This commit is contained in:
Alejandro Alonso 2026-01-13 19:27:34 +01:00
parent 4a8e02987f
commit d593e299e3
2 changed files with 15 additions and 17 deletions

View File

@ -1172,12 +1172,22 @@ impl RenderState {
self.nested_fills.push(Vec::new());
}
// When we're rendering the mask shape we need to set a special blend mode
// called 'destination-in' that keeps the drawn content within the mask.
// @see https://skia.org/docs/user/api/skblendmode_overview/
if mask {
let mut mask_paint = skia::Paint::default();
mask_paint.set_blend_mode(skia::BlendMode::DstIn);
let mask_rec = skia::canvas::SaveLayerRec::default().paint(&mask_paint);
self.surfaces
.canvas(SurfaceId::Current)
.save_layer(&mask_rec);
}
// Only create save_layer if actually needed
// For simple shapes with default opacity and blend mode, skip expensive save_layer
// Groups with masks need a layer to properly handle the mask rendering
let needs_layer = element.needs_layer()
|| (matches!(element.shape_type, Type::Group(g) if g.masked))
|| mask;
let needs_layer = element.needs_layer();
if needs_layer {
let mut paint = skia::Paint::default();
@ -1192,18 +1202,6 @@ impl RenderState {
}
}
// When we're rendering the mask shape we need to set a special blend mode
// called 'destination-in' that keeps the drawn content within the mask.
// @see https://skia.org/docs/user/api/skblendmode_overview/
if mask {
let mut mask_paint = skia::Paint::default();
mask_paint.set_blend_mode(skia::BlendMode::DstIn);
let mask_rec = skia::canvas::SaveLayerRec::default().paint(&mask_paint);
self.surfaces
.canvas(SurfaceId::Current)
.save_layer(&mask_rec);
}
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint);
self.surfaces
.canvas(SurfaceId::Current)
@ -1283,8 +1281,7 @@ impl RenderState {
// Only restore if we created a layer (optimization for simple shapes)
// Groups with masks need restore to properly handle the mask rendering
let needs_layer =
element.needs_layer() || (matches!(element.shape_type, Type::Group(g) if g.masked));
let needs_layer = element.needs_layer();
if needs_layer {
self.surfaces.canvas(SurfaceId::Current).restore();

View File

@ -1485,6 +1485,7 @@ impl Shape {
self.opacity() < 1.0
|| self.blend_mode().0 != skia::BlendMode::SrcOver
|| self.has_frame_clip_layer_blur()
|| (matches!(self.shape_type, Type::Group(g) if g.masked))
}
/// Checks if this frame has clip layer blur (affects children)