use crate::*; use std::fmt::Debug; pub trait Area: From<[N;4]> + Debug + Copy { fn x (&self) -> N; fn y (&self) -> N; fn w (&self) -> N; fn h (&self) -> N; #[inline] fn zero () -> [N;4] { [N::zero(), N::zero(), N::zero(), N::zero()] } #[inline] fn from_position (pos: impl Size) -> [N;4] { let [x, y] = pos.wh(); [x, y, 0.into(), 0.into()] } #[inline] fn from_size (size: impl Size) -> [N;4] { let [w, h] = size.wh(); [0.into(), 0.into(), w, h] } #[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> { if self.w() < w || self.h() < h { Err(format!("min {w}x{h}").into()) } else { Ok(self) } } #[inline] fn xy (&self) -> [N;2] { [self.x(), self.y()] } #[inline] fn wh (&self) -> [N;2] { [self.w(), self.h()] } #[inline] fn xywh (&self) -> [N;4] { [self.x(), self.y(), self.w(), self.h()] } #[inline] fn clip_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h().min(h)] } #[inline] fn clip_w (&self, w: N) -> [N;4] { [self.x(), self.y(), self.w().min(w), self.h()] } #[inline] fn clip (&self, wh: impl Size) -> [N;4] { [self.x(), self.y(), wh.w(), wh.h()] } #[inline] fn set_w (&self, w: N) -> [N;4] { [self.x(), self.y(), w, self.h()] } #[inline] fn set_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), h] } #[inline] fn x2 (&self) -> N { self.x().plus(self.w()) } #[inline] fn y2 (&self) -> N { self.y().plus(self.h()) } #[inline] fn lrtb (&self) -> [N;4] { [self.x(), self.x2(), self.y(), self.y2()] } #[inline] fn center (&self) -> [N;2] { [self.x().plus(self.w()/2.into()), self.y().plus(self.h()/2.into())] } #[inline] fn center_x (&self, n: N) -> [N;4] { let [x, y, w, h] = self.xywh(); [(x.plus(w / 2.into())).minus(n / 2.into()), y.plus(h / 2.into()), n, 1.into()] } #[inline] fn center_y (&self, n: N) -> [N;4] { let [x, y, w, h] = self.xywh(); [x.plus(w / 2.into()), (y.plus(h / 2.into())).minus(n / 2.into()), 1.into(), n] } #[inline] fn center_xy (&self, [n, m]: [N;2]) -> [N;4] { let [x, y, w, h] = self.xywh(); [(x.plus(w / 2.into())).minus(n / 2.into()), (y.plus(h / 2.into())).minus(m / 2.into()), n, m] } #[inline] fn centered (&self) -> [N;2] { [self.x().minus(self.w()/2.into()), self.y().minus(self.h()/2.into())] } } impl Area for (N, N, N, N) { #[inline] fn x (&self) -> N { self.0 } #[inline] fn y (&self) -> N { self.1 } #[inline] fn w (&self) -> N { self.2 } #[inline] fn h (&self) -> N { self.3 } } impl Area for [N;4] { #[inline] fn x (&self) -> N { self[0] } #[inline] fn y (&self) -> N { self[1] } #[inline] fn w (&self) -> N { self[2] } #[inline] fn h (&self) -> N { self[3] } } #[cfg(test)] mod test_area { use super::*; use proptest::prelude::*; proptest! { #[test] fn test_area_prop ( x in u16::MIN..u16::MAX, y in u16::MIN..u16::MAX, w in u16::MIN..u16::MAX, h in u16::MIN..u16::MAX, a in u16::MIN..u16::MAX, b in u16::MIN..u16::MAX, ) { let _: [u16;4] = <[u16;4] as Area>::zero(); let _: [u16;4] = <[u16;4] as Area>::from_position([a, b]); let _: [u16;4] = <[u16;4] as Area>::from_size([a, b]); let area: [u16;4] = [x, y, w, h]; let _ = area.expect_min(a, b); let _ = area.xy(); let _ = area.wh(); let _ = area.xywh(); let _ = area.clip_h(a); let _ = area.clip_w(b); let _ = area.clip([a, b]); let _ = area.set_w(a); let _ = area.set_h(b); let _ = area.x2(); let _ = area.y2(); let _ = area.lrtb(); let _ = area.center(); let _ = area.center_x(a); let _ = area.center_y(b); let _ = area.center_xy([a, b]); let _ = area.centered(); } } }