From 967bc75a1c38a929461500e5f40c3e59c9d38203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Tue, 10 Dec 2024 15:29:49 +0100 Subject: [PATCH] :recycle: Move rendering a single shape to the shape itself --- render-wasm/src/main.rs | 2 +- render-wasm/src/render.rs | 94 ++++++--------------- render-wasm/src/{shapes => render}/blend.rs | 0 render-wasm/src/shapes.rs | 5 +- render-wasm/src/shapes/render.rs | 92 ++++++++++++++++++++ 5 files changed, 121 insertions(+), 72 deletions(-) rename render-wasm/src/{shapes => render}/blend.rs (100%) create mode 100644 render-wasm/src/shapes/render.rs diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index f15d3232f..fb751aa07 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -307,7 +307,7 @@ pub extern "C" fn clear_shape_fills() { 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)); + shape.set_blend_mode(render::BlendMode::from(mode)); } } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 063ab4b7a..9c8c2ebad 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1,18 +1,30 @@ -mod gpu_state; -mod options; - use skia::Contains; use skia_safe as skia; use std::collections::HashMap; use uuid::Uuid; -use crate::math::Rect; -use crate::shapes::{draw_image_in_container, Fill, Image, Kind, Shape}; +use crate::shapes::{Image, Shape}; use crate::view::Viewbox; +mod blend; +mod gpu_state; +mod options; + use gpu_state::GpuState; use options::RenderOptions; +pub use blend::BlendMode; + +pub trait Renderable { + fn render( + &self, + surface: &mut skia::Surface, + images: &HashMap, + ) -> Result<(), String>; + fn blend_mode(&self) -> BlendMode; + fn opacity(&self) -> f32; +} + pub(crate) struct CachedSurfaceImage { pub image: Image, pub viewbox: Viewbox, @@ -133,39 +145,15 @@ impl RenderState { .reset_matrix(); } - pub fn render_single_shape(&mut self, shape: &Shape) { - let mut transform = skia::Matrix::new_identity(); - let (translate_x, translate_y) = shape.translation(); - let (scale_x, scale_y) = shape.scale(); - let (skew_x, skew_y) = shape.skew(); - transform.set_all( - scale_x, - skew_x, - translate_x, - skew_y, - scale_y, - translate_y, - 0., - 0., - 1., - ); - - // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc - let center = shape.selrect.center(); - let mut matrix = skia::Matrix::new_identity(); - matrix.pre_translate(center); - matrix.pre_concat(&transform); - matrix.pre_translate(-center); - - self.drawing_surface.canvas().concat(&matrix); - - for fill in shape.fills().rev() { - self.render_fill(fill, shape.selrect, &shape.kind); - } + pub fn render_single_element(&mut self, element: &impl Renderable) { + element + .render(&mut self.drawing_surface, &self.images) + .unwrap(); let mut paint = skia::Paint::default(); - paint.set_blend_mode(shape.blend_mode.into()); - paint.set_alpha_f(shape.opacity); + 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), @@ -217,38 +205,6 @@ impl RenderState { self.flush(); } - fn render_fill(&mut self, fill: &Fill, selrect: Rect, kind: &Kind) { - match (fill, kind) { - (Fill::Image(image_fill), kind) => { - let image = self.images.get(&image_fill.id()); - if let Some(image) = image { - draw_image_in_container( - &self.drawing_surface.canvas(), - &image, - image_fill.size(), - kind, - &fill.to_paint(&selrect), - ); - } - } - (_, Kind::Rect(rect)) => { - self.drawing_surface - .canvas() - .draw_rect(rect, &fill.to_paint(&selrect)); - } - (_, Kind::Circle(rect)) => { - self.drawing_surface - .canvas() - .draw_oval(rect, &fill.to_paint(&selrect)); - } - (_, Kind::Path(path)) => { - self.drawing_surface - .canvas() - .draw_path(&path.to_skia_path(), &fill.to_paint(&selrect)); - } - } - } - fn render_all_from_cache(&mut self) -> Result<(), String> { self.reset_canvas(); @@ -353,7 +309,7 @@ impl RenderState { self.drawing_surface.canvas().save(); if !id.is_nil() { - self.render_single_shape(shape); + self.render_single_element(shape); if shape.clip_content { self.drawing_surface.canvas().clip_rect( shape.selrect, diff --git a/render-wasm/src/shapes/blend.rs b/render-wasm/src/render/blend.rs similarity index 100% rename from render-wasm/src/shapes/blend.rs rename to render-wasm/src/render/blend.rs diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index 5362c6d4f..71b573d9f 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -2,11 +2,12 @@ use crate::math; use skia_safe as skia; use uuid::Uuid; -mod blend; +use crate::render::BlendMode; + mod fills; mod images; mod paths; -pub use blend::*; +mod render; pub use fills::*; pub use images::*; pub use paths::*; diff --git a/render-wasm/src/shapes/render.rs b/render-wasm/src/shapes/render.rs new file mode 100644 index 000000000..1a4fa74db --- /dev/null +++ b/render-wasm/src/shapes/render.rs @@ -0,0 +1,92 @@ +use skia_safe as skia; +use std::collections::HashMap; +use uuid::Uuid; + +use super::{draw_image_in_container, Fill, Image, Kind, Shape}; +use crate::math::Rect; +use crate::render::Renderable; + +impl Renderable for Shape { + fn blend_mode(&self) -> crate::render::BlendMode { + self.blend_mode + } + + fn opacity(&self) -> f32 { + self.opacity + } + + fn render( + &self, + surface: &mut skia_safe::Surface, + images: &HashMap, + ) -> Result<(), String> { + let mut transform = skia::Matrix::new_identity(); + let (translate_x, translate_y) = self.translation(); + let (scale_x, scale_y) = self.scale(); + let (skew_x, skew_y) = self.skew(); + transform.set_all( + scale_x, + skew_x, + translate_x, + skew_y, + scale_y, + translate_y, + 0., + 0., + 1., + ); + + // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc + let center = self.selrect.center(); + let mut matrix = skia::Matrix::new_identity(); + matrix.pre_translate(center); + matrix.pre_concat(&transform); + matrix.pre_translate(-center); + + surface.canvas().concat(&matrix); + + for fill in self.fills().rev() { + render_fill(surface, images, fill, self.selrect, &self.kind); + } + + let mut paint = skia::Paint::default(); + paint.set_blend_mode(self.blend_mode.into()); + paint.set_alpha_f(self.opacity); + + Ok(()) + } +} + +fn render_fill( + surface: &mut skia::Surface, + images: &HashMap, + fill: &Fill, + selrect: Rect, + kind: &Kind, +) { + match (fill, kind) { + (Fill::Image(image_fill), kind) => { + let image = images.get(&image_fill.id()); + if let Some(image) = image { + draw_image_in_container( + surface.canvas(), + &image, + image_fill.size(), + kind, + &fill.to_paint(&selrect), + ); + } + } + (_, Kind::Rect(rect)) => { + surface.canvas().draw_rect(rect, &fill.to_paint(&selrect)); + } + (_, Kind::Circle(rect)) => { + surface.canvas().draw_oval(rect, &fill.to_paint(&selrect)); + } + (_, Kind::Path(path)) => { + surface + .canvas() + .draw_path(&path.to_skia_path(), &fill.to_paint(&selrect)); + } + } +}