mirror of
https://github.com/penpot/penpot.git
synced 2026-03-21 01:43:43 +00:00
Merge pull request #8659 from penpot/superlalex-fix-test-halos-big-shadows
🐛 Fix visible halos in big shadows
This commit is contained in:
@@ -23,7 +23,8 @@ pub use surfaces::{SurfaceId, Surfaces};
|
||||
|
||||
use crate::performance;
|
||||
use crate::shapes::{
|
||||
all_with_ancestors, Blur, BlurType, Corners, Fill, Shadow, Shape, SolidColor, Stroke, Type,
|
||||
all_with_ancestors, radius_to_sigma, Blur, BlurType, Corners, Fill, Shadow, Shape, SolidColor,
|
||||
Stroke, Type,
|
||||
};
|
||||
use crate::state::{ShapesPoolMutRef, ShapesPoolRef};
|
||||
use crate::tiles::{self, PendingTiles, TileRect};
|
||||
@@ -816,7 +817,7 @@ impl RenderState {
|
||||
{
|
||||
if let Some(blur) = shape.blur.filter(|b| !b.hidden) {
|
||||
shape.to_mut().set_blur(None);
|
||||
Some(blur.value)
|
||||
Some(blur.sigma())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -1437,7 +1438,7 @@ impl RenderState {
|
||||
if !self.options.is_fast_mode() {
|
||||
if let Some(frame_blur) = Self::frame_clip_layer_blur(element) {
|
||||
let scale = self.get_scale();
|
||||
let sigma = frame_blur.value * scale;
|
||||
let sigma = radius_to_sigma(frame_blur.value * scale);
|
||||
if let Some(filter) =
|
||||
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||
{
|
||||
@@ -1630,8 +1631,10 @@ impl RenderState {
|
||||
let mut plain_shape = Cow::Borrowed(shape);
|
||||
let combined_blur =
|
||||
Self::combine_blur_values(self.combined_layer_blur(shape.blur), extra_layer_blur);
|
||||
let blur_filter = combined_blur
|
||||
.and_then(|blur| skia::image_filters::blur((blur.value, blur.value), None, None, None));
|
||||
let blur_filter = combined_blur.and_then(|blur| {
|
||||
let sigma = blur.sigma();
|
||||
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||
});
|
||||
|
||||
let use_low_zoom_path = scale <= 1.0 && combined_blur.is_none();
|
||||
|
||||
@@ -1714,12 +1717,8 @@ impl RenderState {
|
||||
|
||||
// Create filter with blur only (no offset, no spread - handled geometrically)
|
||||
let blur_only_filter = if transformed_shadow.blur > 0.0 {
|
||||
Some(skia::image_filters::blur(
|
||||
(transformed_shadow.blur, transformed_shadow.blur),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
))
|
||||
let sigma = radius_to_sigma(transformed_shadow.blur);
|
||||
Some(skia::image_filters::blur((sigma, sigma), None, None, None))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ pub mod text_paths;
|
||||
mod transform;
|
||||
|
||||
pub use blend::*;
|
||||
pub use blurs::*;
|
||||
pub use blurs::{radius_to_sigma, Blur, BlurType};
|
||||
pub use bools::*;
|
||||
pub use corners::*;
|
||||
pub use fills::*;
|
||||
@@ -1004,7 +1004,8 @@ impl Shape {
|
||||
}
|
||||
}
|
||||
|
||||
let blur = skia::image_filters::blur((children_blur, children_blur), None, None, None);
|
||||
let sigma = radius_to_sigma(children_blur);
|
||||
let blur = skia::image_filters::blur((sigma, sigma), None, None, None);
|
||||
if let Some(image_filter) = blur {
|
||||
let blur_bounds = image_filter.compute_fast_bounds(rect);
|
||||
rect.join(blur_bounds);
|
||||
@@ -1236,12 +1237,10 @@ impl Shape {
|
||||
self.blur
|
||||
.filter(|blur| !blur.hidden)
|
||||
.and_then(|blur| match blur.blur_type {
|
||||
BlurType::LayerBlur => skia::image_filters::blur(
|
||||
(blur.value * scale, blur.value * scale),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
BlurType::LayerBlur => {
|
||||
let sigma = radius_to_sigma(blur.value * scale);
|
||||
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1251,7 +1250,8 @@ impl Shape {
|
||||
.filter(|blur| !blur.hidden)
|
||||
.and_then(|blur| match blur.blur_type {
|
||||
BlurType::LayerBlur => {
|
||||
skia::MaskFilter::blur(skia::BlurStyle::Normal, blur.value * scale, Some(true))
|
||||
let sigma = radius_to_sigma(blur.value * scale);
|
||||
skia::MaskFilter::blur(skia::BlurStyle::Normal, sigma, Some(true))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
/// Skia's kBLUR_SIGMA_SCALE (1/√3 ≈ 0.57735). Used to convert blur radius to sigma
|
||||
const BLUR_SIGMA_SCALE: f32 = 0.577_350_27;
|
||||
|
||||
/// Converts a blur radius to sigma (standard deviation) for Skia's blur APIs.
|
||||
/// Matches Skia's SkBlurMask::ConvertRadiusToSigma:
|
||||
#[inline]
|
||||
pub fn radius_to_sigma(radius: f32) -> f32 {
|
||||
if radius > 0.0 {
|
||||
BLUR_SIGMA_SCALE * radius + 0.5
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum BlurType {
|
||||
LayerBlur,
|
||||
@@ -22,4 +36,11 @@ impl Blur {
|
||||
pub fn scale_content(&mut self, value: f32) {
|
||||
self.value *= value;
|
||||
}
|
||||
|
||||
/// Returns the sigma (standard deviation) for Skia blur APIs.
|
||||
/// The stored `value` is a blur radius; this converts it to sigma.
|
||||
#[inline]
|
||||
pub fn sigma(&self) -> f32 {
|
||||
radius_to_sigma(self.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use skia_safe::{self as skia, image_filters, ImageFilter, Paint};
|
||||
|
||||
use super::blurs::radius_to_sigma;
|
||||
use super::Color;
|
||||
use crate::render::filters::compose_filters;
|
||||
|
||||
@@ -48,9 +49,10 @@ impl Shadow {
|
||||
}
|
||||
|
||||
pub fn get_drop_shadow_filter(&self) -> Option<ImageFilter> {
|
||||
let sigma = radius_to_sigma(self.blur);
|
||||
let mut filter = image_filters::drop_shadow_only(
|
||||
(self.offset.0, self.offset.1),
|
||||
(self.blur, self.blur),
|
||||
(sigma, sigma),
|
||||
self.color,
|
||||
None,
|
||||
None,
|
||||
@@ -78,7 +80,7 @@ impl Shadow {
|
||||
}
|
||||
|
||||
pub fn get_inner_shadow_filter(&self) -> Option<ImageFilter> {
|
||||
let sigma = self.blur * 0.5;
|
||||
let sigma = radius_to_sigma(self.blur);
|
||||
let mut filter = skia::image_filters::drop_shadow_only(
|
||||
(self.offset.0, self.offset.1), // DPR?
|
||||
(sigma, sigma),
|
||||
|
||||
Reference in New Issue
Block a user