mirror of
https://github.com/penpot/penpot.git
synced 2026-09-10 05:58:47 +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:
commit
10359d39df
@ -23,7 +23,8 @@ pub use surfaces::{SurfaceId, Surfaces};
|
|||||||
|
|
||||||
use crate::performance;
|
use crate::performance;
|
||||||
use crate::shapes::{
|
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::state::{ShapesPoolMutRef, ShapesPoolRef};
|
||||||
use crate::tiles::{self, PendingTiles, TileRect};
|
use crate::tiles::{self, PendingTiles, TileRect};
|
||||||
@ -816,7 +817,7 @@ impl RenderState {
|
|||||||
{
|
{
|
||||||
if let Some(blur) = shape.blur.filter(|b| !b.hidden) {
|
if let Some(blur) = shape.blur.filter(|b| !b.hidden) {
|
||||||
shape.to_mut().set_blur(None);
|
shape.to_mut().set_blur(None);
|
||||||
Some(blur.value)
|
Some(blur.sigma())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -1437,7 +1438,7 @@ impl RenderState {
|
|||||||
if !self.options.is_fast_mode() {
|
if !self.options.is_fast_mode() {
|
||||||
if let Some(frame_blur) = Self::frame_clip_layer_blur(element) {
|
if let Some(frame_blur) = Self::frame_clip_layer_blur(element) {
|
||||||
let scale = self.get_scale();
|
let scale = self.get_scale();
|
||||||
let sigma = frame_blur.value * scale;
|
let sigma = radius_to_sigma(frame_blur.value * scale);
|
||||||
if let Some(filter) =
|
if let Some(filter) =
|
||||||
skia::image_filters::blur((sigma, sigma), None, None, None)
|
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||||
{
|
{
|
||||||
@ -1630,8 +1631,10 @@ impl RenderState {
|
|||||||
let mut plain_shape = Cow::Borrowed(shape);
|
let mut plain_shape = Cow::Borrowed(shape);
|
||||||
let combined_blur =
|
let combined_blur =
|
||||||
Self::combine_blur_values(self.combined_layer_blur(shape.blur), extra_layer_blur);
|
Self::combine_blur_values(self.combined_layer_blur(shape.blur), extra_layer_blur);
|
||||||
let blur_filter = combined_blur
|
let blur_filter = combined_blur.and_then(|blur| {
|
||||||
.and_then(|blur| skia::image_filters::blur((blur.value, blur.value), None, None, None));
|
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();
|
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)
|
// Create filter with blur only (no offset, no spread - handled geometrically)
|
||||||
let blur_only_filter = if transformed_shadow.blur > 0.0 {
|
let blur_only_filter = if transformed_shadow.blur > 0.0 {
|
||||||
Some(skia::image_filters::blur(
|
let sigma = radius_to_sigma(transformed_shadow.blur);
|
||||||
(transformed_shadow.blur, transformed_shadow.blur),
|
Some(skia::image_filters::blur((sigma, sigma), None, None, None))
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@ -30,7 +30,7 @@ pub mod text_paths;
|
|||||||
mod transform;
|
mod transform;
|
||||||
|
|
||||||
pub use blend::*;
|
pub use blend::*;
|
||||||
pub use blurs::*;
|
pub use blurs::{radius_to_sigma, Blur, BlurType};
|
||||||
pub use bools::*;
|
pub use bools::*;
|
||||||
pub use corners::*;
|
pub use corners::*;
|
||||||
pub use fills::*;
|
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 {
|
if let Some(image_filter) = blur {
|
||||||
let blur_bounds = image_filter.compute_fast_bounds(rect);
|
let blur_bounds = image_filter.compute_fast_bounds(rect);
|
||||||
rect.join(blur_bounds);
|
rect.join(blur_bounds);
|
||||||
@ -1236,12 +1237,10 @@ impl Shape {
|
|||||||
self.blur
|
self.blur
|
||||||
.filter(|blur| !blur.hidden)
|
.filter(|blur| !blur.hidden)
|
||||||
.and_then(|blur| match blur.blur_type {
|
.and_then(|blur| match blur.blur_type {
|
||||||
BlurType::LayerBlur => skia::image_filters::blur(
|
BlurType::LayerBlur => {
|
||||||
(blur.value * scale, blur.value * scale),
|
let sigma = radius_to_sigma(blur.value * scale);
|
||||||
None,
|
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||||
None,
|
}
|
||||||
None,
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,7 +1250,8 @@ impl Shape {
|
|||||||
.filter(|blur| !blur.hidden)
|
.filter(|blur| !blur.hidden)
|
||||||
.and_then(|blur| match blur.blur_type {
|
.and_then(|blur| match blur.blur_type {
|
||||||
BlurType::LayerBlur => {
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum BlurType {
|
pub enum BlurType {
|
||||||
LayerBlur,
|
LayerBlur,
|
||||||
@ -22,4 +36,11 @@ impl Blur {
|
|||||||
pub fn scale_content(&mut self, value: f32) {
|
pub fn scale_content(&mut self, value: f32) {
|
||||||
self.value *= value;
|
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 skia_safe::{self as skia, image_filters, ImageFilter, Paint};
|
||||||
|
|
||||||
|
use super::blurs::radius_to_sigma;
|
||||||
use super::Color;
|
use super::Color;
|
||||||
use crate::render::filters::compose_filters;
|
use crate::render::filters::compose_filters;
|
||||||
|
|
||||||
@ -48,9 +49,10 @@ impl Shadow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_drop_shadow_filter(&self) -> Option<ImageFilter> {
|
pub fn get_drop_shadow_filter(&self) -> Option<ImageFilter> {
|
||||||
|
let sigma = radius_to_sigma(self.blur);
|
||||||
let mut filter = image_filters::drop_shadow_only(
|
let mut filter = image_filters::drop_shadow_only(
|
||||||
(self.offset.0, self.offset.1),
|
(self.offset.0, self.offset.1),
|
||||||
(self.blur, self.blur),
|
(sigma, sigma),
|
||||||
self.color,
|
self.color,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
@ -78,7 +80,7 @@ impl Shadow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_inner_shadow_filter(&self) -> Option<ImageFilter> {
|
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(
|
let mut filter = skia::image_filters::drop_shadow_only(
|
||||||
(self.offset.0, self.offset.1), // DPR?
|
(self.offset.0, self.offset.1), // DPR?
|
||||||
(sigma, sigma),
|
(sigma, sigma),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user