use crate::*; use std::fmt::{Debug, Display}; use std::ops::{Add, Sub, Mul, Div}; /// Platform backend. pub trait Engine: Send + Sync + Sized { /// Input event type type Input: Input; /// Result of handling input type Handled; /// Render target type Output: Output; /// Unit of length type Unit: Coordinate; /// Rectangle without offset type Size: Size + From<[Self::Unit;2]> + Debug + Copy; /// Rectangle with offset type Area: Area + From<[Self::Unit;4]> + Debug + Copy; /// Prepare before run fn setup (&mut self) -> Usually<()> { Ok(()) } /// True if done fn exited (&self) -> bool; /// Clean up after run fn teardown (&mut self) -> Usually<()> { Ok(()) } } /// A linear coordinate. pub trait Coordinate: Send + Sync + Copy + Add + Sub + Mul + Div + Ord + PartialEq + Eq + Debug + Display + Default + From + Into + Into + Into { #[inline] fn minus (self, other: Self) -> Self { if self >= other { self - other } else { 0.into() } } #[inline] fn zero () -> Self { 0.into() } } pub trait Size { fn x (&self) -> N; fn y (&self) -> N; #[inline] fn w (&self) -> N { self.x() } #[inline] fn h (&self) -> N { self.y() } #[inline] fn wh (&self) -> [N;2] { [self.x(), self.y()] } #[inline] fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w), self.h()] } #[inline] fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(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 zero () -> [N;2] { [N::zero(), N::zero()] } } impl Size for (N, N) { #[inline] fn x (&self) -> N { self.0 } #[inline] fn y (&self) -> N { self.1 } } impl Size for [N;2] { #[inline] fn x (&self) -> N { self[0] } #[inline] fn y (&self) -> N { self[1] } } pub trait Area { fn x (&self) -> N; fn y (&self) -> N; fn w (&self) -> N; fn h (&self) -> N; #[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 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() + self.w() } #[inline] fn y2 (&self) -> N { self.y() + self.h() } #[inline] fn lrtb (&self) -> [N;4] { [self.x(), self.x2(), self.y(), self.y2()] } #[inline] fn center (&self) -> [N;2] { [self.x() + self.w() / 2.into(), self.y() + self.h() / 2.into()] } fn zero () -> [N;4] { [N::zero(), N::zero(), N::zero(), N::zero()] } } 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] } }