ori_core/
unit.rs

1use std::{
2    fmt::Display,
3    hash::{Hash, Hasher},
4    mem,
5    ops::Range,
6};
7
8use glam::Vec2;
9pub use Unit::*;
10
11/// A unit of measurement. (eg. 10px, 10pt, 10%)
12#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
13pub enum Unit {
14    /// Unit of measurement in pixels. (eg. 10px)
15    ///
16    /// This is the default unit.
17    Px(f32),
18    /// Unit of measurement in points. (eg. 10pt)
19    ///
20    /// 1pt = 1/72 inch
21    Pt(f32),
22    /// Unit of measurement in percent. (eg. 10%)
23    ///
24    /// The percent is context specific, and is often relative
25    /// to the parent's size, but doesn't have to be.
26    Pc(f32),
27    /// Unit of measurement in viewport width. (eg. 10vw)
28    Vw(f32),
29    /// Unit of measurement in viewport height. (eg. 10vh)
30    Vh(f32),
31    /// Unit of measurement in em. (eg. 10em)
32    ///
33    /// 1em = the font size of the root.
34    /// 1em = 16px by default.
35    Em(f32),
36}
37
38impl Eq for Unit {}
39
40impl Hash for Unit {
41    fn hash<H: Hasher>(&self, state: &mut H) {
42        mem::discriminant(self).hash(state);
43
44        match self {
45            Px(value) => value.to_bits().hash(state),
46            Pt(value) => value.to_bits().hash(state),
47            Pc(value) => value.to_bits().hash(state),
48            Vw(value) => value.to_bits().hash(state),
49            Vh(value) => value.to_bits().hash(state),
50            Em(value) => value.to_bits().hash(state),
51        }
52    }
53}
54
55impl Default for Unit {
56    fn default() -> Self {
57        Self::ZERO
58    }
59}
60
61impl Unit {
62    pub const ZERO: Self = Px(0.0);
63
64    pub fn pixels(self, range: Range<f32>, scale: f32, window_size: Vec2) -> f32 {
65        match self {
66            Px(value) => value,
67            Pt(value) => value * 96.0 / 72.0 * scale,
68            Pc(value) => value * (range.end - range.start) / 100.0,
69            Vw(value) => value * window_size.x / 100.0,
70            Vh(value) => value * window_size.y / 100.0,
71            Em(value) => value * 16.0 * scale,
72        }
73    }
74}
75
76impl Display for Unit {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        match self {
79            Px(value) => write!(f, "{}px", value),
80            Pt(value) => write!(f, "{}pt", value),
81            Pc(value) => write!(f, "{}%", value),
82            Vw(value) => write!(f, "{}vw", value),
83            Vh(value) => write!(f, "{}vh", value),
84            Em(value) => write!(f, "{}em", value),
85        }
86    }
87}