use crate::units::Pt;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Transform {
pub translate_x: Pt,
pub translate_y: Pt,
pub rotate_degrees: f64,
pub scale_x: f64,
pub scale_y: f64,
}
impl Default for Transform {
fn default() -> Self {
Self {
translate_x: Pt::ZERO,
translate_y: Pt::ZERO,
rotate_degrees: 0.0,
scale_x: 1.0,
scale_y: 1.0,
}
}
}
impl Transform {
#[must_use]
pub fn to_pdf_matrix(&self) -> [f32; 6] {
let theta = self.rotate_degrees.to_radians();
let cos_t = theta.cos() as f32;
let sin_t = theta.sin() as f32;
let sx = self.scale_x as f32;
let sy = self.scale_y as f32;
[
cos_t * sx,
sin_t * sx,
-sin_t * sy,
cos_t * sy,
self.translate_x.get() as f32,
self.translate_y.get() as f32,
]
}
#[must_use]
pub fn is_identity(&self) -> bool {
self.translate_x.get() == 0.0
&& self.translate_y.get() == 0.0
&& self.rotate_degrees == 0.0
&& (self.scale_x - 1.0).abs() < 1e-6
&& (self.scale_y - 1.0).abs() < 1e-6
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn identity_transform() {
let t = Transform::default();
assert!(t.is_identity());
let m = t.to_pdf_matrix();
assert!((m[0] - 1.0).abs() < 0.001); assert!((m[3] - 1.0).abs() < 0.001); }
#[test]
fn translate_only() {
let t = Transform {
translate_x: Pt::new(10.0),
translate_y: Pt::new(20.0),
..Transform::default()
};
assert!(!t.is_identity());
let m = t.to_pdf_matrix();
assert!((m[4] - 10.0).abs() < 0.001);
assert!((m[5] - 20.0).abs() < 0.001);
}
#[test]
fn scale_only() {
let t = Transform {
scale_x: 2.0,
scale_y: 0.5,
..Transform::default()
};
let m = t.to_pdf_matrix();
assert!((m[0] - 2.0).abs() < 0.001);
assert!((m[3] - 0.5).abs() < 0.001);
}
}