1use super::{
2 ByteLength, ByteUnits, Dip, DipToPx, EQ_GRANULARITY, EQ_GRANULARITY_100, Factor, FactorPercent, FactorUnits, LayoutAxis, Px, about_eq,
3};
4use std::{fmt, mem, ops};
5
6use zng_unit::about_eq_hash;
7use zng_var::{
8 animation::{Transitionable, easing::EasingStep},
9 impl_from_and_into_var,
10};
11
12use crate::{
13 context::{LAYOUT, LayoutMask},
14 unit::ParseCompositeError,
15};
16
17mod expr;
18pub use expr::*;
19
20#[derive(Clone, serde::Serialize, serde::Deserialize)]
32#[non_exhaustive]
33pub enum Length {
34 Default,
36 Dip(Dip),
38 Px(Px),
40 Pt(f32),
42 Factor(Factor),
44 Leftover(Factor),
46 Em(Factor),
48 RootEm(Factor),
50 ViewportWidth(Factor),
52 ViewportHeight(Factor),
54 ViewportMin(Factor),
56 ViewportMax(Factor),
58
59 DipF32(f32),
64 PxF32(f32),
69
70 Expr(Box<LengthExpr>),
72}
73impl<L: Into<Length>> ops::Add<L> for Length {
74 type Output = Length;
75
76 fn add(self, rhs: L) -> Self::Output {
77 use Length::*;
78
79 let rhs = rhs.into();
80
81 if self.is_zero() == Some(true) {
82 return rhs; } else if rhs.is_zero() == Some(true) {
84 return self; }
86
87 match (self, rhs) {
88 (Dip(a), Dip(b)) => Dip(a + b),
89 (Px(a), Px(b)) => Px(a + b),
90 (Pt(a), Pt(b)) => Pt(a + b),
91 (Factor(a), Factor(b)) => Factor(a + b),
92 (Leftover(a), Leftover(b)) => Leftover(a + b),
93 (Em(a), Em(b)) => Em(a + b),
94 (RootEm(a), RootEm(b)) => RootEm(a + b),
95 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a + b),
96 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a + b),
97 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a + b),
98 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a + b),
99 (PxF32(a), PxF32(b)) => PxF32(a + b),
100 (DipF32(a), DipF32(b)) => DipF32(a + b),
101 (Px(a), PxF32(b)) | (PxF32(b), Px(a)) => PxF32(a.0 as f32 + b),
102 (Dip(a), DipF32(b)) | (DipF32(b), Dip(a)) => DipF32(a.to_f32() + b),
103 (a, b) => LengthExpr::Add(a, b).to_length_checked(),
104 }
105 }
106}
107impl<L: Into<Length>> ops::AddAssign<L> for Length {
108 fn add_assign(&mut self, rhs: L) {
109 let lhs = mem::take(self);
110 *self = lhs + rhs.into();
111 }
112}
113impl<L: Into<Length>> ops::Sub<L> for Length {
114 type Output = Length;
115
116 fn sub(self, rhs: L) -> Self::Output {
117 use Length::*;
118
119 let rhs = rhs.into();
120
121 if rhs.is_zero() == Some(true) {
122 return self; } else if self.is_zero() == Some(true) {
124 return -rhs; }
126
127 match (self, rhs) {
128 (Dip(a), Dip(b)) => Dip(a - b),
129 (Px(a), Px(b)) => Px(a - b),
130 (Pt(a), Pt(b)) => Pt(a - b),
131 (Factor(a), Factor(b)) => Factor(a - b),
132 (Leftover(a), Leftover(b)) => Leftover(a - b),
133 (Em(a), Em(b)) => Em(a - b),
134 (RootEm(a), RootEm(b)) => RootEm(a - b),
135 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a - b),
136 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a - b),
137 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a - b),
138 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a - b),
139 (PxF32(a), PxF32(b)) => PxF32(a - b),
140 (DipF32(a), DipF32(b)) => DipF32(a - b),
141 (Px(a), PxF32(b)) => PxF32(a.0 as f32 - b),
142 (PxF32(a), Px(b)) => PxF32(a - b.0 as f32),
143 (Dip(a), DipF32(b)) => DipF32(a.to_f32() - b),
144 (DipF32(a), Dip(b)) => DipF32(a - b.to_f32()),
145 (a, b) => LengthExpr::Sub(a, b).to_length_checked(),
146 }
147 }
148}
149impl<L: Into<Length>> ops::SubAssign<L> for Length {
150 fn sub_assign(&mut self, rhs: L) {
151 let lhs = mem::take(self);
152 *self = lhs - rhs.into();
153 }
154}
155impl<F: Into<Factor>> ops::Mul<F> for Length {
156 type Output = Length;
157
158 fn mul(self, rhs: F) -> Self::Output {
159 use Length::*;
160 let rhs = rhs.into();
161
162 if self.is_zero() == Some(true) || rhs == 1.fct() {
163 return self; } else if rhs == 0.fct() {
165 return Self::zero(); }
167
168 match self {
169 Dip(e) => DipF32(e.to_f32() * rhs.0),
170 Px(e) => PxF32(e.0 as f32 * rhs.0),
171 Pt(e) => Pt(e * rhs.0),
172 Factor(r) => Factor(r * rhs),
173 Leftover(r) => Leftover(r * rhs),
174 Em(e) => Em(e * rhs),
175 RootEm(e) => RootEm(e * rhs),
176 ViewportWidth(w) => ViewportWidth(w * rhs),
177 ViewportHeight(h) => ViewportHeight(h * rhs),
178 ViewportMin(m) => ViewportMin(m * rhs),
179 ViewportMax(m) => ViewportMax(m * rhs),
180 DipF32(e) => DipF32(e * rhs.0),
181 PxF32(e) => PxF32(e * rhs.0),
182 e => LengthExpr::Mul(e, rhs).to_length_checked(),
183 }
184 }
185}
186impl<F: Into<Factor>> ops::MulAssign<F> for Length {
187 fn mul_assign(&mut self, rhs: F) {
188 let lhs = mem::take(self);
189 *self = lhs * rhs.into();
190 }
191}
192impl<F: Into<Factor>> ops::Div<F> for Length {
193 type Output = Length;
194
195 fn div(self, rhs: F) -> Self::Output {
196 use Length::*;
197
198 let rhs = rhs.into();
199
200 if self.is_zero() == Some(true) && rhs != 0.fct() {
201 return self; }
203
204 match self {
205 Dip(e) => DipF32(e.to_f32() / rhs.0),
206 Px(e) => PxF32(e.0 as f32 / rhs.0),
207 Pt(e) => Pt(e / rhs.0),
208 Factor(r) => Factor(r / rhs),
209 Leftover(r) => Leftover(r / rhs),
210 Em(e) => Em(e / rhs),
211 RootEm(e) => RootEm(e / rhs),
212 ViewportWidth(w) => ViewportWidth(w / rhs),
213 ViewportHeight(h) => ViewportHeight(h / rhs),
214 ViewportMin(m) => ViewportMin(m / rhs),
215 ViewportMax(m) => ViewportMax(m / rhs),
216 DipF32(e) => DipF32(e / rhs.0),
217 PxF32(e) => PxF32(e / rhs.0),
218 e => LengthExpr::Div(e, rhs).to_length_checked(),
219 }
220 }
221}
222impl<F: Into<Factor>> ops::DivAssign<F> for Length {
223 fn div_assign(&mut self, rhs: F) {
224 let lhs = mem::take(self);
225 *self = lhs / rhs.into();
226 }
227}
228impl Transitionable for Length {
229 fn lerp(self, to: &Self, step: EasingStep) -> Self {
230 use Length::*;
231
232 if step == 0.fct() {
233 return self;
234 }
235 if step == 1.fct() {
236 return to.clone();
237 }
238
239 match (self, to) {
240 (Dip(a), Dip(b)) => Dip(a.lerp(b, step)),
241 (Px(a), Px(b)) => Px(a.lerp(b, step)),
242 (Pt(a), Pt(b)) => Pt(a.lerp(b, step)),
243 (Factor(a), Factor(b)) => Factor(a.lerp(b, step)),
244 (Leftover(a), Leftover(b)) => Leftover(a.lerp(b, step)),
245 (Em(a), Em(b)) => Em(a.lerp(b, step)),
246 (RootEm(a), RootEm(b)) => RootEm(a.lerp(b, step)),
247 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.lerp(b, step)),
248 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.lerp(b, step)),
249 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.lerp(b, step)),
250 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.lerp(b, step)),
251 (PxF32(a), PxF32(b)) => PxF32(a.lerp(b, step)),
252 (DipF32(a), DipF32(b)) => DipF32(a.lerp(b, step)),
253 (Px(a), PxF32(b)) => PxF32((a.0 as f32).lerp(b, step)),
254 (PxF32(a), Px(b)) => PxF32(a.lerp(&(b.0 as f32), step)),
255 (Dip(a), DipF32(b)) => DipF32(a.to_f32().lerp(b, step)),
256 (DipF32(a), Dip(b)) => DipF32(a.lerp(&b.to_f32(), step)),
257 (a, b) => LengthExpr::Lerp(a, b.clone(), step).to_length_checked(),
258 }
259 }
260}
261impl ops::Neg for Length {
262 type Output = Self;
263
264 fn neg(self) -> Self::Output {
265 match self {
266 Length::Default => LengthExpr::Neg(Length::Default).to_length_checked(),
267 Length::Dip(e) => Length::Dip(-e),
268 Length::Px(e) => Length::Px(-e),
269 Length::Pt(e) => Length::Pt(-e),
270 Length::Factor(e) => Length::Factor(-e),
271 Length::Leftover(e) => Length::Leftover(-e),
272 Length::Em(e) => Length::Em(-e),
273 Length::RootEm(e) => Length::RootEm(-e),
274 Length::ViewportWidth(e) => Length::ViewportWidth(-e),
275 Length::ViewportHeight(e) => Length::ViewportHeight(-e),
276 Length::ViewportMin(e) => Length::ViewportMin(-e),
277 Length::ViewportMax(e) => Length::ViewportMax(-e),
278 Length::DipF32(e) => Length::DipF32(-e),
279 Length::PxF32(e) => Length::PxF32(-e),
280 Length::Expr(e) => LengthExpr::Neg(Length::Expr(e)).to_length_checked(),
281 }
282 }
283}
284impl Default for Length {
285 fn default() -> Self {
287 Length::Default
288 }
289}
290impl PartialEq for Length {
291 fn eq(&self, other: &Self) -> bool {
292 use Length::*;
293 match (self, other) {
294 (Default, Default) => true,
295
296 (Dip(a), Dip(b)) => a == b,
297 (Px(a), Px(b)) => a == b,
298 (Pt(a), Pt(b)) => about_eq(*a, *b, EQ_GRANULARITY_100),
299
300 (DipF32(a), DipF32(b)) | (PxF32(a), PxF32(b)) => about_eq(*a, *b, EQ_GRANULARITY_100),
301
302 (Factor(a), Factor(b))
303 | (Em(a), Em(b))
304 | (RootEm(a), RootEm(b))
305 | (Leftover(a), Leftover(b))
306 | (ViewportWidth(a), ViewportWidth(b))
307 | (ViewportHeight(a), ViewportHeight(b))
308 | (ViewportMin(a), ViewportMin(b))
309 | (ViewportMax(a), ViewportMax(b)) => a == b,
310
311 (Expr(a), Expr(b)) => a == b,
312
313 (Dip(a), DipF32(b)) | (DipF32(b), Dip(a)) => about_eq(a.to_f32(), *b, EQ_GRANULARITY_100),
314 (Px(a), PxF32(b)) | (PxF32(b), Px(a)) => about_eq(a.0 as f32, *b, EQ_GRANULARITY_100),
315
316 (a, b) => {
317 debug_assert_ne!(std::mem::discriminant(a), std::mem::discriminant(b));
318 false
319 }
320 }
321 }
322}
323impl Eq for Length {}
324impl std::hash::Hash for Length {
325 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
326 core::mem::discriminant(self).hash(state);
327 match self {
328 Length::Default => {}
329 Length::Dip(dip) => dip.hash(state),
330 Length::Px(px) => px.hash(state),
331 Length::Factor(factor)
332 | Length::Leftover(factor)
333 | Length::Em(factor)
334 | Length::RootEm(factor)
335 | Length::ViewportWidth(factor)
336 | Length::ViewportHeight(factor)
337 | Length::ViewportMin(factor)
338 | Length::ViewportMax(factor) => factor.hash(state),
339 Length::DipF32(f) | Length::PxF32(f) | Length::Pt(f) => about_eq_hash(*f, EQ_GRANULARITY_100, state),
340 Length::Expr(length_expr) => length_expr.hash(state),
341 }
342 }
343}
344impl fmt::Debug for Length {
345 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346 use Length::*;
347 if f.alternate() {
348 match self {
349 Default => write!(f, "Length::Default"),
350 Dip(e) => f.debug_tuple("Length::Dip").field(e).finish(),
351 Px(e) => f.debug_tuple("Length::Px").field(e).finish(),
352 Pt(e) => f.debug_tuple("Length::Pt").field(e).finish(),
353 Factor(e) => f.debug_tuple("Length::Factor").field(e).finish(),
354 Leftover(e) => f.debug_tuple("Length::Leftover").field(e).finish(),
355 Em(e) => f.debug_tuple("Length::Em").field(e).finish(),
356 RootEm(e) => f.debug_tuple("Length::RootEm").field(e).finish(),
357 ViewportWidth(e) => f.debug_tuple("Length::ViewportWidth").field(e).finish(),
358 ViewportHeight(e) => f.debug_tuple("Length::ViewportHeight").field(e).finish(),
359 ViewportMin(e) => f.debug_tuple("Length::ViewportMin").field(e).finish(),
360 ViewportMax(e) => f.debug_tuple("Length::ViewportMax").field(e).finish(),
361 DipF32(e) => f.debug_tuple("Length::DipF32").field(e).finish(),
362 PxF32(e) => f.debug_tuple("Length::PxF32").field(e).finish(),
363 Expr(e) => f.debug_tuple("Length::Expr").field(e).finish(),
364 }
365 } else {
366 match self {
367 Default => write!(f, "Default"),
368 Dip(e) => write!(f, "{:.*}.dip()", f.precision().unwrap_or(0), e.to_f32()),
369 Px(e) => write!(f, "{}.px()", e.0),
370 Pt(e) => write!(f, "{e:.*}.pt()", f.precision().unwrap_or(0)),
371 Factor(e) => write!(f, "{:.*}.pct()", f.precision().unwrap_or(0), e.0 * 100.0),
372 Leftover(e) => write!(f, "{:.*}.lft()", f.precision().unwrap_or(0), e.0),
373 Em(e) => write!(f, "{:.*}.em()", f.precision().unwrap_or(0), e.0),
374 RootEm(e) => write!(f, "{:.*}.rem()", f.precision().unwrap_or(0), e.0),
375 ViewportWidth(e) => write!(f, "{e:.*}.vw()", f.precision().unwrap_or(0)),
376 ViewportHeight(e) => write!(f, "{e:.*}.vh()", f.precision().unwrap_or(0)),
377 ViewportMin(e) => write!(f, "{e:.*}.vmin()", f.precision().unwrap_or(0)),
378 ViewportMax(e) => write!(f, "{e:.*}.vmax()", f.precision().unwrap_or(0)),
379 DipF32(e) => write!(f, "{e:.*}.dip()", f.precision().unwrap_or(0)),
380 PxF32(e) => write!(f, "{e:.*}.px()", f.precision().unwrap_or(0)),
381 Expr(e) => write!(f, "{e:.*}", f.precision().unwrap_or(0)),
382 }
383 }
384 }
385}
386impl fmt::Display for Length {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 use Length::*;
389 match self {
390 Default => write!(f, "default"),
391 Dip(l) => write!(f, "{l:.*}", f.precision().unwrap_or(0)),
392 Px(l) => write!(f, "{l}"),
393 Pt(l) => write!(f, "{l:.*}pt", f.precision().unwrap_or(0)),
394 Factor(n) => write!(f, "{:.*}%", f.precision().unwrap_or(0), n.0 * 100.0),
395 Leftover(l) => write!(f, "{l:.*}lft", f.precision().unwrap_or(0)),
396 Em(e) => write!(f, "{e:.*}em", f.precision().unwrap_or(0)),
397 RootEm(re) => write!(f, "{re:.*}rem", f.precision().unwrap_or(0)),
398 ViewportWidth(vw) => write!(f, "{vw:.*}vw", f.precision().unwrap_or(0)),
399 ViewportHeight(vh) => write!(f, "{vh:.*}vh", f.precision().unwrap_or(0)),
400 ViewportMin(vmin) => write!(f, "{vmin:.*}vmin", f.precision().unwrap_or(0)),
401 ViewportMax(vmax) => write!(f, "{vmax:.*}vmax", f.precision().unwrap_or(0)),
402 DipF32(l) => write!(f, "{l:.*}dip", f.precision().unwrap_or(0)),
403 PxF32(l) => write!(f, "{l:.*}px", f.precision().unwrap_or(0)),
404 Expr(e) => write!(f, "{e:.*}", f.precision().unwrap_or(0)),
405 }
406 }
407}
408impl std::str::FromStr for Length {
409 type Err = ParseCompositeError;
410
411 fn from_str(s: &str) -> Result<Self, Self::Err> {
412 if s == "default" || s == "Default" {
413 Ok(Self::Default)
414 } else if let Some(dip) = s.strip_suffix("dip").or_else(|| s.strip_suffix(".dip()")) {
415 if dip.contains('.') {
416 Ok(Self::DipF32(dip.parse()?))
417 } else {
418 Ok(Self::Dip(Dip::new_f32(dip.parse()?)))
419 }
420 } else if let Some(px) = s.strip_suffix("px").or_else(|| s.strip_suffix(".px()")) {
421 if px.contains('.') {
422 Ok(Self::PxF32(px.parse()?))
423 } else {
424 Ok(Self::Px(Px(px.parse()?)))
425 }
426 } else if let Some(pt) = s.strip_suffix("pt").or_else(|| s.strip_suffix(".pt()")) {
427 Ok(Self::Pt(pt.parse()?))
428 } else if let Some(fct) = s.strip_suffix("fct").or_else(|| s.strip_suffix(".fct()")) {
429 Ok(Self::Factor(Factor(fct.parse()?)))
430 } else if let Some(fct) = s.strip_suffix("%").or_else(|| s.strip_suffix(".pct()")) {
431 Ok(Self::Factor(FactorPercent(fct.parse()?).fct()))
432 } else if let Some(lft) = s.strip_suffix("lft").or_else(|| s.strip_suffix(".lft()")) {
433 Ok(Self::Leftover(Factor(lft.parse()?)))
434 } else if let Some(em) = s.strip_suffix("em").or_else(|| s.strip_suffix(".em()")) {
435 Ok(Self::Em(Factor(em.parse()?)))
436 } else if let Some(root_em) = s.strip_suffix("rem").or_else(|| s.strip_suffix(".rem()")) {
437 Ok(Self::RootEm(Factor(root_em.parse()?)))
438 } else if let Some(vw) = s.strip_suffix("vw").or_else(|| s.strip_suffix(".vw()")) {
439 Ok(Self::ViewportWidth(Factor(vw.parse()?)))
440 } else if let Some(vh) = s.strip_suffix("vh").or_else(|| s.strip_suffix(".vh()")) {
441 Ok(Self::ViewportHeight(Factor(vh.parse()?)))
442 } else if let Some(v_min) = s.strip_suffix("vmin").or_else(|| s.strip_suffix(".vmin()")) {
443 Ok(Self::ViewportMin(Factor(v_min.parse()?)))
444 } else if let Some(v_max) = s.strip_suffix("vmax").or_else(|| s.strip_suffix(".vmax()")) {
445 Ok(Self::ViewportMax(Factor(v_max.parse()?)))
446 } else if let Ok(int) = s.parse::<i32>() {
447 Ok(Self::Dip(Dip::new(int)))
448 } else if let Ok(float) = s.parse::<f32>() {
449 Ok(Self::DipF32(float))
450 } else {
451 Ok(Self::Expr(Box::new(s.parse()?)))
452 }
453 }
454}
455impl_from_and_into_var! {
456 fn from(percent: FactorPercent) -> Length {
458 Length::Factor(percent.into())
459 }
460
461 fn from(norm: Factor) -> Length {
463 Length::Factor(norm)
464 }
465
466 fn from(f: f32) -> Length {
468 Length::DipF32(f)
469 }
470
471 fn from(i: i32) -> Length {
473 Length::Dip(Dip::new(i))
474 }
475
476 fn from(l: Px) -> Length {
478 Length::Px(l)
479 }
480
481 fn from(l: Dip) -> Length {
483 Length::Dip(l)
484 }
485
486 fn from(expr: LengthExpr) -> Length {
487 Length::Expr(Box::new(expr))
488 }
489}
490impl Length {
491 pub const fn zero() -> Length {
493 Length::Px(Px(0))
494 }
495
496 pub const fn fill() -> Length {
498 Length::Factor(Factor(1.0))
499 }
500
501 pub const fn half() -> Length {
503 Length::Factor(Factor(0.5))
504 }
505
506 pub fn max(&self, other: impl Into<Length>) -> Length {
508 use Length::*;
509 match (self.clone(), other.into()) {
510 (Default, Default) => Default,
511 (Dip(a), Dip(b)) => Dip(a.max(b)),
512 (Px(a), Px(b)) => Px(a.max(b)),
513 (Pt(a), Pt(b)) => Pt(a.max(b)),
514 (Factor(a), Factor(b)) => Factor(a.max(b)),
515 (Leftover(a), Leftover(b)) => Leftover(a.max(b)),
516 (Em(a), Em(b)) => Em(a.max(b)),
517 (RootEm(a), RootEm(b)) => RootEm(a.max(b)),
518 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.max(b)),
519 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.max(b)),
520 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.max(b)),
521 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.max(b)),
522 (DipF32(a), DipF32(b)) => DipF32(a.max(b)),
523 (PxF32(a), PxF32(b)) => PxF32(a.max(b)),
524 (DipF32(a), Dip(b)) | (Dip(b), DipF32(a)) => DipF32(a.max(b.to_f32())),
525 (PxF32(a), Px(b)) | (Px(b), PxF32(a)) => PxF32(a.max(b.0 as f32)),
526 (a, b) => LengthExpr::Max(a, b).to_length_checked(),
527 }
528 }
529
530 pub fn min(&self, other: impl Into<Length>) -> Length {
532 use Length::*;
533 match (self.clone(), other.into()) {
534 (Default, Default) => Default,
535 (Dip(a), Dip(b)) => Dip(a.min(b)),
536 (Px(a), Px(b)) => Px(a.min(b)),
537 (Pt(a), Pt(b)) => Pt(a.min(b)),
538 (Factor(a), Factor(b)) => Factor(a.min(b)),
539 (Leftover(a), Leftover(b)) => Leftover(a.min(b)),
540 (Em(a), Em(b)) => Em(a.min(b)),
541 (RootEm(a), RootEm(b)) => RootEm(a.min(b)),
542 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.min(b)),
543 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.min(b)),
544 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.min(b)),
545 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.min(b)),
546 (DipF32(a), DipF32(b)) => DipF32(a.min(b)),
547 (PxF32(a), PxF32(b)) => PxF32(a.min(b)),
548 (DipF32(a), Dip(b)) | (Dip(b), DipF32(a)) => DipF32(a.min(b.to_f32())),
549 (PxF32(a), Px(b)) | (Px(b), PxF32(a)) => PxF32(a.min(b.0 as f32)),
550 (a, b) => LengthExpr::Min(a, b).to_length_checked(),
551 }
552 }
553
554 pub fn clamp(&self, min: impl Into<Length>, max: impl Into<Length>) -> Length {
556 self.max(min).min(max)
557 }
558
559 pub fn abs(&self) -> Length {
561 use Length::*;
562 match self {
563 Default => LengthExpr::Abs(Length::Default).to_length_checked(),
564 Dip(e) => Dip(e.abs()),
565 Px(e) => Px(e.abs()),
566 Pt(e) => Pt(e.abs()),
567 Factor(r) => Factor(r.abs()),
568 Leftover(r) => Leftover(r.abs()),
569 Em(e) => Em(e.abs()),
570 RootEm(r) => RootEm(r.abs()),
571 ViewportWidth(w) => ViewportWidth(w.abs()),
572 ViewportHeight(h) => ViewportHeight(h.abs()),
573 ViewportMin(m) => ViewportMin(m.abs()),
574 ViewportMax(m) => ViewportMax(m.abs()),
575 DipF32(e) => DipF32(e.abs()),
576 PxF32(e) => PxF32(e.abs()),
577 Expr(e) => LengthExpr::Abs(Length::Expr(e.clone())).to_length_checked(),
578 }
579 }
580
581 pub fn is_zero(&self) -> Option<bool> {
585 use Length::*;
586 match self {
587 Default => None,
588 Dip(l) => Some(*l == self::Dip::new(0)),
589 Px(l) => Some(*l == self::Px(0)),
590 Pt(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY)),
591 Factor(f) | Leftover(f) | Em(f) | RootEm(f) | ViewportWidth(f) | ViewportHeight(f) | ViewportMin(f) | ViewportMax(f) => {
592 Some(*f == 0.fct())
593 }
594 DipF32(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY_100)),
595 PxF32(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY_100)),
596 Expr(_) => None,
597 }
598 }
599
600 pub fn pt_to_px(pt: f32, scale_factor: Factor) -> Px {
602 let px = Self::pt_to_px_f32(pt, scale_factor);
603 Px(px.round() as i32)
604 }
605
606 pub fn pt_to_px_f32(pt: f32, scale_factor: Factor) -> f32 {
610 pt * Self::PT_TO_DIP * scale_factor.0
611 }
612
613 pub fn px_to_pt(px: Px, scale_factor: Factor) -> f32 {
615 let dip = px.0 as f32 / scale_factor.0;
616 dip / Self::PT_TO_DIP
617 }
618
619 pub fn is_default(&self) -> bool {
623 matches!(self, Length::Default)
624 }
625
626 pub fn has_default(&self) -> bool {
631 match self {
632 Length::Default => true,
633 Length::Expr(e) => e.has_default(),
634 _ => false,
635 }
636 }
637
638 pub fn replace_default(&mut self, overwrite: &Length) {
643 match self {
644 Length::Default => *self = overwrite.clone(),
645 Length::Expr(e) => e.replace_default(overwrite),
646 _ => {}
647 }
648 }
649
650 pub fn round_exact(&mut self) {
657 match self {
658 Length::PxF32(l) => *self = Length::Px(Px(l.round() as i32)),
659 Length::DipF32(l) => *self = Length::Dip(Dip::new_f32(*l)),
660 Length::Expr(e) => e.round_exact(),
661 _ => {}
662 }
663 }
664
665 pub fn memory_used(&self) -> ByteLength {
669 std::mem::size_of::<Length>().bytes() + self.heap_memory_used()
670 }
671
672 pub fn heap_memory_used(&self) -> ByteLength {
674 if let Length::Expr(e) = self { e.memory_used() } else { 0.bytes() }
675 }
676
677 const PT_TO_DIP: f32 = 96.0 / 72.0; }
680impl super::Layout1d for Length {
681 fn layout_dft(&self, axis: LayoutAxis, default: Px) -> Px {
682 use Length::*;
683 match self {
684 Default => default,
685 Dip(l) => l.to_px(LAYOUT.scale_factor()),
686 Px(l) => *l,
687 Pt(l) => Self::pt_to_px(*l, LAYOUT.scale_factor()),
688 Factor(f) => LAYOUT.constraints_for(axis).fill() * f.0,
689 Leftover(f) => {
690 if let Some(l) = LAYOUT.leftover_for(axis) {
691 l
692 } else {
693 let fill = LAYOUT.constraints_for(axis).fill();
694 (fill * f.0).clamp(self::Px(0), fill)
695 }
696 }
697 Em(f) => LAYOUT.font_size() * f.0,
698 RootEm(f) => LAYOUT.root_font_size() * f.0,
699 ViewportWidth(p) => LAYOUT.viewport().width * *p,
700 ViewportHeight(p) => LAYOUT.viewport().height * *p,
701 ViewportMin(p) => LAYOUT.viewport_min() * *p,
702 ViewportMax(p) => LAYOUT.viewport_max() * *p,
703 DipF32(l) => self::Px((l * LAYOUT.scale_factor().0).round() as i32),
704 PxF32(l) => self::Px(l.round() as i32),
705 Expr(e) => e.layout_dft(axis, default),
706 }
707 }
708
709 fn layout_f32_dft(&self, axis: LayoutAxis, default: f32) -> f32 {
710 use Length::*;
711 match self {
712 Default => default,
713 Dip(l) => l.to_f32() * LAYOUT.scale_factor().0,
714 Px(l) => l.0 as f32,
715 Pt(l) => Self::pt_to_px_f32(*l, LAYOUT.scale_factor()),
716 Factor(f) => LAYOUT.constraints_for(axis).fill().0 as f32 * f.0,
717 Leftover(f) => {
718 if let Some(l) = LAYOUT.leftover_for(axis) {
719 l.0 as f32
720 } else {
721 let fill = LAYOUT.constraints_for(axis).fill().0 as f32;
722 (fill * f.0).clamp(0.0, fill)
723 }
724 }
725 Em(f) => LAYOUT.font_size().0 as f32 * f.0,
726 RootEm(f) => LAYOUT.root_font_size().0 as f32 * f.0,
727 ViewportWidth(p) => LAYOUT.viewport().width.0 as f32 * *p,
728 ViewportHeight(p) => LAYOUT.viewport().height.0 as f32 * *p,
729 ViewportMin(p) => LAYOUT.viewport_min().0 as f32 * *p,
730 ViewportMax(p) => LAYOUT.viewport_max().0 as f32 * *p,
731 DipF32(l) => *l * LAYOUT.scale_factor().0,
732 PxF32(l) => *l,
733 Expr(e) => e.layout_f32_dft(axis, default),
734 }
735 }
736
737 fn affect_mask(&self) -> LayoutMask {
738 use Length::*;
739 match self {
740 Default => LayoutMask::DEFAULT_VALUE,
741 Dip(_) => LayoutMask::SCALE_FACTOR,
742 Px(_) => LayoutMask::empty(),
743 Pt(_) => LayoutMask::SCALE_FACTOR,
744 Factor(_) => LayoutMask::CONSTRAINTS,
745 Leftover(_) => LayoutMask::LEFTOVER,
746 Em(_) => LayoutMask::FONT_SIZE,
747 RootEm(_) => LayoutMask::ROOT_FONT_SIZE,
748 ViewportWidth(_) => LayoutMask::VIEWPORT,
749 ViewportHeight(_) => LayoutMask::VIEWPORT,
750 ViewportMin(_) => LayoutMask::VIEWPORT,
751 ViewportMax(_) => LayoutMask::VIEWPORT,
752 DipF32(_) => LayoutMask::SCALE_FACTOR,
753 PxF32(_) => LayoutMask::empty(),
754 Expr(e) => e.affect_mask(),
755 }
756 }
757}
758
759pub trait LengthUnits {
781 fn dip(self) -> Length;
785
786 fn px(self) -> Length;
790
791 fn pt(self) -> Length;
795
796 fn fct_l(self) -> Length;
803
804 fn pct_l(self) -> Length;
811
812 fn em(self) -> Length;
816
817 fn em_pct(self) -> Length;
821
822 fn rem(self) -> Length;
826
827 fn rem_pct(self) -> Length;
831
832 fn vw(self) -> Length;
836
837 fn vw_pct(self) -> Length;
841
842 fn vh(self) -> Length;
846
847 fn vh_pct(self) -> Length;
851
852 fn vmin(self) -> Length;
856
857 fn vmin_pct(self) -> Length;
861
862 fn vmax(self) -> Length;
866
867 fn vmax_pct(self) -> Length;
871
872 fn lft(self) -> Length;
879}
880impl LengthUnits for f32 {
881 fn dip(self) -> Length {
882 Length::DipF32(self)
883 }
884
885 fn px(self) -> Length {
886 Length::PxF32(self)
887 }
888
889 fn pt(self) -> Length {
890 Length::Pt(self)
891 }
892
893 fn fct_l(self) -> Length {
894 Length::Factor(self.fct())
895 }
896
897 fn pct_l(self) -> Length {
898 Length::Factor(self.pct().fct())
899 }
900
901 fn em(self) -> Length {
902 Length::Em(self.into())
903 }
904
905 fn rem(self) -> Length {
906 Length::RootEm(self.into())
907 }
908
909 fn vw(self) -> Length {
910 Length::ViewportWidth(self.into())
911 }
912
913 fn vh(self) -> Length {
914 Length::ViewportHeight(self.into())
915 }
916
917 fn vmin(self) -> Length {
918 Length::ViewportMin(self.into())
919 }
920
921 fn vmax(self) -> Length {
922 Length::ViewportMax(self.into())
923 }
924
925 fn em_pct(self) -> Length {
926 Length::Em(self.pct().into())
927 }
928
929 fn rem_pct(self) -> Length {
930 Length::RootEm(self.pct().into())
931 }
932
933 fn vw_pct(self) -> Length {
934 Length::ViewportWidth(self.pct().into())
935 }
936
937 fn vh_pct(self) -> Length {
938 Length::ViewportHeight(self.pct().into())
939 }
940
941 fn vmin_pct(self) -> Length {
942 Length::ViewportMin(self.pct().into())
943 }
944
945 fn vmax_pct(self) -> Length {
946 Length::ViewportMax(self.pct().into())
947 }
948
949 fn lft(self) -> Length {
950 Length::Leftover(self.fct())
951 }
952}
953impl LengthUnits for i32 {
954 fn dip(self) -> Length {
955 Length::Dip(Dip::new(self))
956 }
957
958 fn px(self) -> Length {
959 Length::Px(Px(self))
960 }
961
962 fn pt(self) -> Length {
963 Length::Pt(self as f32)
964 }
965
966 fn fct_l(self) -> Length {
967 Length::Factor(self.fct())
968 }
969
970 fn pct_l(self) -> Length {
971 Length::Factor(self.pct().fct())
972 }
973
974 fn em(self) -> Length {
975 Length::Em(self.fct())
976 }
977
978 fn rem(self) -> Length {
979 Length::RootEm(self.fct())
980 }
981
982 fn vw(self) -> Length {
983 Length::ViewportWidth(self.fct())
984 }
985
986 fn vh(self) -> Length {
987 Length::ViewportHeight(self.fct())
988 }
989
990 fn vmin(self) -> Length {
991 Length::ViewportMin(self.fct())
992 }
993
994 fn vmax(self) -> Length {
995 Length::ViewportMax(self.fct())
996 }
997
998 fn em_pct(self) -> Length {
999 Length::Em(self.pct().into())
1000 }
1001
1002 fn rem_pct(self) -> Length {
1003 Length::RootEm(self.pct().into())
1004 }
1005
1006 fn vw_pct(self) -> Length {
1007 Length::ViewportWidth(self.pct().into())
1008 }
1009
1010 fn vh_pct(self) -> Length {
1011 Length::ViewportHeight(self.pct().into())
1012 }
1013
1014 fn vmin_pct(self) -> Length {
1015 Length::ViewportMin(self.pct().into())
1016 }
1017
1018 fn vmax_pct(self) -> Length {
1019 Length::ViewportMax(self.pct().into())
1020 }
1021
1022 fn lft(self) -> Length {
1023 Length::Leftover(self.fct())
1024 }
1025}