mirror of
https://github.com/penpot/penpot.git
synced 2025-01-21 06:02:32 -05:00
🎉 Implement drawing with blend mode (single fill)
This commit is contained in:
parent
7458165e51
commit
966e942a7f
5 changed files with 87 additions and 15 deletions
|
@ -20,6 +20,7 @@
|
|||
(defonce wasm-set-shape-transform (constantly nil))
|
||||
(defonce wasm-set-shape-rotation (constantly nil))
|
||||
(defonce wasm-set-shape-fills (constantly nil))
|
||||
(defonce wasm-set-shape-blend-mode (constantly nil))
|
||||
(defonce wasm-set-shape-children (constantly nil))
|
||||
|
||||
(cr/defrecord Shape [id name type x y width height rotation selrect points
|
||||
|
@ -115,11 +116,12 @@
|
|||
(when *wasm-sync*
|
||||
(wasm-use-shape (:id coll))
|
||||
(case k
|
||||
:selrect (wasm-set-shape-selrect v)
|
||||
:rotation (wasm-set-shape-rotation v)
|
||||
:transform (wasm-set-shape-transform v)
|
||||
:fills (wasm-set-shape-fills v)
|
||||
:shapes (wasm-set-shape-children v)
|
||||
:selrect (wasm-set-shape-selrect v)
|
||||
:rotation (wasm-set-shape-rotation v)
|
||||
:transform (wasm-set-shape-transform v)
|
||||
:fills (wasm-set-shape-fills v)
|
||||
:blend-mode (wasm-set-shape-blend-mode v)
|
||||
:shapes (wasm-set-shape-children v)
|
||||
nil))
|
||||
(let [delegate (.-delegate ^ShapeProxy coll)
|
||||
delegate' (assoc delegate k v)]
|
||||
|
|
|
@ -74,24 +74,50 @@
|
|||
[r g b] (cc/hex->rgb (:fill-color fill))]
|
||||
(._add_shape_solid_fill ^js internal-module r g b a))))
|
||||
|
||||
(defn set-shape-blend-mode
|
||||
[blend-mode]
|
||||
;; These values correspond to skia::BlendMode representation
|
||||
;; https://rust-skia.github.io/doc/skia_safe/enum.BlendMode.html
|
||||
(let [encoded-blend (case blend-mode
|
||||
:normal 3
|
||||
:darken 16
|
||||
:multiply 24
|
||||
:color-burn 19
|
||||
:lighten 17
|
||||
:screen 14
|
||||
:color-dodge 18
|
||||
:overlay 15
|
||||
:soft-light 21
|
||||
:hard-light 20
|
||||
:difference 22
|
||||
:exclusion 23
|
||||
:hue 25
|
||||
:saturation 26
|
||||
:color 27
|
||||
:luminosity 28
|
||||
3)]
|
||||
(._set_shape_blend_mode ^js internal-module encoded-blend)))
|
||||
|
||||
(defn set-objects
|
||||
[objects]
|
||||
(let [shapes (into [] xform (vals objects))
|
||||
total-shapes (count shapes)]
|
||||
(loop [index 0]
|
||||
(when (< index total-shapes)
|
||||
(let [shape (nth shapes index)
|
||||
id (dm/get-prop shape :id)
|
||||
selrect (dm/get-prop shape :selrect)
|
||||
rotation (dm/get-prop shape :rotation)
|
||||
transform (dm/get-prop shape :transform)
|
||||
fills (dm/get-prop shape :fills)
|
||||
children (dm/get-prop shape :shapes)]
|
||||
(let [shape (nth shapes index)
|
||||
id (dm/get-prop shape :id)
|
||||
selrect (dm/get-prop shape :selrect)
|
||||
rotation (dm/get-prop shape :rotation)
|
||||
transform (dm/get-prop shape :transform)
|
||||
fills (dm/get-prop shape :fills)
|
||||
children (dm/get-prop shape :shapes)
|
||||
blend-mode (dm/get-prop shape :blend-mode)]
|
||||
(use-shape id)
|
||||
(set-shape-selrect selrect)
|
||||
(set-shape-rotation rotation)
|
||||
(set-shape-transform transform)
|
||||
(set-shape-fills fills)
|
||||
(set-shape-blend-mode blend-mode)
|
||||
(set-shape-children children)
|
||||
(recur (inc index)))))))
|
||||
|
||||
|
@ -155,4 +181,5 @@
|
|||
(set! app.common.types.shape.impl/wasm-set-shape-transform set-shape-transform)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-rotation set-shape-rotation)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-fills set-shape-fills)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-blend-mode set-shape-blend-mode)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-children set-shape-children)
|
||||
|
|
|
@ -128,6 +128,14 @@ pub extern "C" fn clear_shape_fills() {
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn set_shape_blend_mode(mode: i32) {
|
||||
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
|
||||
if let Some(shape) = state.current_shape() {
|
||||
shape.set_blend_mode(shapes::BlendMode::from(mode));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
render::init_gl();
|
||||
}
|
||||
|
|
|
@ -141,7 +141,10 @@ fn render_single_shape(surface: &mut skia::Surface, shape: &Shape) {
|
|||
|
||||
surface.canvas().concat(&matrix);
|
||||
|
||||
// TODO: use blend mode for the shape as a whole, not in each fill
|
||||
for fill in shape.fills().rev() {
|
||||
surface.canvas().draw_rect(r, &fill.to_paint());
|
||||
let mut p = fill.to_paint();
|
||||
p.set_blend_mode(shape.blend_mode.into());
|
||||
surface.canvas().draw_rect(r, &p);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@ impl Fill {
|
|||
p.set_color(*color);
|
||||
p.set_style(skia::PaintStyle::Fill);
|
||||
p.set_anti_alias(true);
|
||||
// TODO: get proper blend mode. See https://tree.taiga.io/project/penpot/task/9275
|
||||
p.set_blend_mode(skia::BlendMode::SrcOver);
|
||||
p
|
||||
}
|
||||
|
@ -80,15 +79,43 @@ impl Fill {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub struct BlendMode(skia::BlendMode);
|
||||
|
||||
impl Default for BlendMode {
|
||||
fn default() -> Self {
|
||||
BlendMode(skia::BlendMode::SrcOver)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for BlendMode {
|
||||
fn from(value: i32) -> Self {
|
||||
if value <= skia::BlendMode::Luminosity as i32 {
|
||||
unsafe { Self(std::mem::transmute(value)) }
|
||||
} else {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<skia::BlendMode> for BlendMode {
|
||||
fn into(self) -> skia::BlendMode {
|
||||
match self {
|
||||
Self(skia_blend) => skia_blend,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Shape {
|
||||
pub id: Uuid,
|
||||
pub children: Vec::<Uuid>,
|
||||
pub children: Vec<Uuid>,
|
||||
pub kind: Kind,
|
||||
pub selrect: Rect,
|
||||
pub transform: Matrix,
|
||||
pub rotation: f32,
|
||||
fills: Vec<Fill>,
|
||||
pub blend_mode: BlendMode,
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
|
@ -101,6 +128,7 @@ impl Shape {
|
|||
transform: Matrix::identity(),
|
||||
rotation: 0.,
|
||||
fills: vec![],
|
||||
blend_mode: BlendMode::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,4 +155,8 @@ impl Shape {
|
|||
pub fn clear_fills(&mut self) {
|
||||
self.fills.clear();
|
||||
}
|
||||
|
||||
pub fn set_blend_mode(&mut self, mode: BlendMode) {
|
||||
self.blend_mode = mode;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue