diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 531cbfad8..b1ffea2d0 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1,5 +1,9 @@ -use skia_safe as skia; use skia_safe::gpu::{self, gl::FramebufferInfo, DirectContext}; +use skia_safe::{self as skia}; +use std::collections::HashMap; +use uuid::Uuid; + +use crate::shapes::Shape; struct GpuState { pub context: DirectContext, @@ -99,4 +103,92 @@ impl RenderState { .clear(skia_safe::Color::TRANSPARENT) .reset_matrix(); } + + pub fn render_single_shape(&mut self, shape: &Shape) { + let r = skia::Rect::new( + shape.selrect.x1, + shape.selrect.y1, + shape.selrect.x2, + shape.selrect.y2, + ); + + // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc + let mut matrix = 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(); + + matrix.set_all( + scale_x, + skew_x, + translate_x, + skew_y, + scale_y, + translate_y, + 0., + 0., + 1., + ); + + let mut center = r.center(); + matrix.post_translate(center); + center.negate(); + matrix.pre_translate(center); + + self.drawing_surface.canvas().concat(&matrix); + + for fill in shape.fills().rev() { + self.drawing_surface.canvas().draw_rect(r, &fill.to_paint()); + } + + let mut paint = skia::Paint::default(); + paint.set_blend_mode(shape.blend_mode.into()); + self.drawing_surface.draw( + &mut self.final_surface.canvas(), + (0.0, 0.0), + skia::SamplingOptions::new(skia::FilterMode::Linear, skia::MipmapMode::Nearest), + Some(&paint), + ); + self.drawing_surface + .canvas() + .clear(skia::Color::TRANSPARENT); + } + + pub fn draw_all_shapes( + &mut self, + zoom: f32, + pan_x: f32, + pan_y: f32, + shapes: &HashMap, + ) { + self.reset_canvas(); + + self.scale(zoom, zoom); + self.translate(pan_x, pan_y); + + self.render_shape_tree(Uuid::nil(), shapes); + + self.flush(); + } + + fn render_shape_tree(&mut self, id: Uuid, shapes: &HashMap) { + let shape = shapes.get(&id).unwrap(); + + // This is needed so the next non-children shape does not carry this shape's transform + self.final_surface.canvas().save(); + self.drawing_surface.canvas().save(); + + if id != Uuid::nil() { + self.render_single_shape(shape); + } + + // draw all the children shapes + let shape_ids = shape.children.clone(); + for shape_id in shape_ids { + self.render_shape_tree(shape_id, shapes); + } + + self.final_surface.canvas().restore(); + self.drawing_surface.canvas().restore(); + } } diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs index 88cf47dba..4718f3b0c 100644 --- a/render-wasm/src/state.rs +++ b/render-wasm/src/state.rs @@ -1,4 +1,3 @@ -use skia_safe::{self as skia, SamplingOptions}; use std::collections::HashMap; use uuid::Uuid; @@ -32,37 +31,8 @@ impl<'a> State<'a> { } pub fn draw_all_shapes(&mut self, zoom: f32, pan_x: f32, pan_y: f32) { - self.render_state.reset_canvas(); - - self.render_state.scale(zoom, zoom); - self.render_state.translate(pan_x, pan_y); - - self.render_shape_tree(Uuid::nil()); - - self.render_state.flush(); - } - - fn render_shape_tree(&mut self, id: Uuid) { - let shape = self.shapes.get(&id).unwrap(); - - // This is needed so the next non-children shape does not carry this shape's transform - self.render_state.final_surface.canvas().save(); - self.render_state.drawing_surface.canvas().save(); - - render_single_shape( - &mut self.render_state.final_surface, - &mut self.render_state.drawing_surface, - shape, - ); - - // draw all the children shapes - let shape_ids = shape.children.clone(); - for shape_id in shape_ids { - self.render_shape_tree(shape_id); - } - - self.render_state.final_surface.canvas().restore(); - self.render_state.drawing_surface.canvas().restore(); + self.render_state + .draw_all_shapes(zoom, pan_x, pan_y, &self.shapes); } pub fn use_shape(&'a mut self, id: Uuid) { @@ -79,50 +49,3 @@ impl<'a> State<'a> { self.current_shape.as_deref_mut() } } - -fn render_single_shape(surface: &mut skia::Surface, offscreen: &mut skia::Surface, shape: &Shape) { - let r = skia::Rect::new( - shape.selrect.x1, - shape.selrect.y1, - shape.selrect.x2, - shape.selrect.y2, - ); - - // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc - let mut matrix = 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(); - - matrix.set_all( - scale_x, - skew_x, - translate_x, - skew_y, - scale_y, - translate_y, - 0., - 0., - 1., - ); - - let mut center = r.center(); - matrix.post_translate(center); - center.negate(); - matrix.pre_translate(center); - - offscreen.canvas().concat(&matrix); - - for fill in shape.fills().rev() { - offscreen.canvas().draw_rect(r, &fill.to_paint()); - } - - let mut paint = skia::Paint::default(); - paint.set_blend_mode(shape.blend_mode.into()); - offscreen.draw( - &mut surface.canvas(), - (0.0, 0.0), - SamplingOptions::new(skia::FilterMode::Linear, skia::MipmapMode::None), - Some(&paint), - ); -}