zng_layout/unit/
resolution.rs

1use std::fmt;
2
3use zng_var::{animation::Transitionable, impl_from_and_into_var};
4
5/// Pixels-per-inch resolution.
6#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Transitionable)]
7#[serde(transparent)]
8pub struct Ppi(pub f32);
9impl Default for Ppi {
10    /// 96ppi.
11    fn default() -> Self {
12        Ppi(96.0)
13    }
14}
15impl PartialEq for Ppi {
16    fn eq(&self, other: &Self) -> bool {
17        super::about_eq(self.0, other.0, 0.0001)
18    }
19}
20impl Eq for Ppi {}
21impl std::hash::Hash for Ppi {
22    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
23        super::about_eq_hash(self.0, 0.0001, state)
24    }
25}
26impl Ord for Ppi {
27    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
28        super::about_eq_ord(self.0, other.0, 0.0001)
29    }
30}
31impl PartialOrd for Ppi {
32    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
33        Some(self.cmp(other))
34    }
35}
36
37/// Pixels-per-meter resolution.
38#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Transitionable)]
39#[serde(transparent)]
40pub struct Ppm(pub f32);
41impl PartialEq for Ppm {
42    fn eq(&self, other: &Self) -> bool {
43        super::about_eq(self.0, other.0, 0.0001)
44    }
45}
46impl Eq for Ppm {}
47impl std::hash::Hash for Ppm {
48    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49        super::about_eq_hash(self.0, 0.0001, state)
50    }
51}
52impl Ord for Ppm {
53    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
54        super::about_eq_ord(self.0, other.0, 0.0001)
55    }
56}
57impl PartialOrd for Ppm {
58    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
59        Some(self.cmp(other))
60    }
61}
62impl Default for Ppm {
63    /// 96ppi.
64    fn default() -> Self {
65        Ppi(96.0).into()
66    }
67}
68
69/// Extension methods for initializing resolution units.
70///
71/// # Examples
72///
73/// ```
74/// use zng_layout::unit::*;
75///
76/// let ppm: Ppm = 96.dpi().into();
77/// ```
78pub trait ResolutionUnits {
79    /// Pixels-per-inch.
80    fn ppi(self) -> Ppi;
81    /// Same as [`ppi`].
82    ///
83    /// [`ppi`]: ResolutionUnits::ppi
84    fn dpi(self) -> Ppi
85    where
86        Self: Sized,
87    {
88        self.ppi()
89    }
90
91    /// Pixels-per-meter.
92    fn ppm(self) -> Ppm;
93}
94impl ResolutionUnits for u32 {
95    fn ppi(self) -> Ppi {
96        Ppi(self as f32)
97    }
98
99    fn ppm(self) -> Ppm {
100        Ppm(self as f32)
101    }
102}
103impl ResolutionUnits for f32 {
104    fn ppi(self) -> Ppi {
105        Ppi(self)
106    }
107
108    fn ppm(self) -> Ppm {
109        Ppm(self)
110    }
111}
112
113impl fmt::Display for Ppi {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        write!(f, "{}ppi", self.0)
116    }
117}
118impl fmt::Display for Ppm {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        write!(f, "{}ppm", self.0)
121    }
122}
123impl_from_and_into_var! {
124    fn from(ppi: Ppi) -> Ppm {
125        Ppm(ppi.0 * 39.3701)
126    }
127
128    fn from(ppm: Ppm) -> Ppi {
129        Ppi(ppm.0 / 39.3701)
130    }
131}