83 lines
2.1 KiB
Rust
83 lines
2.1 KiB
Rust
use super::*;
|
|
|
|
/// A scale-skew-translate transformation.
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
pub struct Transform {
|
|
pub sx: Ratio,
|
|
pub ky: Ratio,
|
|
pub kx: Ratio,
|
|
pub sy: Ratio,
|
|
pub tx: Length,
|
|
pub ty: Length,
|
|
}
|
|
|
|
impl Transform {
|
|
/// The identity transformation.
|
|
pub const fn identity() -> Self {
|
|
Self {
|
|
sx: Ratio::one(),
|
|
ky: Ratio::zero(),
|
|
kx: Ratio::zero(),
|
|
sy: Ratio::one(),
|
|
tx: Length::zero(),
|
|
ty: Length::zero(),
|
|
}
|
|
}
|
|
|
|
/// Transform by mirroring along the x-axis.
|
|
pub fn mirror_x() -> Self {
|
|
Self::scale(Ratio::one(), -Ratio::one())
|
|
}
|
|
|
|
/// Transform by mirroring along the y-axis.
|
|
pub fn mirror_y() -> Self {
|
|
Self::scale(-Ratio::one(), Ratio::one())
|
|
}
|
|
|
|
/// A translate transform.
|
|
pub const fn translate(tx: Length, ty: Length) -> Self {
|
|
Self { tx, ty, ..Self::identity() }
|
|
}
|
|
|
|
/// A scale transform.
|
|
pub const fn scale(sx: Ratio, sy: Ratio) -> Self {
|
|
Self { sx, sy, ..Self::identity() }
|
|
}
|
|
|
|
/// A rotate transform.
|
|
pub fn rotate(angle: Angle) -> Self {
|
|
let cos = Ratio::new(angle.cos());
|
|
let sin = Ratio::new(angle.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.of(prev.tx) + self.kx.of(prev.ty) + self.tx,
|
|
ty: self.ky.of(prev.tx) + self.sy.of(prev.ty) + self.ty,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Transform {
|
|
fn default() -> Self {
|
|
Self::identity()
|
|
}
|
|
}
|