typst/src/geom/transform.rs
2021-11-23 22:04:08 +01:00

74 lines
1.9 KiB
Rust

use super::*;
/// A scale-skew-translate transformation.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct Transform {
pub sx: Relative,
pub ky: Relative,
pub kx: Relative,
pub sy: Relative,
pub tx: Length,
pub ty: Length,
}
impl Transform {
/// The identity transformation.
pub const fn identity() -> Self {
Self {
sx: Relative::one(),
ky: Relative::zero(),
kx: Relative::zero(),
sy: Relative::one(),
tx: Length::zero(),
ty: Length::zero(),
}
}
/// A translation transform.
pub const fn translation(tx: Length, ty: Length) -> Self {
Self { tx, ty, ..Self::identity() }
}
/// A scaling transform.
pub const fn scaling(sx: Relative, sy: Relative) -> Self {
Self { sx, sy, ..Self::identity() }
}
/// A rotation transform.
pub fn rotation(angle: Angle) -> Self {
let v = angle.to_rad();
let cos = Relative::new(v.cos());
let sin = Relative::new(v.sin());
Self {
sx: cos,
ky: sin,
kx: -sin,
sy: cos,
..Self::default()
}
}
/// Whether this is the identity transformation.
pub fn is_identity(&self) -> bool {
*self == Self::identity()
}
/// Pre-concatenate another transformation.
pub fn pre_concat(&self, prev: Self) -> Self {
Transform {
sx: self.sx * prev.sx + self.kx * prev.ky,
ky: self.ky * prev.sx + self.sy * prev.ky,
kx: self.sx * prev.kx + self.kx * prev.sy,
sy: self.ky * prev.kx + self.sy * prev.sy,
tx: self.sx.resolve(prev.tx) + self.kx.resolve(prev.ty) + self.tx,
ty: self.ky.resolve(prev.tx) + self.sy.resolve(prev.ty) + self.ty,
}
}
}
impl Default for Transform {
fn default() -> Self {
Self::identity()
}
}