mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
🐛 Fix nested shadows clipping
This commit is contained in:
committed by
Belén Albeza
parent
d9ab28e6ed
commit
e3b87390f6
@@ -383,6 +383,15 @@ impl RenderState {
|
||||
Self::blur_from_variance(total)
|
||||
}
|
||||
|
||||
fn frame_clip_layer_blur(shape: &Shape) -> Option<Blur> {
|
||||
match shape.shape_type {
|
||||
Type::Frame(_) if shape.clip() => shape.blur.filter(|blur| {
|
||||
!blur.hidden && blur.blur_type == BlurType::LayerBlur && blur.value > 0.
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs `f` with `ignore_nested_blurs` temporarily forced to `true`.
|
||||
/// Certain off-screen passes (e.g. shadow masks) must render shapes without
|
||||
/// inheriting ancestor blur. This helper guarantees the flag is restored.
|
||||
@@ -629,11 +638,21 @@ impl RenderState {
|
||||
|
||||
// We don't want to change the value in the global state
|
||||
let mut shape: Cow<Shape> = Cow::Borrowed(shape);
|
||||
let frame_has_blur = Self::frame_clip_layer_blur(&shape).is_some();
|
||||
let shape_has_blur = shape.blur.is_some();
|
||||
|
||||
if !self.ignore_nested_blurs {
|
||||
if self.ignore_nested_blurs {
|
||||
if frame_has_blur && shape_has_blur {
|
||||
shape.to_mut().set_blur(None);
|
||||
}
|
||||
} else {
|
||||
if !frame_has_blur {
|
||||
if let Some(blur) = self.combined_layer_blur(shape.blur) {
|
||||
shape.to_mut().set_blur(Some(blur));
|
||||
}
|
||||
} else if shape_has_blur {
|
||||
shape.to_mut().set_blur(None);
|
||||
}
|
||||
}
|
||||
|
||||
let center = shape.center();
|
||||
@@ -1081,6 +1100,16 @@ impl RenderState {
|
||||
paint.set_blend_mode(element.blend_mode().into());
|
||||
paint.set_alpha_f(element.opacity());
|
||||
|
||||
if let Some(frame_blur) = Self::frame_clip_layer_blur(element) {
|
||||
let scale = self.get_scale();
|
||||
let sigma = frame_blur.value * scale;
|
||||
if let Some(filter) =
|
||||
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||
{
|
||||
paint.set_image_filter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
// 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/
|
||||
@@ -1389,7 +1418,7 @@ impl RenderState {
|
||||
let mut iteration = 0;
|
||||
let mut is_empty = true;
|
||||
|
||||
while let Some(mut node_render_state) = self.pending_nodes.pop() {
|
||||
while let Some(node_render_state) = self.pending_nodes.pop() {
|
||||
let node_id = node_render_state.id;
|
||||
let visited_children = node_render_state.visited_children;
|
||||
let visited_mask = node_render_state.visited_mask;
|
||||
@@ -1632,6 +1661,9 @@ impl RenderState {
|
||||
}
|
||||
|
||||
match element.shape_type {
|
||||
Type::Frame(_) if Self::frame_clip_layer_blur(element).is_some() => {
|
||||
self.nested_blurs.push(None);
|
||||
}
|
||||
Type::Frame(_) | Type::Group(_) => {
|
||||
self.nested_blurs.push(element.blur);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user