Modify shapes geometry instead of transformation matrix

This commit is contained in:
alonso.torres 2025-02-20 16:52:11 +01:00
parent b661f39422
commit 9143187efd
3 changed files with 106 additions and 28 deletions

View file

@ -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()) {

View file

@ -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)
}
}
}

View file

@ -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);
}
}