diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 099a954fd5..7244f1169c 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -221,8 +221,7 @@ (aget buffer 0) (aget buffer 1) (aget buffer 2) - (aget buffer 3) - image-size) + (aget buffer 3)) true)))))) (defn set-shape-fills diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 8016bcf946..c6a8d0710b 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -332,21 +332,19 @@ pub extern "C" fn store_font(family_name_size: u32, font_size: u32) { } #[no_mangle] -pub extern "C" fn store_image(a: u32, b: u32, c: u32, d: u32, size: u32) { +pub extern "C" fn store_image(a: u32, b: u32, c: u32, d: u32) { let state = unsafe { STATE.as_mut() }.expect("Got an invalid state pointer"); let id = uuid_from_u32_quartet(a, b, c, d); + let image_bytes = mem::bytes(); - unsafe { - let image_bytes = - Vec::::from_raw_parts(mem::buffer_ptr(), size as usize, size as usize); - match state.render_state().add_image(id, &image_bytes) { - Err(msg) => { - eprintln!("{}", msg); - } - _ => {} + match state.render_state().add_image(id, &image_bytes) { + Err(msg) => { + eprintln!("{}", msg); } - mem::free_bytes(); + _ => {} } + + mem::free_bytes(); } #[no_mangle] diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 0f5bf86e69..5c034adcdc 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 cd8b84b165..1114b182f1 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 d3b4de1c87..5f0741842c 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); + } }