use std::ops::Mul;
use windows::Foundation::Numerics::Matrix3x2;
use crate::{geometry::FRect, matrix::MatrixBackend, Float};
#[derive(Clone, Debug, PartialEq)]
pub struct D2DMatrix {
pub matrix: Matrix3x2,
}
impl Mul for D2DMatrix {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self {
matrix: self.matrix * rhs.matrix,
}
}
}
impl MatrixBackend for D2DMatrix {
fn identity() -> Self {
Self {
matrix: Matrix3x2::identity(),
}
}
fn from_row(scx: Float, sky: Float, skx: Float, scy: Float, tx: Float, ty: Float) -> Self {
Self {
matrix: Matrix3x2 {
M11: scx,
M12: sky,
M21: skx,
M22: scy,
M31: tx,
M32: ty,
},
}
}
fn from_translate(x: Float, y: Float) -> Self {
Self {
matrix: Matrix3x2::translation(x, y),
}
}
fn from_scale(x: Float, y: Float) -> Self {
Self {
matrix: Matrix3x2 {
M11: x,
M22: y,
..Default::default()
},
}
}
fn from_rotate(angle: Float) -> Self {
Self {
matrix: Matrix3x2::rotation(angle, 0.0, 0.0),
}
}
fn pre_rotate(&mut self, angle: Float) {
self.matrix = self.matrix * Self::rotate_matrix(angle);
}
fn pre_scale(&mut self, x: Float, y: Float) {
self.matrix = self.matrix * Self::scale_matrix(x, y);
}
fn pre_translate(&mut self, x: Float, y: Float) {
self.matrix = self.matrix * Matrix3x2::translation(x, y);
}
fn post_rotate(&mut self, angle: Float) {
self.matrix = Self::rotate_matrix(angle) * self.matrix;
}
fn post_scale(&mut self, x: Float, y: Float) {
self.matrix = Self::scale_matrix(x, y) * self.matrix;
}
fn post_translate(&mut self, x: Float, y: Float) {
self.matrix = Matrix3x2::translation(x, y) * self.matrix;
}
fn map_rect(&self, rect: FRect) -> FRect {
let (x1, y1) = self.map_point(rect.point.x, rect.point.y);
let (x2, y2) = self.map_point(rect.point.x + rect.size.width, rect.point.y);
let (x3, y3) = self.map_point(rect.point.x, rect.point.y + rect.size.height);
let (x4, y4) = self.map_point(rect.point.x + rect.size.width, rect.point.y + rect.size.height);
let min_x = x1.min(x2).min(x3).min(x4);
let min_y = y1.min(y2).min(y3).min(y4);
let max_x = x1.max(x2).max(x3).max(x4);
let max_y = y1.max(y2).max(y3).max(y4);
FRect::new(min_x, min_y, max_x - min_x, max_y - min_y)
}
}
impl D2DMatrix {
pub(super) fn from_matrix(matrix: Matrix3x2) -> Self {
Self {
matrix,
}
}
pub(super) fn scale_matrix(x: Float, y: Float) -> Matrix3x2 {
Matrix3x2 {
M11: x,
M22: y,
..Default::default()
}
}
pub(super) fn rotate_matrix(angle: Float) -> Matrix3x2 {
let cos_theta = angle.cos();
let sin_theta = angle.sin();
Matrix3x2 {
M11: cos_theta,
M12: sin_theta,
M21: -sin_theta,
M22: cos_theta,
..Default::default()
}
}
fn map_point(&self, x: Float, y: Float) -> (Float, Float) {
let mapped_x = self.matrix.M11 * x + self.matrix.M21 * y + self.matrix.M31;
let mapped_y = self.matrix.M12 * x + self.matrix.M22 * y + self.matrix.M32;
(mapped_x, mapped_y)
}
}