use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub};
#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
pub struct Pixels(pub f32);
pub const fn px(value: f32) -> Pixels {
Pixels(value)
}
impl Pixels {
pub const ZERO: Pixels = Pixels(0.0);
pub fn max(self, other: Pixels) -> Pixels {
Pixels(self.0.max(other.0))
}
pub fn min(self, other: Pixels) -> Pixels {
Pixels(self.0.min(other.0))
}
}
impl Add for Pixels {
type Output = Pixels;
fn add(self, rhs: Pixels) -> Pixels {
Pixels(self.0 + rhs.0)
}
}
impl AddAssign for Pixels {
fn add_assign(&mut self, rhs: Pixels) {
self.0 += rhs.0;
}
}
impl Sub for Pixels {
type Output = Pixels;
fn sub(self, rhs: Pixels) -> Pixels {
Pixels(self.0 - rhs.0)
}
}
impl Mul<f32> for Pixels {
type Output = Pixels;
fn mul(self, rhs: f32) -> Pixels {
Pixels(self.0 * rhs)
}
}
impl Div<f32> for Pixels {
type Output = Pixels;
fn div(self, rhs: f32) -> Pixels {
Pixels(self.0 / rhs)
}
}
impl Neg for Pixels {
type Output = Pixels;
fn neg(self) -> Pixels {
Pixels(-self.0)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Point {
pub x: Pixels,
pub y: Pixels,
}
impl Point {
pub const fn new(x: Pixels, y: Pixels) -> Self {
Self { x, y }
}
}
impl Add for Point {
type Output = Point;
fn add(self, rhs: Point) -> Point {
Point::new(self.x + rhs.x, self.y + rhs.y)
}
}
impl Sub for Point {
type Output = Point;
fn sub(self, rhs: Point) -> Point {
Point::new(self.x - rhs.x, self.y - rhs.y)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Size {
pub width: Pixels,
pub height: Pixels,
}
impl Size {
pub const fn new(width: Pixels, height: Pixels) -> Self {
Self { width, height }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Bounds {
pub origin: Point,
pub size: Size,
}
impl Bounds {
pub const fn new(origin: Point, size: Size) -> Self {
Self { origin, size }
}
pub fn right(&self) -> Pixels {
self.origin.x + self.size.width
}
pub fn bottom(&self) -> Pixels {
self.origin.y + self.size.height
}
pub fn contains(&self, point: Point) -> bool {
point.x >= self.origin.x && point.x < self.right() && point.y >= self.origin.y && point.y < self.bottom()
}
pub fn intersect(&self, other: &Bounds) -> Bounds {
let left = self.origin.x.max(other.origin.x);
let top = self.origin.y.max(other.origin.y);
let right = self.right().min(other.right());
let bottom = self.bottom().min(other.bottom());
Bounds::new(
Point::new(left, top),
Size::new((right - left).max(Pixels::ZERO), (bottom - top).max(Pixels::ZERO)),
)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Edges {
pub top: Pixels,
pub right: Pixels,
pub bottom: Pixels,
pub left: Pixels,
}
impl Edges {
pub const fn all(value: Pixels) -> Self {
Self { top: value, right: value, bottom: value, left: value }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Corners {
pub top_left: Pixels,
pub top_right: Pixels,
pub bottom_right: Pixels,
pub bottom_left: Pixels,
}
impl Corners {
pub const fn all(value: Pixels) -> Self {
Self { top_left: value, top_right: value, bottom_right: value, bottom_left: value }
}
}