mirror of
https://github.com/penpot/penpot.git
synced 2026-06-16 12:22:22 +00:00
🎉 Suport in wasm for both layer and background blur
This commit is contained in:
parent
100caa794d
commit
21cad83b2a
@ -76,7 +76,7 @@
|
||||
}
|
||||
|
||||
.disabled-label-tooltip {
|
||||
flex-grow:1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
||||
@ -944,21 +944,21 @@
|
||||
|
||||
(defn set-shape-blur
|
||||
[blur]
|
||||
(if (some? blur)
|
||||
(let [type (sr/translate-blur-type :layer-blur)
|
||||
hidden (:hidden blur)
|
||||
value (:value blur)]
|
||||
(h/call wasm/internal-module "_set_shape_blur" type hidden value))
|
||||
(h/call wasm/internal-module "_clear_shape_blur")))
|
||||
(let [type (sr/translate-blur-type :layer-blur)]
|
||||
(if (some? blur)
|
||||
(let [hidden (:hidden blur)
|
||||
value (:value blur)]
|
||||
(h/call wasm/internal-module "_set_shape_blur" type hidden value))
|
||||
(h/call wasm/internal-module "_clear_shape_blur" type))))
|
||||
|
||||
(defn set-shape-background-blur
|
||||
[background-blur]
|
||||
(if (some? background-blur)
|
||||
(let [type (sr/translate-blur-type :background-blur)
|
||||
hidden (:hidden background-blur)
|
||||
value (:value background-blur)]
|
||||
(h/call wasm/internal-module "_set_shape_blur" type hidden value))
|
||||
(h/call wasm/internal-module "_clear_shape_blur")))
|
||||
(let [type (sr/translate-blur-type :background-blur)]
|
||||
(if (some? background-blur)
|
||||
(let [hidden (:hidden background-blur)
|
||||
value (:value background-blur)]
|
||||
(h/call wasm/internal-module "_set_shape_blur" type hidden value))
|
||||
(h/call wasm/internal-module "_clear_shape_blur" type))))
|
||||
|
||||
(defn set-shape-corners
|
||||
[corners]
|
||||
|
||||
@ -130,7 +130,6 @@
|
||||
(defn- set-wasm-attr!
|
||||
[shape k]
|
||||
(when wasm/context-initialized?
|
||||
;;TODO_BLUR: ask about this,
|
||||
(let [shape (case k
|
||||
:svg-attrs (svg-filters/apply-svg-derived (assoc shape :svg-attrs (get shape :svg-attrs)))
|
||||
(:fills :blur :shadow) (svg-filters/apply-svg-derived shape)
|
||||
|
||||
@ -44,7 +44,6 @@
|
||||
(set! context-initialized? false)
|
||||
(reset! context-lost? false))
|
||||
|
||||
;; TODO_BLUR: ask for blur-type??
|
||||
(defonce serializers
|
||||
#js {:blur-type shared/RawBlurType
|
||||
:blend-mode shared/RawBlendMode
|
||||
|
||||
@ -24,7 +24,6 @@ use std::collections::{HashMap, HashSet};
|
||||
use options::RenderOptions;
|
||||
pub use surfaces::{SurfaceId, Surfaces};
|
||||
|
||||
// TODO_BLUR: should we add here BackgroundBlur
|
||||
use crate::error::{Error, Result};
|
||||
use crate::math;
|
||||
use crate::shapes::{
|
||||
@ -371,7 +370,7 @@ pub(crate) struct RenderState {
|
||||
// migration to remove group-level fills is completed, this code should be removed.
|
||||
// Frames contained in groups must reset this nested_fills stack pushing a new empty vector.
|
||||
pub nested_fills: Vec<Vec<Fill>>,
|
||||
pub nested_blurs: Vec<Option<Blur>>, // FIXME: why is this an option?, sholud be an option now? TODO_BLUR
|
||||
pub nested_blurs: Vec<Option<Blur>>, // FIXME: why is this an option?
|
||||
pub nested_shadows: Vec<Vec<Shadow>>,
|
||||
pub show_grid: Option<Uuid>,
|
||||
pub rulers: RulerState,
|
||||
@ -588,7 +587,7 @@ impl RenderState {
|
||||
backbuffer_crop_cache: HashMap::default(),
|
||||
})
|
||||
}
|
||||
/// TODO_BLUR: ?
|
||||
|
||||
/// Combines every visible layer blur currently active (ancestors + shape)
|
||||
/// into a single equivalent blur. Layer blur radii compound by adding their
|
||||
/// variances (σ² = radius²), so we:
|
||||
@ -650,10 +649,7 @@ impl RenderState {
|
||||
{
|
||||
return;
|
||||
}
|
||||
let blur = match shape
|
||||
.blur
|
||||
.filter(|b| !b.hidden && b.blur_type == BlurType::BackgroundBlur)
|
||||
{
|
||||
let blur = match shape.visible_background_blur() {
|
||||
Some(blur) => blur,
|
||||
None => return,
|
||||
};
|
||||
@ -1203,6 +1199,7 @@ impl RenderState {
|
||||
&& parent_shadows.is_none()
|
||||
&& !shape.needs_layer()
|
||||
&& shape.blur.is_none()
|
||||
&& shape.background_blur.is_none()
|
||||
&& !has_inherited_blur
|
||||
&& shape.shadows.is_empty()
|
||||
&& shape.transform.is_identity()
|
||||
@ -1312,20 +1309,9 @@ impl RenderState {
|
||||
// We don't want to change the value in the global state
|
||||
let mut shape: Cow<Shape> = Cow::Borrowed(shape);
|
||||
|
||||
// Remove background blur from the shape so it doesn't get processed
|
||||
// as a layer blur. The actual rendering is done before the save_layer
|
||||
// in render_background_blur() so it's independent of shape opacity.
|
||||
if !skip_effects
|
||||
&& apply_to_current_surface
|
||||
&& fills_surface_id == SurfaceId::Fills
|
||||
&& !matches!(shape.shape_type, Type::Text(_))
|
||||
&& !matches!(shape.shape_type, Type::SVGRaw(_))
|
||||
&& shape
|
||||
.blur
|
||||
.is_some_and(|b| !b.hidden && b.blur_type == BlurType::BackgroundBlur)
|
||||
{
|
||||
shape.to_mut().set_blur(None);
|
||||
}
|
||||
// Background blur is stored separately (shape.background_blur) and is
|
||||
// rendered before the save_layer in render_background_blur(), so here
|
||||
// shape.blur only ever holds a layer blur.
|
||||
|
||||
let frame_has_blur = Self::frame_clip_layer_blur(&shape).is_some();
|
||||
let shape_has_blur = shape.blur.is_some();
|
||||
@ -2842,6 +2828,7 @@ impl RenderState {
|
||||
|
||||
plain_shape_mut.clear_shadows();
|
||||
plain_shape_mut.blur = None;
|
||||
plain_shape_mut.background_blur = None;
|
||||
|
||||
// Shadow rendering uses a single render_shape call with no render_shape_exit,
|
||||
// so strokes must be drawn here. Disable clip_content to avoid skip_strokes
|
||||
@ -3645,10 +3632,8 @@ impl RenderState {
|
||||
// assigned to this tile) because the blur snapshots Current
|
||||
// which must contain the shapes behind it.
|
||||
let tile_has_bg_blur = ids.iter().any(|id| {
|
||||
tree.get(id).is_some_and(|s| {
|
||||
s.blur
|
||||
.is_some_and(|b| !b.hidden && b.blur_type == BlurType::BackgroundBlur)
|
||||
})
|
||||
tree.get(id)
|
||||
.is_some_and(|s| s.visible_background_blur().is_some())
|
||||
});
|
||||
|
||||
// We only need first level shapes, in the same order as the parent node.
|
||||
|
||||
@ -188,6 +188,7 @@ pub struct Shape {
|
||||
pub blend_mode: BlendMode,
|
||||
pub vertical_align: VerticalAlign,
|
||||
pub blur: Option<Blur>,
|
||||
pub background_blur: Option<Blur>,
|
||||
pub opacity: f32,
|
||||
pub hidden: bool,
|
||||
pub svg: Option<skia::svg::Dom>,
|
||||
@ -291,6 +292,7 @@ impl Shape {
|
||||
opacity: 1.,
|
||||
hidden: false,
|
||||
blur: None,
|
||||
background_blur: None,
|
||||
svg: None,
|
||||
svg_attrs: None,
|
||||
shadows: Vec::with_capacity(1),
|
||||
@ -314,6 +316,10 @@ impl Shape {
|
||||
blur.scale_content(value);
|
||||
}
|
||||
|
||||
if let Some(background_blur) = self.background_blur.as_mut() {
|
||||
background_blur.scale_content(value);
|
||||
}
|
||||
|
||||
self.layout_item
|
||||
.iter_mut()
|
||||
.for_each(|i| i.scale_content(value));
|
||||
@ -631,6 +637,15 @@ impl Shape {
|
||||
self.blur = blur;
|
||||
}
|
||||
|
||||
pub fn set_background_blur(&mut self, blur: Option<Blur>) {
|
||||
self.invalidate_extrect();
|
||||
self.background_blur = blur;
|
||||
}
|
||||
|
||||
pub fn visible_background_blur(&self) -> Option<Blur> {
|
||||
self.background_blur.filter(|blur| !blur.hidden)
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, id: Uuid) {
|
||||
self.children.push(id);
|
||||
}
|
||||
@ -1421,6 +1436,7 @@ impl Shape {
|
||||
}
|
||||
|
||||
self.blur.is_none()
|
||||
&& self.background_blur.is_none()
|
||||
&& self.shadows.is_empty()
|
||||
&& (self.opacity - 1.0).abs() <= 1e-4
|
||||
&& self.blend_mode().0 == skia::BlendMode::SrcOver
|
||||
@ -1665,7 +1681,7 @@ impl Shape {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.blur.is_some() {
|
||||
if self.blur.is_some() || self.background_blur.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1805,6 +1821,38 @@ mod tests {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn layer_blur_and_background_blur_can_coexist() {
|
||||
let mut shape = any_shape();
|
||||
|
||||
let layer_blur = Blur::new(BlurType::LayerBlur, false, 4.0);
|
||||
let background_blur = Blur::new(BlurType::BackgroundBlur, false, 8.0);
|
||||
|
||||
shape.set_blur(Some(layer_blur));
|
||||
shape.set_background_blur(Some(background_blur));
|
||||
|
||||
assert_eq!(shape.blur, Some(layer_blur));
|
||||
assert_eq!(shape.background_blur, Some(background_blur));
|
||||
assert_eq!(shape.visible_background_blur(), Some(background_blur));
|
||||
|
||||
// Clearing one type must not affect the other.
|
||||
shape.set_blur(None);
|
||||
assert_eq!(shape.blur, None);
|
||||
assert_eq!(shape.background_blur, Some(background_blur));
|
||||
|
||||
shape.set_blur(Some(layer_blur));
|
||||
shape.set_background_blur(None);
|
||||
assert_eq!(shape.blur, Some(layer_blur));
|
||||
assert_eq!(shape.background_blur, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hidden_background_blur_is_not_visible() {
|
||||
let mut shape = any_shape();
|
||||
shape.set_background_blur(Some(Blur::new(BlurType::BackgroundBlur, true, 8.0)));
|
||||
assert_eq!(shape.visible_background_blur(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_corners() {
|
||||
let mut shape = any_shape();
|
||||
|
||||
@ -29,14 +29,21 @@ impl From<RawBlurType> for BlurType {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_shape_blur(blur_type: u8, hidden: bool, value: f32) {
|
||||
with_current_shape_mut!(state, |shape: &mut Shape| {
|
||||
let blur_type = RawBlurType::from(blur_type);
|
||||
shape.set_blur(Some(Blur::new(blur_type.into(), hidden, value)));
|
||||
let blur_type: BlurType = RawBlurType::from(blur_type).into();
|
||||
let blur = Some(Blur::new(blur_type, hidden, value));
|
||||
match blur_type {
|
||||
BlurType::LayerBlur => shape.set_blur(blur),
|
||||
BlurType::BackgroundBlur => shape.set_background_blur(blur),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn clear_shape_blur() {
|
||||
pub extern "C" fn clear_shape_blur(blur_type: u8) {
|
||||
with_current_shape_mut!(state, |shape: &mut Shape| {
|
||||
shape.set_blur(None);
|
||||
match RawBlurType::from(blur_type).into() {
|
||||
BlurType::LayerBlur => shape.set_blur(None),
|
||||
BlurType::BackgroundBlur => shape.set_background_blur(None),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user