mirror of
https://github.com/penpot/penpot.git
synced 2025-02-21 22:36:12 -05:00
🎉 Render wasm blur support
This commit is contained in:
parent
d500058aa9
commit
7cc33b1a1a
8 changed files with 117 additions and 11 deletions
|
@ -346,7 +346,6 @@
|
|||
[hidden]
|
||||
(h/call internal-module "_set_shape_hidden" hidden))
|
||||
|
||||
|
||||
(defn- translate-bool-type
|
||||
[bool-type]
|
||||
(case bool-type
|
||||
|
@ -364,6 +363,19 @@
|
|||
[content]
|
||||
(set-shape-path-content content))
|
||||
|
||||
(defn- translate-blur-type
|
||||
[blur-type]
|
||||
(case blur-type
|
||||
:layer-blur 1
|
||||
0))
|
||||
|
||||
(defn set-shape-blur
|
||||
[blur]
|
||||
(let [type (-> blur :type translate-blur-type)
|
||||
hidden (:hidden blur)
|
||||
value (:value blur)]
|
||||
(h/call internal-module "_set_shape_blur" type hidden value)))
|
||||
|
||||
(def debounce-render-without-cache (fns/debounce render-without-cache 100))
|
||||
|
||||
(defn set-view
|
||||
|
@ -395,7 +407,8 @@
|
|||
opacity (dm/get-prop shape :opacity)
|
||||
hidden (dm/get-prop shape :hidden)
|
||||
content (dm/get-prop shape :content)
|
||||
bool-content (dm/get-prop shape :bool-content)]
|
||||
bool-content (dm/get-prop shape :bool-content)
|
||||
blur (dm/get-prop shape :blur)]
|
||||
|
||||
(use-shape id)
|
||||
(set-shape-type type)
|
||||
|
@ -407,6 +420,8 @@
|
|||
(set-shape-children children)
|
||||
(set-shape-opacity opacity)
|
||||
(set-shape-hidden hidden)
|
||||
(when (some? blur)
|
||||
(set-shape-blur blur))
|
||||
(when (and (some? content) (= type :path)) (set-shape-path-content content))
|
||||
(when (some? bool-content) (set-shape-bool-content bool-content))
|
||||
(let [pending' (concat (set-shape-fills fills) (set-shape-strokes strokes))]
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
|
||||
;; --- SHAPE IMPL
|
||||
|
||||
(defn- impl-assoc
|
||||
(defn- set-wasm-attrs
|
||||
[self k v]
|
||||
(when ^boolean shape/*wasm-sync*
|
||||
(api/use-shape (:id self))
|
||||
|
@ -125,11 +125,16 @@
|
|||
:hidden (api/set-shape-hidden v)
|
||||
:shapes (api/set-shape-children v)
|
||||
:content (api/set-shape-path-content v)
|
||||
:blur (api/set-shape-blur v)
|
||||
nil)
|
||||
;; when something synced with wasm
|
||||
;; is modified, we need to request
|
||||
;; a new render.
|
||||
(api/request-render))
|
||||
(api/request-render)))
|
||||
|
||||
(defn- impl-assoc
|
||||
[self k v]
|
||||
(set-wasm-attrs self k v)
|
||||
(case k
|
||||
:id
|
||||
(ShapeProxy. v
|
||||
|
@ -150,6 +155,7 @@
|
|||
|
||||
(defn- impl-dissoc
|
||||
[self k]
|
||||
(set-wasm-attrs self k nil)
|
||||
(case k
|
||||
:id
|
||||
(ShapeProxy. nil
|
||||
|
|
|
@ -77,3 +77,12 @@ Bool operations (`bool-type`) are serialized as `u8`:
|
|||
| 2 | Intersection |
|
||||
| 3 | Exclusion |
|
||||
| \_ | Union |
|
||||
|
||||
## BlurType
|
||||
|
||||
Blur types are serialized as `u8`:
|
||||
|
||||
| Value | Field |
|
||||
| ----- | ------------ |
|
||||
| 1 | Layer |
|
||||
| \_ | None |
|
||||
|
|
|
@ -347,6 +347,14 @@ pub extern "C" fn set_shape_hidden(hidden: bool) {
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_shape_blur(blur_type: u8, hidden: bool, value: f32) {
|
||||
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
|
||||
if let Some(shape) = state.current_shape() {
|
||||
shape.set_blur(blur_type, hidden, value);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_shape_path_content() {
|
||||
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
|
||||
|
|
|
@ -26,6 +26,7 @@ pub trait Renderable {
|
|||
fn hidden(&self) -> bool;
|
||||
fn clip(&self) -> bool;
|
||||
fn children_ids(&self) -> Vec<Uuid>;
|
||||
fn image_filter(&self, scale: f32) -> Option<skia::ImageFilter>;
|
||||
}
|
||||
|
||||
pub(crate) struct CachedSurfaceImage {
|
||||
|
@ -156,15 +157,11 @@ impl RenderState {
|
|||
.render(&mut self.drawing_surface, &self.images)
|
||||
.unwrap();
|
||||
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_blend_mode(element.blend_mode().into());
|
||||
paint.set_alpha_f(element.opacity());
|
||||
|
||||
self.drawing_surface.draw(
|
||||
&mut self.final_surface.canvas(),
|
||||
(0.0, 0.0),
|
||||
skia::SamplingOptions::new(skia::FilterMode::Linear, skia::MipmapMode::Nearest),
|
||||
Some(&paint),
|
||||
Some(&skia::Paint::default()),
|
||||
);
|
||||
self.drawing_surface
|
||||
.canvas()
|
||||
|
@ -310,8 +307,17 @@ impl RenderState {
|
|||
}
|
||||
}
|
||||
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_blend_mode(element.blend_mode().into());
|
||||
paint.set_alpha_f(element.opacity());
|
||||
let filter = element.image_filter(self.viewbox.zoom * self.options.dpr());
|
||||
if let Some(image_filter) = filter {
|
||||
paint.set_image_filter(image_filter);
|
||||
}
|
||||
|
||||
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint);
|
||||
// This is needed so the next non-children shape does not carry this shape's transform
|
||||
self.final_surface.canvas().save();
|
||||
self.final_surface.canvas().save_layer(&layer_rec);
|
||||
self.drawing_surface.canvas().save();
|
||||
|
||||
if !root_id.is_nil() {
|
||||
|
|
|
@ -4,6 +4,7 @@ use uuid::Uuid;
|
|||
|
||||
use crate::render::{BlendMode, Renderable};
|
||||
|
||||
mod blurs;
|
||||
mod bools;
|
||||
mod fills;
|
||||
mod images;
|
||||
|
@ -12,6 +13,7 @@ mod paths;
|
|||
mod renderable;
|
||||
mod strokes;
|
||||
|
||||
pub use blurs::*;
|
||||
pub use bools::*;
|
||||
pub use fills::*;
|
||||
pub use images::*;
|
||||
|
@ -42,6 +44,7 @@ pub struct Shape {
|
|||
fills: Vec<Fill>,
|
||||
strokes: Vec<Stroke>,
|
||||
blend_mode: BlendMode,
|
||||
blur: Blur,
|
||||
opacity: f32,
|
||||
hidden: bool,
|
||||
}
|
||||
|
@ -61,6 +64,7 @@ impl Shape {
|
|||
blend_mode: BlendMode::default(),
|
||||
opacity: 1.,
|
||||
hidden: false,
|
||||
blur: Blur::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,6 +109,10 @@ impl Shape {
|
|||
self.hidden = value;
|
||||
}
|
||||
|
||||
pub fn set_blur(&mut self, blur_type: u8, hidden: bool, value: f32) {
|
||||
self.blur = Blur::new(blur_type, hidden, value);
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, id: Uuid) {
|
||||
self.children.push(id);
|
||||
}
|
||||
|
|
38
render-wasm/src/shapes/blurs.rs
Normal file
38
render-wasm/src/shapes/blurs.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum BlurType {
|
||||
None,
|
||||
Layer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Blur {
|
||||
pub hidden: bool,
|
||||
pub blur_type: BlurType,
|
||||
pub value: f32,
|
||||
}
|
||||
|
||||
impl From<u8> for BlurType {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
1 => BlurType::Layer,
|
||||
_ => BlurType::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Blur {
|
||||
pub fn default() -> Self {
|
||||
Blur {
|
||||
blur_type: BlurType::None,
|
||||
hidden: true,
|
||||
value: 0.,
|
||||
}
|
||||
}
|
||||
pub fn new(blur_type: u8, hidden: bool, value: f32) -> Self {
|
||||
Blur {
|
||||
blur_type: BlurType::from(blur_type),
|
||||
hidden,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use skia_safe as skia;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{Fill, Image, Kind, Path, Shape, Stroke, StrokeCap, StrokeKind};
|
||||
use super::{BlurType, Fill, Image, Kind, Path, Shape, Stroke, StrokeCap, StrokeKind};
|
||||
use crate::math::Rect;
|
||||
use crate::render::{ImageStore, Renderable};
|
||||
|
||||
|
@ -70,6 +70,22 @@ impl Renderable for Shape {
|
|||
self.children.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn image_filter(&self, scale: f32) -> Option<skia::ImageFilter> {
|
||||
if !self.blur.hidden {
|
||||
match self.blur.blur_type {
|
||||
BlurType::None => None,
|
||||
BlurType::Layer => skia::image_filters::blur(
|
||||
(self.blur.value * scale, self.blur.value * scale),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_fill(
|
||||
|
|
Loading…
Add table
Reference in a new issue