1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use super::*;
/// A length, possibly expressed with contextual units.
///
/// Currently supports absolute and font-relative units, but support could quite
/// easily be extended to other units.
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
pub struct Length {
/// The absolute part.
pub abs: Abs,
/// The font-relative part.
pub em: Em,
}
impl Length {
/// The zero length.
pub const fn zero() -> Self {
Self { abs: Abs::zero(), em: Em::zero() }
}
/// Try to compute the absolute value of the length.
pub fn try_abs(self) -> Option<Self> {
(self.abs.is_zero() || self.em.is_zero())
.then(|| Self { abs: self.abs.abs(), em: self.em.abs() })
}
/// Try to divide two lengths.
pub fn try_div(self, other: Self) -> Option<f64> {
if self.abs.is_zero() && other.abs.is_zero() {
Some(self.em / other.em)
} else if self.em.is_zero() && other.em.is_zero() {
Some(self.abs / other.abs)
} else {
None
}
}
}
impl Debug for Length {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match (self.abs.is_zero(), self.em.is_zero()) {
(false, false) => write!(f, "{:?} + {:?}", self.abs, self.em),
(true, false) => self.em.fmt(f),
(_, true) => self.abs.fmt(f),
}
}
}
impl Numeric for Length {
fn zero() -> Self {
Self::zero()
}
fn is_finite(self) -> bool {
self.abs.is_finite() && self.em.is_finite()
}
}
impl PartialOrd for Length {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.em.is_zero() && other.em.is_zero() {
self.abs.partial_cmp(&other.abs)
} else if self.abs.is_zero() && other.abs.is_zero() {
self.em.partial_cmp(&other.em)
} else {
None
}
}
}
impl From<Abs> for Length {
fn from(abs: Abs) -> Self {
Self { abs, em: Em::zero() }
}
}
impl From<Em> for Length {
fn from(em: Em) -> Self {
Self { abs: Abs::zero(), em }
}
}
impl Neg for Length {
type Output = Self;
fn neg(self) -> Self::Output {
Self { abs: -self.abs, em: -self.em }
}
}
impl Add for Length {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self { abs: self.abs + rhs.abs, em: self.em + rhs.em }
}
}
sub_impl!(Length - Length -> Length);
impl Mul<f64> for Length {
type Output = Self;
fn mul(self, rhs: f64) -> Self::Output {
Self { abs: self.abs * rhs, em: self.em * rhs }
}
}
impl Div<f64> for Length {
type Output = Self;
fn div(self, rhs: f64) -> Self::Output {
Self { abs: self.abs / rhs, em: self.em / rhs }
}
}
assign_impl!(Length += Length);
assign_impl!(Length -= Length);
assign_impl!(Length *= f64);
assign_impl!(Length /= f64);
impl Resolve for Length {
type Output = Abs;
fn resolve(self, styles: StyleChain) -> Self::Output {
self.abs + self.em.resolve(styles)
}
}
|