use windows_numerics::Matrix3x2;
use super::{Offset, Size};
use crate::ecs::types::{PointF, Rect};
pub type D2DRect = Rect;
pub trait D2DRectExt {
fn from_offset_size(offset: Offset, size: Size) -> Self;
fn width(&self) -> f32;
fn height(&self) -> f32;
fn offset(&self) -> PointF;
fn size(&self) -> Size;
fn set_offset(&mut self, offset: PointF);
fn set_size(&mut self, size: Size);
fn set_left(&mut self, left: f32);
fn set_top(&mut self, top: f32);
fn set_right(&mut self, right: f32);
fn set_bottom(&mut self, bottom: f32);
fn contains(&self, x: f32, y: f32) -> bool;
fn union(&self, other: &Self) -> Self;
#[cfg(debug_assertions)]
fn validate(&self);
}
impl D2DRectExt for Rect {
fn from_offset_size(offset: Offset, size: Size) -> Self {
Rect {
left: offset.x,
top: offset.y,
right: offset.x + size.width,
bottom: offset.y + size.height,
}
}
fn width(&self) -> f32 {
self.right - self.left
}
fn height(&self) -> f32 {
self.bottom - self.top
}
fn offset(&self) -> PointF {
PointF {
x: self.left,
y: self.top,
}
}
fn size(&self) -> Size {
Size {
width: self.width(),
height: self.height(),
}
}
fn set_offset(&mut self, offset: PointF) {
let w = self.width();
let h = self.height();
self.left = offset.x;
self.top = offset.y;
self.right = offset.x + w;
self.bottom = offset.y + h;
}
fn set_size(&mut self, size: Size) {
self.right = self.left + size.width;
self.bottom = self.top + size.height;
}
fn set_left(&mut self, left: f32) {
self.left = left;
}
fn set_top(&mut self, top: f32) {
self.top = top;
}
fn set_right(&mut self, right: f32) {
self.right = right;
}
fn set_bottom(&mut self, bottom: f32) {
self.bottom = bottom;
}
fn contains(&self, x: f32, y: f32) -> bool {
x >= self.left && x <= self.right && y >= self.top && y <= self.bottom
}
fn union(&self, other: &Self) -> Self {
Rect {
left: self.left.min(other.left),
top: self.top.min(other.top),
right: self.right.max(other.right),
bottom: self.bottom.max(other.bottom),
}
}
#[cfg(debug_assertions)]
fn validate(&self) {
debug_assert!(self.left <= self.right, "Invalid rect: left > right");
debug_assert!(self.top <= self.bottom, "Invalid rect: top > bottom");
}
}
pub fn transform_rect_axis_aligned(rect: &Rect, matrix: &Matrix3x2) -> Rect {
let top_left_x = matrix.M11 * rect.left + matrix.M21 * rect.top + matrix.M31;
let top_left_y = matrix.M12 * rect.left + matrix.M22 * rect.top + matrix.M32;
let bottom_right_x = matrix.M11 * rect.right + matrix.M21 * rect.bottom + matrix.M31;
let bottom_right_y = matrix.M12 * rect.right + matrix.M22 * rect.bottom + matrix.M32;
Rect {
left: top_left_x.min(bottom_right_x),
top: top_left_y.min(bottom_right_y),
right: top_left_x.max(bottom_right_x),
bottom: top_left_y.max(bottom_right_y),
}
}