From 9143187efd39169896df4762fa44bbda297243d9 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 20 Feb 2025 16:52:11 +0100 Subject: [PATCH] :sparkles: Modify shapes geometry instead of transformation matrix --- render-wasm/src/render.rs | 28 +++++---- render-wasm/src/shapes.rs | 100 +++++++++++++++++++++++++++----- render-wasm/src/shapes/paths.rs | 6 +- 3 files changed, 106 insertions(+), 28 deletions(-) diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 0f5bf86e6..5c034adcd 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -297,24 +297,28 @@ impl RenderState { self.drawing_surface .canvas() - .concat(&transform.invert().unwrap()); + .concat(&transform.invert().unwrap_or(Matrix::default())); + } + + // Clone so we don't change the value in the global state + let mut shape = shape.clone(); + + if let Some(modifiers) = modifiers { + shape.apply_transform(&modifiers); } let center = shape.center(); - // Transform the shape in the center - let mut matrix = shape.transform.clone(); + let mut matrix = shape.transform; matrix.post_translate(center); matrix.pre_translate(-center); - if let Some(modifiers) = modifiers { - matrix.post_concat(&modifiers); - } - - self.drawing_surface.canvas().concat(&matrix); - match &shape.kind { Kind::SVGRaw(sr) => { + if let Some(modifiers) = modifiers { + self.drawing_surface.canvas().concat(&modifiers); + } + self.drawing_surface.canvas().concat(&matrix); if let Some(svg) = shape.svg.as_ref() { svg.render(self.drawing_surface.canvas()) } else { @@ -332,12 +336,14 @@ impl RenderState { } } _ => { + self.drawing_surface.canvas().concat(&matrix); + for fill in shape.fills().rev() { - fills::render(self, shape, fill); + fills::render(self, &shape, fill); } for stroke in shape.strokes().rev() { - strokes::render(self, shape, stroke); + strokes::render(self, &shape, stroke); } for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) { diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index cd8b84b16..1f442b700 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -348,24 +348,29 @@ impl Shape { } pub fn set_corners(&mut self, raw_corners: (f32, f32, f32, f32)) { - let (r1, r2, r3, r4) = raw_corners; - let are_straight_corners = r1.abs() <= f32::EPSILON - && r2.abs() <= f32::EPSILON - && r3.abs() <= f32::EPSILON - && r4.abs() <= f32::EPSILON; + match self.kind { + Kind::Rect(_, _) => { + let (r1, r2, r3, r4) = raw_corners; + let are_straight_corners = r1.abs() <= f32::EPSILON + && r2.abs() <= f32::EPSILON + && r3.abs() <= f32::EPSILON + && r4.abs() <= f32::EPSILON; - let corners = if are_straight_corners { - None - } else { - Some([ - (r1, r1).into(), - (r2, r2).into(), - (r3, r3).into(), - (r4, r4).into(), - ]) - }; + let corners = if are_straight_corners { + None + } else { + Some([ + (r1, r1).into(), + (r2, r2).into(), + (r3, r3).into(), + (r4, r4).into(), + ]) + }; - self.kind = Kind::Rect(self.selrect, corners); + self.kind = Kind::Rect(self.selrect, corners); + } + _ => {} + } } pub fn set_svg(&mut self, svg: skia::svg::Dom) { @@ -494,6 +499,52 @@ impl Shape { _ => None, } } + + fn transform_selrect(&mut self, transform: &Matrix) { + let mut center = self.selrect.center(); + center = transform.map_point(center); + + let bounds = self.bounds().transform(&transform); + self.transform = bounds.transform_matrix().unwrap_or(Matrix::default()); + + let width = bounds.width(); + let height = bounds.height(); + + self.selrect = Rect::from_xywh( + center.x - width / 2.0, + center.y - height / 2.0, + width, + height, + ); + } + + pub fn apply_transform(&mut self, transform: &Matrix) { + match &self.kind { + Kind::Rect(_, c) => { + let c = c.clone(); + self.transform_selrect(&transform); + self.kind = Kind::Rect(self.selrect, c); + } + Kind::Circle(_) => { + self.transform_selrect(&transform); + self.kind = Kind::Circle(self.selrect); + } + Kind::Path(path) => { + let mut path = path.clone(); + self.transform_selrect(&transform); + path.transform(&transform); + self.kind = Kind::Path(path); + } + Kind::Bool(bool_type, path) => { + let bool_type = *bool_type; + let mut path = path.clone(); + self.transform_selrect(&transform); + path.transform(&transform); + self.kind = Kind::Bool(bool_type, path); + } + _ => {} + } + } } #[cfg(test)] @@ -512,4 +563,21 @@ mod tests { shape.add_fill(Fill::Solid(Color::TRANSPARENT)); assert_eq!(shape.fills.get(0), Some(&Fill::Solid(Color::TRANSPARENT))) } + + #[test] + fn test_apply_transform() { + let mut shape = Shape::new(Uuid::new_v4()); + shape.set_shape_type(Type::Rect); + shape.set_selrect(0.0, 10.0, 10.0, 0.0); + shape.apply_transform(Matrix::scale((2.0, 2.0))); + + match shape.kind { + Kind::Rect(r, _) => { + //println!(">>>{r:?}"); + assert_eq!(r.width(), 20.0); + assert_eq!(r.height(), 20.0); + } + _ => assert!(false) + } + } } diff --git a/render-wasm/src/shapes/paths.rs b/render-wasm/src/shapes/paths.rs index d3b4de1c8..5f0741842 100644 --- a/render-wasm/src/shapes/paths.rs +++ b/render-wasm/src/shapes/paths.rs @@ -1,4 +1,4 @@ -use skia_safe as skia; +use skia_safe::{self as skia, Matrix}; use std::array::TryFromSliceError; type Point = (f32, f32); @@ -144,4 +144,8 @@ impl Path { pub fn is_open(&self) -> bool { self.open } + + pub fn transform(&mut self, mtx: &Matrix) { + self.skia_path.transform(mtx); + } }