use bytemuck::{Pod, Zeroable}; use core::fmt::Debug; use derive_more::{Add, AddAssign, Div, Mul, Sub, SubAssign}; use refineable::Refineable; use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Sub, SubAssign}; #[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)] #[refineable(debug)] #[repr(C)] pub struct Point { pub x: T, pub y: T, } pub fn point(x: T, y: T) -> Point { Point { x, y } } impl Point { pub fn new(x: T, y: T) -> Self { Self { x, y } } pub fn map U>(&self, f: F) -> Point { Point { x: f(self.x.clone()), y: f(self.y.clone()), } } } impl Mul for Point where T: Mul + Clone + Debug, Rhs: Clone + Debug, { type Output = Point; fn mul(self, rhs: Rhs) -> Self::Output { Point { x: self.x * rhs.clone(), y: self.y * rhs, } } } impl, S: Clone> MulAssign for Point { fn mul_assign(&mut self, rhs: S) { self.x = self.x.clone() * rhs.clone(); self.y = self.y.clone() * rhs; } } impl> SubAssign> for Point { fn sub_assign(&mut self, rhs: Size) { self.x = self.x.clone() - rhs.width; self.y = self.y.clone() - rhs.height; } } impl + Copy> AddAssign for Point { fn add_assign(&mut self, rhs: T) { self.x = self.x.clone() + rhs; self.y = self.y.clone() + rhs; } } impl, S: Clone> Div for Point { type Output = Self; fn div(self, rhs: S) -> Self::Output { Self { x: self.x / rhs.clone(), y: self.y / rhs, } } } impl Point { pub fn max(&self, other: &Self) -> Self { Point { x: if self.x >= other.x { self.x.clone() } else { other.x.clone() }, y: if self.y >= other.y { self.y.clone() } else { other.y.clone() }, } } } impl Clone for Point { fn clone(&self) -> Self { Self { x: self.x.clone(), y: self.y.clone(), } } } unsafe impl Zeroable for Point {} unsafe impl Pod for Point {} #[derive(Refineable, Default, Clone, Copy, Debug, PartialEq, Div)] #[refineable(debug)] #[repr(C)] pub struct Size { pub width: T, pub height: T, } unsafe impl Zeroable for Size {} unsafe impl Pod for Size {} pub fn size(width: T, height: T) -> Size { Size { width, height } } impl Size { pub fn map U>(&self, f: F) -> Size { Size { width: f(self.width.clone()), height: f(self.height.clone()), } } } impl Mul for Size where T: Mul + Debug + Clone, Rhs: Debug + Clone, { type Output = Size; fn mul(self, rhs: Rhs) -> Self::Output { Size { width: self.width * rhs.clone(), height: self.height * rhs, } } } impl, S: Clone> MulAssign for Size { fn mul_assign(&mut self, rhs: S) { self.width = self.width.clone() * rhs.clone(); self.height = self.height.clone() * rhs; } } impl From>> for Size> { fn from(val: Size>) -> Self { Size { width: val.width.map(|p| p.0 as f32), height: val.height.map(|p| p.0 as f32), } } } impl Size { pub fn full() -> Self { Self { width: relative(1.).into(), height: relative(1.).into(), } } } impl Size { pub fn zero() -> Self { Self { width: px(0.).into(), height: px(0.).into(), } } } impl Size { pub fn auto() -> Self { Self { width: Length::Auto, height: Length::Auto, } } } #[derive(Refineable, Clone, Default, Debug, PartialEq)] #[refineable(debug)] #[repr(C)] pub struct Bounds { pub origin: Point, pub size: Size, } unsafe impl Zeroable for Bounds {} unsafe impl Pod for Bounds {} // Bounds * Pixels = Bounds impl Mul for Bounds where T: Mul + Clone + Debug, Rhs: Clone + Debug, { type Output = Bounds; fn mul(self, rhs: Rhs) -> Self::Output { Bounds { origin: self.origin * rhs.clone(), size: self.size * rhs, } } } impl, S: Clone> MulAssign for Bounds { fn mul_assign(&mut self, rhs: S) { self.origin *= rhs.clone(); self.size *= rhs; } } impl, S: Clone> Div for Bounds where Size: Div>, { type Output = Self; fn div(self, rhs: S) -> Self { Self { origin: self.origin / rhs.clone(), size: self.size / rhs, } } } impl> Bounds { pub fn upper_right(&self) -> Point { Point { x: self.origin.x.clone() + self.size.width.clone(), y: self.origin.y.clone(), } } pub fn lower_right(&self) -> Point { Point { x: self.origin.x.clone() + self.size.width.clone(), y: self.origin.y.clone() + self.size.height.clone(), } } } impl> Bounds { pub fn contains_point(&self, point: Point) -> bool { point.x >= self.origin.x && point.x <= self.origin.x.clone() + self.size.width.clone() && point.y >= self.origin.y && point.y <= self.origin.y.clone() + self.size.height.clone() } pub fn map U>(&self, f: F) -> Bounds { Bounds { origin: self.origin.map(&f), size: self.size.map(f), } } } impl Copy for Bounds {} #[derive(Refineable, Clone, Default, Debug)] #[refineable(debug)] #[repr(C)] pub struct Edges { pub top: T, pub right: T, pub bottom: T, pub left: T, } impl> Mul for Edges { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Self { top: self.top.clone() * rhs.top, right: self.right.clone() * rhs.right, bottom: self.bottom.clone() * rhs.bottom, left: self.left.clone() * rhs.left, } } } impl, S: Clone> MulAssign for Edges { fn mul_assign(&mut self, rhs: S) { self.top = self.top.clone() * rhs.clone(); self.right = self.right.clone() * rhs.clone(); self.bottom = self.bottom.clone() * rhs.clone(); self.left = self.left.clone() * rhs.clone(); } } impl Copy for Edges {} unsafe impl Zeroable for Edges {} unsafe impl Pod for Edges {} impl Edges { pub fn auto() -> Self { Self { top: Length::Auto, right: Length::Auto, bottom: Length::Auto, left: Length::Auto, } } pub fn zero() -> Self { Self { top: px(0.).into(), right: px(0.).into(), bottom: px(0.).into(), left: px(0.).into(), } } } impl Edges { pub fn zero() -> Self { Self { top: px(0.).into(), right: px(0.).into(), bottom: px(0.).into(), left: px(0.).into(), } } } impl Edges { pub fn zero() -> Self { Self { top: px(0.).into(), right: px(0.).into(), bottom: px(0.).into(), left: px(0.).into(), } } pub fn to_pixels(&self, rem_size: Pixels) -> Edges { Edges { top: self.top.to_pixels(rem_size), right: self.right.to_pixels(rem_size), bottom: self.bottom.to_pixels(rem_size), left: self.left.to_pixels(rem_size), } } } impl Edges { pub fn is_empty(&self) -> bool { self.top == px(0.) && self.right == px(0.) && self.bottom == px(0.) && self.left == px(0.) } } #[derive(Refineable, Clone, Default, Debug)] #[refineable(debug)] #[repr(C)] pub struct Corners { pub top_left: T, pub top_right: T, pub bottom_right: T, pub bottom_left: T, } impl> Mul for Corners { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Self { top_left: self.top_left.clone() * rhs.top_left, top_right: self.top_right.clone() * rhs.top_right, bottom_right: self.bottom_right.clone() * rhs.bottom_right, bottom_left: self.bottom_left.clone() * rhs.bottom_left, } } } impl, S: Clone> MulAssign for Corners { fn mul_assign(&mut self, rhs: S) { self.top_left = self.top_left.clone() * rhs.clone(); self.top_right = self.top_right.clone() * rhs.clone(); self.bottom_right = self.bottom_right.clone() * rhs.clone(); self.bottom_left = self.bottom_left.clone() * rhs; } } impl Copy for Corners {} unsafe impl Zeroable for Corners {} unsafe impl Pod for Corners {} #[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)] #[repr(transparent)] pub struct Pixels(pub(crate) f32); impl Mul for Pixels { type Output = Pixels; fn mul(self, other: f32) -> Pixels { Pixels(self.0 * other) } } impl Mul for f32 { type Output = Pixels; fn mul(self, rhs: Pixels) -> Self::Output { Pixels(self * rhs.0) } } impl Pixels { pub fn round(&self) -> Self { Self(self.0.round()) } pub fn to_device_pixels(&self, scale: f32) -> DevicePixels { DevicePixels((self.0 * scale).ceil() as u32) } } impl Mul for Pixels { type Output = Pixels; fn mul(self, rhs: Pixels) -> Self::Output { Pixels(self.0 * rhs.0) } } impl Eq for Pixels {} impl Ord for Pixels { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.0.partial_cmp(&other.0).unwrap() } } impl std::hash::Hash for Pixels { fn hash(&self, state: &mut H) { self.0.to_bits().hash(state); } } impl From for Pixels { fn from(val: f64) -> Self { Pixels(val as f32) } } impl From for Pixels { fn from(val: f32) -> Self { Pixels(val) } } unsafe impl bytemuck::Pod for Pixels {} unsafe impl bytemuck::Zeroable for Pixels {} impl Debug for Pixels { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} px", self.0) } } impl From for f32 { fn from(pixels: Pixels) -> Self { pixels.0 } } impl From<&Pixels> for f32 { fn from(pixels: &Pixels) -> Self { pixels.0 } } impl From for f64 { fn from(pixels: Pixels) -> Self { pixels.0 as f64 } } #[derive( Clone, Copy, Debug, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd, )] #[repr(transparent)] pub struct DevicePixels(pub(crate) u32); unsafe impl bytemuck::Pod for DevicePixels {} unsafe impl bytemuck::Zeroable for DevicePixels {} impl From for u32 { fn from(device_pixels: DevicePixels) -> Self { device_pixels.0 } } impl From for DevicePixels { fn from(val: u32) -> Self { DevicePixels(val) } } #[derive(Clone, Copy, Default, Add, Sub, Mul, Div)] pub struct Rems(f32); impl Mul for Rems { type Output = Pixels; fn mul(self, other: Pixels) -> Pixels { Pixels(self.0 * other.0) } } impl Debug for Rems { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} rem", self.0) } } #[derive(Clone, Copy, Debug)] pub enum AbsoluteLength { Pixels(Pixels), Rems(Rems), } impl From for AbsoluteLength { fn from(pixels: Pixels) -> Self { AbsoluteLength::Pixels(pixels) } } impl From for AbsoluteLength { fn from(rems: Rems) -> Self { AbsoluteLength::Rems(rems) } } impl AbsoluteLength { pub fn to_pixels(&self, rem_size: Pixels) -> Pixels { match self { AbsoluteLength::Pixels(pixels) => *pixels, AbsoluteLength::Rems(rems) => *rems * rem_size, } } } impl Default for AbsoluteLength { fn default() -> Self { px(0.).into() } } /// A non-auto length that can be defined in pixels, rems, or percent of parent. #[derive(Clone, Copy)] pub enum DefiniteLength { Absolute(AbsoluteLength), /// A fraction of the parent's size between 0 and 1. Fraction(f32), } impl DefiniteLength { pub fn to_pixels(&self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels { match self { DefiniteLength::Absolute(size) => size.to_pixels(rem_size), DefiniteLength::Fraction(fraction) => match base_size { AbsoluteLength::Pixels(px) => px * *fraction, AbsoluteLength::Rems(rems) => rems * rem_size * *fraction, }, } } } impl Debug for DefiniteLength { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { DefiniteLength::Absolute(length) => Debug::fmt(length, f), DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32), } } } impl From for DefiniteLength { fn from(pixels: Pixels) -> Self { Self::Absolute(pixels.into()) } } impl From for DefiniteLength { fn from(rems: Rems) -> Self { Self::Absolute(rems.into()) } } impl From for DefiniteLength { fn from(length: AbsoluteLength) -> Self { Self::Absolute(length) } } impl Default for DefiniteLength { fn default() -> Self { Self::Absolute(AbsoluteLength::default()) } } /// A length that can be defined in pixels, rems, percent of parent, or auto. #[derive(Clone, Copy)] pub enum Length { Definite(DefiniteLength), Auto, } impl Debug for Length { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Length::Definite(definite_length) => write!(f, "{:?}", definite_length), Length::Auto => write!(f, "auto"), } } } pub fn relative(fraction: f32) -> DefiniteLength { DefiniteLength::Fraction(fraction).into() } /// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`. pub fn phi() -> DefiniteLength { relative(1.61803398875) } pub fn rems(rems: f32) -> Rems { Rems(rems) } pub fn px(pixels: f32) -> Pixels { Pixels(pixels) } pub fn auto() -> Length { Length::Auto } impl From for Length { fn from(pixels: Pixels) -> Self { Self::Definite(pixels.into()) } } impl From for Length { fn from(rems: Rems) -> Self { Self::Definite(rems.into()) } } impl From for Length { fn from(length: DefiniteLength) -> Self { Self::Definite(length) } } impl From for Length { fn from(length: AbsoluteLength) -> Self { Self::Definite(length.into()) } } impl Default for Length { fn default() -> Self { Self::Definite(DefiniteLength::default()) } } impl From<()> for Length { fn from(_: ()) -> Self { Self::Definite(DefiniteLength::default()) } }