mirror of
https://github.com/penpot/penpot.git
synced 2025-05-17 05:06:11 +02:00
✨ Add support for WASM transforms
This commit is contained in:
parent
a3a757f842
commit
1bb337c3dd
18 changed files with 658 additions and 153 deletions
|
@ -1,70 +0,0 @@
|
|||
use skia_safe as skia;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Matrix {
|
||||
pub a: f32,
|
||||
pub b: f32,
|
||||
pub c: f32,
|
||||
pub d: f32,
|
||||
pub e: f32,
|
||||
pub f: f32,
|
||||
}
|
||||
|
||||
impl Matrix {
|
||||
pub fn new(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> Self {
|
||||
Self { a, b, c, d, e, f }
|
||||
}
|
||||
|
||||
pub fn identity() -> Self {
|
||||
Self {
|
||||
a: 1.,
|
||||
b: 0.,
|
||||
c: 0.,
|
||||
d: 1.,
|
||||
e: 0.,
|
||||
f: 0.,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_skia_matrix(&self) -> skia::Matrix {
|
||||
let mut res = 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();
|
||||
res.set_all(
|
||||
scale_x,
|
||||
skew_x,
|
||||
translate_x,
|
||||
skew_y,
|
||||
scale_y,
|
||||
translate_y,
|
||||
0.,
|
||||
0.,
|
||||
1.,
|
||||
);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn no_translation(&self) -> Self {
|
||||
let mut res = Self::identity();
|
||||
res.c = self.c;
|
||||
res.b = self.b;
|
||||
res.a = self.a;
|
||||
res.d = self.d;
|
||||
res
|
||||
}
|
||||
|
||||
fn translation(&self) -> (f32, f32) {
|
||||
(self.e, self.f)
|
||||
}
|
||||
|
||||
fn scale(&self) -> (f32, f32) {
|
||||
(self.a, self.d)
|
||||
}
|
||||
|
||||
fn skew(&self) -> (f32, f32) {
|
||||
(self.c, self.b)
|
||||
}
|
||||
}
|
71
render-wasm/src/shapes/transform.rs
Normal file
71
render-wasm/src/shapes/transform.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::matrix::Matrix;
|
||||
use crate::mem::SerializableResult;
|
||||
use crate::utils::{uuid_from_u32_quartet, uuid_to_u32_quartet};
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct TransformEntry {
|
||||
pub id: Uuid,
|
||||
pub transform: Matrix,
|
||||
}
|
||||
|
||||
impl SerializableResult for TransformEntry {
|
||||
type BytesType = [u8; size_of::<TransformEntry>()];
|
||||
|
||||
fn from_bytes(bytes: Self::BytesType) -> Self {
|
||||
let id = uuid_from_u32_quartet(
|
||||
u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
|
||||
u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
|
||||
u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]),
|
||||
u32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]),
|
||||
);
|
||||
|
||||
let transform = Matrix::new(
|
||||
f32::from_le_bytes([bytes[16], bytes[17], bytes[18], bytes[19]]),
|
||||
f32::from_le_bytes([bytes[20], bytes[21], bytes[22], bytes[23]]),
|
||||
f32::from_le_bytes([bytes[24], bytes[25], bytes[26], bytes[27]]),
|
||||
f32::from_le_bytes([bytes[28], bytes[29], bytes[30], bytes[31]]),
|
||||
f32::from_le_bytes([bytes[32], bytes[33], bytes[34], bytes[35]]),
|
||||
f32::from_le_bytes([bytes[36], bytes[37], bytes[38], bytes[39]]),
|
||||
);
|
||||
|
||||
TransformEntry { id, transform }
|
||||
}
|
||||
|
||||
fn as_bytes(&self) -> Self::BytesType {
|
||||
let mut result: [u8; 40] = [0; 40];
|
||||
let (a, b, c, d) = uuid_to_u32_quartet(&self.id);
|
||||
result[0..4].clone_from_slice(&a.to_le_bytes());
|
||||
result[4..8].clone_from_slice(&b.to_le_bytes());
|
||||
result[8..12].clone_from_slice(&c.to_le_bytes());
|
||||
result[12..16].clone_from_slice(&d.to_le_bytes());
|
||||
result[16..40].clone_from_slice(&self.transform.as_bytes());
|
||||
result
|
||||
}
|
||||
|
||||
// The generic trait doesn't know the size of the array. This is why the
|
||||
// clone needs to be here even if it could be generic.
|
||||
fn clone_to_slice(&self, slice: &mut [u8]) {
|
||||
slice.clone_from_slice(&self.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use uuid::uuid;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
let entry = TransformEntry {
|
||||
id: uuid!("550e8400-e29b-41d4-a716-446655440000"),
|
||||
transform: Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0),
|
||||
};
|
||||
|
||||
let bytes = entry.as_bytes();
|
||||
|
||||
assert_eq!(entry, TransformEntry::from_bytes(bytes));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue