mirror of
https://github.com/penpot/penpot.git
synced 2026-05-23 08:53:39 +00:00
* 🔧 Autogenerate serialization values for wasm enums * 🔧 Add serializer values to the wasm api * ✨ Avoid converting to a clojure map the serializer js object * 🔧 Update watch script for autoserialized enums * 🐛 Fix missing serializer values
165 lines
5.5 KiB
Rust
165 lines
5.5 KiB
Rust
use crate::math::{Bounds, Matrix};
|
|
use crate::shapes::{ConstraintH, ConstraintV};
|
|
|
|
pub fn calculate_resize(
|
|
constraint_h: ConstraintH,
|
|
constraint_v: ConstraintV,
|
|
parent_before: &Bounds,
|
|
parent_after: &Bounds,
|
|
child_before: &Bounds,
|
|
child_after: &Bounds,
|
|
) -> Option<(f32, f32)> {
|
|
let scale_width = match constraint_h {
|
|
ConstraintH::Left | ConstraintH::Right | ConstraintH::Center => {
|
|
parent_before.width() / f32::max(0.01, parent_after.width())
|
|
}
|
|
ConstraintH::Leftright => {
|
|
let left = parent_before.left(child_before.nw);
|
|
let right = parent_before.right(child_before.ne);
|
|
let target_width = parent_after.width() - left - right;
|
|
target_width / f32::max(0.01, child_after.width())
|
|
}
|
|
_ => 1.0,
|
|
};
|
|
|
|
let scale_height = match constraint_v {
|
|
ConstraintV::Top | ConstraintV::Bottom | ConstraintV::Center => {
|
|
parent_before.height() / f32::max(0.01, parent_after.height())
|
|
}
|
|
ConstraintV::Topbottom => {
|
|
let top = parent_before.top(child_before.nw);
|
|
let bottom = parent_before.bottom(child_before.sw);
|
|
let target_height = parent_after.height() - top - bottom;
|
|
target_height / f32::max(0.01, child_after.height())
|
|
}
|
|
_ => 1.0,
|
|
};
|
|
|
|
if (scale_width - 1.0).abs() < f32::EPSILON && (scale_height - 1.0).abs() < f32::EPSILON {
|
|
None
|
|
} else {
|
|
Some((scale_width, scale_height))
|
|
}
|
|
}
|
|
|
|
pub fn calculate_displacement(
|
|
constraint_h: ConstraintH,
|
|
constraint_v: ConstraintV,
|
|
parent_before: &Bounds,
|
|
parent_after: &Bounds,
|
|
child_before: &Bounds,
|
|
child_after: &Bounds,
|
|
) -> Option<(f32, f32)> {
|
|
let delta_x = match constraint_h {
|
|
ConstraintH::Left | ConstraintH::Leftright => {
|
|
let target_left = parent_before.left(child_before.nw);
|
|
let current_left = parent_after.left(child_after.nw);
|
|
target_left - current_left
|
|
}
|
|
ConstraintH::Right => {
|
|
let target_right = parent_before.right(child_before.ne);
|
|
let current_right = parent_after.right(child_after.ne);
|
|
current_right - target_right
|
|
}
|
|
ConstraintH::Center => {
|
|
let delta_width = parent_after.width() - parent_before.width();
|
|
let target_left = parent_before.left(child_before.nw);
|
|
let current_left = parent_after.left(child_after.nw);
|
|
target_left - current_left + delta_width / 2.0
|
|
}
|
|
_ => 0.0,
|
|
};
|
|
|
|
let delta_y = match constraint_v {
|
|
ConstraintV::Top | ConstraintV::Topbottom => {
|
|
let target_top = parent_before.top(child_before.nw);
|
|
let current_top = parent_after.top(child_after.nw);
|
|
target_top - current_top
|
|
}
|
|
ConstraintV::Bottom => {
|
|
let target_bottom = parent_before.bottom(child_before.ne);
|
|
let current_bottom = parent_after.bottom(child_after.ne);
|
|
current_bottom - target_bottom
|
|
}
|
|
ConstraintV::Center => {
|
|
let delta_height = parent_after.height() - parent_before.height();
|
|
let target_top = parent_before.top(child_before.nw);
|
|
let current_top = parent_after.top(child_after.nw);
|
|
target_top - current_top + delta_height / 2.0
|
|
}
|
|
_ => 0.0,
|
|
};
|
|
|
|
if delta_x.abs() < f32::EPSILON && delta_y.abs() < f32::EPSILON {
|
|
None
|
|
} else {
|
|
Some((delta_x, delta_y))
|
|
}
|
|
}
|
|
|
|
pub fn propagate_shape_constraints(
|
|
parent_bounds_before: &Bounds,
|
|
parent_bounds_after: &Bounds,
|
|
child_bounds_before: &Bounds,
|
|
constraint_h: ConstraintH,
|
|
constraint_v: ConstraintV,
|
|
transform: Matrix,
|
|
ignore_constrainst: bool,
|
|
) -> Matrix {
|
|
// if the constrains are scale & scale or the transform has only moves we
|
|
// can propagate as is
|
|
if (ignore_constrainst
|
|
|| constraint_h == ConstraintH::Scale && constraint_v == ConstraintV::Scale)
|
|
|| transform.is_translate()
|
|
{
|
|
return transform;
|
|
}
|
|
|
|
let mut transform = transform;
|
|
let mut child_bounds_after = child_bounds_before.transform(&transform);
|
|
|
|
// Scale shape
|
|
if let Some((scale_width, scale_height)) = calculate_resize(
|
|
constraint_h,
|
|
constraint_v,
|
|
parent_bounds_before,
|
|
parent_bounds_after,
|
|
child_bounds_before,
|
|
&child_bounds_after,
|
|
) {
|
|
let center = child_bounds_before.center();
|
|
|
|
let mut parent_transform = parent_bounds_after.transform_matrix().unwrap_or_default();
|
|
parent_transform.post_translate(center);
|
|
parent_transform.pre_translate(-center);
|
|
|
|
let parent_transform_inv = &parent_transform.invert().unwrap();
|
|
let origin = parent_transform_inv.map_point(child_bounds_after.nw);
|
|
|
|
let mut scale = Matrix::scale((scale_width, scale_height));
|
|
scale.post_translate(origin);
|
|
scale.post_concat(&parent_transform);
|
|
scale.pre_translate(-origin);
|
|
scale.pre_concat(parent_transform_inv);
|
|
|
|
child_bounds_after.transform_mut(&scale);
|
|
transform.post_concat(&scale);
|
|
}
|
|
|
|
// Translate position
|
|
if let Some((delta_x, delta_y)) = calculate_displacement(
|
|
constraint_h,
|
|
constraint_v,
|
|
parent_bounds_before,
|
|
parent_bounds_after,
|
|
child_bounds_before,
|
|
&child_bounds_after,
|
|
) {
|
|
let th = parent_bounds_after.hv(delta_x);
|
|
let tv = parent_bounds_after.vv(delta_y);
|
|
transform.post_concat(&Matrix::translate(th + tv));
|
|
}
|
|
|
|
transform
|
|
}
|