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(mut self, rhs: L) -> Self::Output {
77 let mut rhs = rhs.into();
78
79 if self.try_add(&mut rhs) {
80 self
81 } else {
82 LengthExpr::Add(self, rhs).to_length_checked()
83 }
84 }
85}
86impl<L: Into<Length>> ops::AddAssign<L> for Length {
87 fn add_assign(&mut self, rhs: L) {
88 let lhs = mem::take(self);
89 *self = lhs + rhs.into();
90 }
91}
92impl Length {
93 pub(crate) fn try_add(&mut self, rhs: &mut Self) -> bool {
94 use Length::*;
95 if self.is_zero() == Some(true) {
96 *self = mem::take(rhs);
97 return true; }
99 if rhs.is_zero() == Some(true) {
100 return true; }
102
103 let ok = match (mem::take(self), mem::take(rhs)) {
104 (Dip(a), Dip(b)) => Dip(a + b),
105 (Px(a), Px(b)) => Px(a + b),
106 (Pt(a), Pt(b)) => Pt(a + b),
107 (Factor(a), Factor(b)) => Factor(a + b),
108 (Leftover(a), Leftover(b)) => Leftover(a + b),
109 (Em(a), Em(b)) => Em(a + b),
110 (RootEm(a), RootEm(b)) => RootEm(a + b),
111 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a + b),
112 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a + b),
113 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a + b),
114 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a + b),
115 (PxF32(a), PxF32(b)) => PxF32(a + b),
116 (DipF32(a), DipF32(b)) => DipF32(a + b),
117 (Px(a), PxF32(b)) | (PxF32(b), Px(a)) => PxF32(a.0 as f32 + b),
118 (Dip(a), DipF32(b)) | (DipF32(b), Dip(a)) => DipF32(a.to_f32() + b),
119 (a, b) => {
120 *self = a;
121 *rhs = b;
122 return false;
123 }
124 };
125
126 *self = ok;
127 true
128 }
129}
130impl<L: Into<Length>> ops::Sub<L> for Length {
131 type Output = Length;
132
133 fn sub(mut self, rhs: L) -> Self::Output {
134 let mut rhs = rhs.into();
135
136 if self.try_sub(&mut rhs) {
137 self
138 } else {
139 LengthExpr::Sub(self, rhs).to_length_checked()
140 }
141 }
142}
143impl<L: Into<Length>> ops::SubAssign<L> for Length {
144 fn sub_assign(&mut self, rhs: L) {
145 let lhs = mem::take(self);
146 *self = lhs - rhs.into();
147 }
148}
149impl Length {
150 pub(crate) fn try_sub(&mut self, rhs: &mut Self) -> bool {
151 use Length::*;
152
153 if rhs.is_zero() == Some(true) {
154 return true; } else if self.is_zero() == Some(true) {
156 *self = -mem::take(rhs);
157 return true; }
159
160 let ok = match (mem::take(self), mem::take(rhs)) {
161 (Dip(a), Dip(b)) => Dip(a - b),
162 (Px(a), Px(b)) => Px(a - b),
163 (Pt(a), Pt(b)) => Pt(a - b),
164 (Factor(a), Factor(b)) => Factor(a - b),
165 (Leftover(a), Leftover(b)) => Leftover(a - b),
166 (Em(a), Em(b)) => Em(a - b),
167 (RootEm(a), RootEm(b)) => RootEm(a - b),
168 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a - b),
169 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a - b),
170 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a - b),
171 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a - b),
172 (PxF32(a), PxF32(b)) => PxF32(a - b),
173 (DipF32(a), DipF32(b)) => DipF32(a - b),
174 (Px(a), PxF32(b)) => PxF32(a.0 as f32 - b),
175 (PxF32(a), Px(b)) => PxF32(a - b.0 as f32),
176 (Dip(a), DipF32(b)) => DipF32(a.to_f32() - b),
177 (DipF32(a), Dip(b)) => DipF32(a - b.to_f32()),
178 (a, b) => {
179 *self = a;
180 *rhs = b;
181 return false;
182 }
183 };
184
185 *self = ok;
186 true
187 }
188}
189impl<F: Into<Factor>> ops::Mul<F> for Length {
190 type Output = Length;
191
192 fn mul(mut self, rhs: F) -> Self::Output {
193 let rhs = rhs.into();
194 if self.try_mul(rhs) {
195 self
196 } else {
197 LengthExpr::Mul(self, rhs).to_length_checked()
198 }
199 }
200}
201impl<F: Into<Factor>> ops::MulAssign<F> for Length {
202 fn mul_assign(&mut self, rhs: F) {
203 let lhs = mem::take(self);
204 *self = lhs * rhs.into();
205 }
206}
207impl Length {
208 pub(crate) fn try_mul(&mut self, rhs: Factor) -> bool {
209 use Length::*;
210
211 if self.is_zero() == Some(true) || rhs == 1.fct() {
212 return true; } else if rhs == 0.fct() {
214 *self = Self::zero();
215 return true; }
217
218 let ok = match mem::take(self) {
219 Dip(e) => DipF32(e.to_f32() * rhs.0),
220 Px(e) => PxF32(e.0 as f32 * rhs.0),
221 Pt(e) => Pt(e * rhs.0),
222 Factor(r) => Factor(r * rhs),
223 Leftover(r) => Leftover(r * rhs),
224 Em(e) => Em(e * rhs),
225 RootEm(e) => RootEm(e * rhs),
226 ViewportWidth(w) => ViewportWidth(w * rhs),
227 ViewportHeight(h) => ViewportHeight(h * rhs),
228 ViewportMin(m) => ViewportMin(m * rhs),
229 ViewportMax(m) => ViewportMax(m * rhs),
230 DipF32(e) => DipF32(e * rhs.0),
231 PxF32(e) => PxF32(e * rhs.0),
232 e => {
233 *self = e;
234 return false;
235 }
236 };
237
238 *self = ok;
239 true
240 }
241}
242
243impl<F: Into<Factor>> ops::Div<F> for Length {
244 type Output = Length;
245
246 fn div(mut self, rhs: F) -> Self::Output {
247 let rhs = rhs.into();
248 if self.try_div(rhs) {
249 self
250 } else {
251 LengthExpr::Div(self, rhs).to_length_checked()
252 }
253 }
254}
255impl<F: Into<Factor>> ops::DivAssign<F> for Length {
256 fn div_assign(&mut self, rhs: F) {
257 let lhs = mem::take(self);
258 *self = lhs / rhs.into();
259 }
260}
261impl Length {
262 pub(crate) fn try_div(&mut self, rhs: Factor) -> bool {
263 use Length::*;
264
265 if self.is_zero() == Some(true) && rhs != 0.fct() {
266 return true; }
268
269 let ok = match mem::take(self) {
270 Dip(e) => DipF32(e.to_f32() / rhs.0),
271 Px(e) => PxF32(e.0 as f32 / rhs.0),
272 Pt(e) => Pt(e / rhs.0),
273 Factor(r) => Factor(r / rhs),
274 Leftover(r) => Leftover(r / rhs),
275 Em(e) => Em(e / rhs),
276 RootEm(e) => RootEm(e / rhs),
277 ViewportWidth(w) => ViewportWidth(w / rhs),
278 ViewportHeight(h) => ViewportHeight(h / rhs),
279 ViewportMin(m) => ViewportMin(m / rhs),
280 ViewportMax(m) => ViewportMax(m / rhs),
281 DipF32(e) => DipF32(e / rhs.0),
282 PxF32(e) => PxF32(e / rhs.0),
283 e => {
284 *self = e;
285 return false;
286 }
287 };
288
289 *self = ok;
290 true
291 }
292}
293impl Transitionable for Length {
294 fn lerp(mut self, to: &Self, step: EasingStep) -> Self {
295 if self.try_lerp(to, step) {
296 self
297 } else {
298 LengthExpr::Lerp(self, to.clone(), step).to_length_checked()
299 }
300 }
301}
302impl Length {
303 pub(crate) fn try_lerp(&mut self, to: &Self, step: EasingStep) -> bool {
304 use Length::*;
305
306 if step == 0.fct() {
307 return true;
308 }
309 if step == 1.fct() {
310 *self = to.clone();
311 return true;
312 }
313 if self == to || self.is_zero().unwrap_or(false) && to.is_zero().unwrap_or(false) {
314 return true;
315 }
316
317 let ok = match (mem::take(self), to) {
318 (Dip(a), Dip(b)) => Dip(a.lerp(b, step)),
319 (Px(a), Px(b)) => Px(a.lerp(b, step)),
320 (Pt(a), Pt(b)) => Pt(a.lerp(b, step)),
321 (Factor(a), Factor(b)) => Factor(a.lerp(b, step)),
322 (Leftover(a), Leftover(b)) => Leftover(a.lerp(b, step)),
323 (Em(a), Em(b)) => Em(a.lerp(b, step)),
324 (RootEm(a), RootEm(b)) => RootEm(a.lerp(b, step)),
325 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.lerp(b, step)),
326 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.lerp(b, step)),
327 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.lerp(b, step)),
328 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.lerp(b, step)),
329 (PxF32(a), PxF32(b)) => PxF32(a.lerp(b, step)),
330 (DipF32(a), DipF32(b)) => DipF32(a.lerp(b, step)),
331 (Px(a), PxF32(b)) => PxF32((a.0 as f32).lerp(b, step)),
332 (PxF32(a), Px(b)) => PxF32(a.lerp(&(b.0 as f32), step)),
333 (Dip(a), DipF32(b)) => DipF32(a.to_f32().lerp(b, step)),
334 (DipF32(a), Dip(b)) => DipF32(a.lerp(&b.to_f32(), step)),
335 (a, _) => {
336 *self = a;
337 return false;
338 }
339 };
340
341 *self = ok;
342 true
343 }
344}
345impl ops::Neg for Length {
346 type Output = Self;
347
348 fn neg(self) -> Self::Output {
349 match self {
350 Length::Default => LengthExpr::Neg(Length::Default).to_length_checked(),
351 Length::Dip(e) => Length::Dip(-e),
352 Length::Px(e) => Length::Px(-e),
353 Length::Pt(e) => Length::Pt(-e),
354 Length::Factor(e) => Length::Factor(-e),
355 Length::Leftover(e) => Length::Leftover(-e),
356 Length::Em(e) => Length::Em(-e),
357 Length::RootEm(e) => Length::RootEm(-e),
358 Length::ViewportWidth(e) => Length::ViewportWidth(-e),
359 Length::ViewportHeight(e) => Length::ViewportHeight(-e),
360 Length::ViewportMin(e) => Length::ViewportMin(-e),
361 Length::ViewportMax(e) => Length::ViewportMax(-e),
362 Length::DipF32(e) => Length::DipF32(-e),
363 Length::PxF32(e) => Length::PxF32(-e),
364 Length::Expr(e) => LengthExpr::Neg(Length::Expr(e)).to_length_checked(),
365 }
366 }
367}
368impl Default for Length {
369 fn default() -> Self {
371 Length::Default
372 }
373}
374impl PartialEq for Length {
375 fn eq(&self, other: &Self) -> bool {
376 use Length::*;
377 match (self, other) {
378 (Default, Default) => true,
379
380 (Dip(a), Dip(b)) => a == b,
381 (Px(a), Px(b)) => a == b,
382 (Pt(a), Pt(b)) => about_eq(*a, *b, EQ_GRANULARITY_100),
383
384 (DipF32(a), DipF32(b)) | (PxF32(a), PxF32(b)) => about_eq(*a, *b, EQ_GRANULARITY_100),
385
386 (Factor(a), Factor(b))
387 | (Em(a), Em(b))
388 | (RootEm(a), RootEm(b))
389 | (Leftover(a), Leftover(b))
390 | (ViewportWidth(a), ViewportWidth(b))
391 | (ViewportHeight(a), ViewportHeight(b))
392 | (ViewportMin(a), ViewportMin(b))
393 | (ViewportMax(a), ViewportMax(b)) => a == b,
394
395 (Expr(a), Expr(b)) => a == b,
396
397 (Dip(a), DipF32(b)) | (DipF32(b), Dip(a)) => about_eq(a.to_f32(), *b, EQ_GRANULARITY_100),
398 (Px(a), PxF32(b)) | (PxF32(b), Px(a)) => about_eq(a.0 as f32, *b, EQ_GRANULARITY_100),
399
400 (a, b) => {
401 debug_assert_ne!(std::mem::discriminant(a), std::mem::discriminant(b));
402 false
403 }
404 }
405 }
406}
407impl Eq for Length {}
408impl std::hash::Hash for Length {
409 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
410 core::mem::discriminant(self).hash(state);
411 match self {
412 Length::Default => {}
413 Length::Dip(dip) => dip.hash(state),
414 Length::Px(px) => px.hash(state),
415 Length::Factor(factor)
416 | Length::Leftover(factor)
417 | Length::Em(factor)
418 | Length::RootEm(factor)
419 | Length::ViewportWidth(factor)
420 | Length::ViewportHeight(factor)
421 | Length::ViewportMin(factor)
422 | Length::ViewportMax(factor) => factor.hash(state),
423 Length::DipF32(f) | Length::PxF32(f) | Length::Pt(f) => about_eq_hash(*f, EQ_GRANULARITY_100, state),
424 Length::Expr(length_expr) => length_expr.hash(state),
425 }
426 }
427}
428impl fmt::Debug for Length {
429 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430 use Length::*;
431 if f.alternate() {
432 match self {
433 Default => write!(f, "Length::Default"),
434 Dip(e) => f.debug_tuple("Length::Dip").field(e).finish(),
435 Px(e) => f.debug_tuple("Length::Px").field(e).finish(),
436 Pt(e) => f.debug_tuple("Length::Pt").field(e).finish(),
437 Factor(e) => f.debug_tuple("Length::Factor").field(e).finish(),
438 Leftover(e) => f.debug_tuple("Length::Leftover").field(e).finish(),
439 Em(e) => f.debug_tuple("Length::Em").field(e).finish(),
440 RootEm(e) => f.debug_tuple("Length::RootEm").field(e).finish(),
441 ViewportWidth(e) => f.debug_tuple("Length::ViewportWidth").field(e).finish(),
442 ViewportHeight(e) => f.debug_tuple("Length::ViewportHeight").field(e).finish(),
443 ViewportMin(e) => f.debug_tuple("Length::ViewportMin").field(e).finish(),
444 ViewportMax(e) => f.debug_tuple("Length::ViewportMax").field(e).finish(),
445 DipF32(e) => f.debug_tuple("Length::DipF32").field(e).finish(),
446 PxF32(e) => f.debug_tuple("Length::PxF32").field(e).finish(),
447 Expr(e) => f.debug_tuple("Length::Expr").field(e).finish(),
448 }
449 } else {
450 match self {
451 Default => write!(f, "Default"),
452 Dip(e) => write!(f, "{:.*}.dip()", f.precision().unwrap_or(0), e.to_f32()),
453 Px(e) => write!(f, "{}.px()", e.0),
454 Pt(e) => write!(f, "{e:.*}.pt()", f.precision().unwrap_or(0)),
455 Factor(e) => write!(f, "{:.*}.pct()", f.precision().unwrap_or(0), e.0 * 100.0),
456 Leftover(e) => write!(f, "{:.*}.lft()", f.precision().unwrap_or(0), e.0),
457 Em(e) => write!(f, "{:.*}.em()", f.precision().unwrap_or(0), e.0),
458 RootEm(e) => write!(f, "{:.*}.rem()", f.precision().unwrap_or(0), e.0),
459 ViewportWidth(e) => write!(f, "{e:.*}.vw()", f.precision().unwrap_or(0)),
460 ViewportHeight(e) => write!(f, "{e:.*}.vh()", f.precision().unwrap_or(0)),
461 ViewportMin(e) => write!(f, "{e:.*}.vmin()", f.precision().unwrap_or(0)),
462 ViewportMax(e) => write!(f, "{e:.*}.vmax()", f.precision().unwrap_or(0)),
463 DipF32(e) => write!(f, "{e:.*}.dip()", f.precision().unwrap_or(0)),
464 PxF32(e) => write!(f, "{e:.*}.px()", f.precision().unwrap_or(0)),
465 Expr(e) => write!(f, "{e:.*}", f.precision().unwrap_or(0)),
466 }
467 }
468 }
469}
470impl fmt::Display for Length {
471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 use Length::*;
473 match self {
474 Default => write!(f, "default"),
475 Dip(l) => write!(f, "{l:.*}", f.precision().unwrap_or(0)),
476 Px(l) => write!(f, "{l}"),
477 Pt(l) => write!(f, "{l:.*}pt", f.precision().unwrap_or(0)),
478 Factor(n) => write!(f, "{:.*}%", f.precision().unwrap_or(0), n.0 * 100.0),
479 Leftover(l) => write!(f, "{l:.*}lft", f.precision().unwrap_or(0)),
480 Em(e) => write!(f, "{e:.*}em", f.precision().unwrap_or(0)),
481 RootEm(re) => write!(f, "{re:.*}rem", f.precision().unwrap_or(0)),
482 ViewportWidth(vw) => write!(f, "{vw:.*}vw", f.precision().unwrap_or(0)),
483 ViewportHeight(vh) => write!(f, "{vh:.*}vh", f.precision().unwrap_or(0)),
484 ViewportMin(vmin) => write!(f, "{vmin:.*}vmin", f.precision().unwrap_or(0)),
485 ViewportMax(vmax) => write!(f, "{vmax:.*}vmax", f.precision().unwrap_or(0)),
486 DipF32(l) => write!(f, "{l:.*}dip", f.precision().unwrap_or(0)),
487 PxF32(l) => write!(f, "{l:.*}px", f.precision().unwrap_or(0)),
488 Expr(e) => write!(f, "{e:.*}", f.precision().unwrap_or(0)),
489 }
490 }
491}
492impl std::str::FromStr for Length {
493 type Err = ParseCompositeError;
494
495 fn from_str(s: &str) -> Result<Self, Self::Err> {
496 let mut r = if s == "default" || s == "Default" {
497 Self::Default
498 } else if let Some(dip) = s.strip_suffix("dip").or_else(|| s.strip_suffix(".dip()")) {
499 if dip.contains('.') {
500 Self::DipF32(dip.parse()?)
501 } else {
502 Self::Dip(Dip::new_f32(dip.parse()?))
503 }
504 } else if let Some(px) = s.strip_suffix("px").or_else(|| s.strip_suffix(".px()")) {
505 if px.contains('.') {
506 Self::PxF32(px.parse()?)
507 } else {
508 Self::Px(Px(px.parse()?))
509 }
510 } else if let Some(pt) = s.strip_suffix("pt").or_else(|| s.strip_suffix(".pt()")) {
511 Self::Pt(pt.parse()?)
512 } else if let Some(fct) = s.strip_suffix("fct").or_else(|| s.strip_suffix(".fct()")) {
513 Self::Factor(Factor(fct.parse()?))
514 } else if let Some(fct) = s.strip_suffix("%").or_else(|| s.strip_suffix(".pct()")) {
515 Self::Factor(FactorPercent(fct.parse()?).fct())
516 } else if let Some(lft) = s.strip_suffix("lft").or_else(|| s.strip_suffix(".lft()")) {
517 Self::Leftover(Factor(lft.parse()?))
518 } else if let Some(em) = s.strip_suffix("em").or_else(|| s.strip_suffix(".em()")) {
519 Self::Em(Factor(em.parse()?))
520 } else if let Some(root_em) = s.strip_suffix("rem").or_else(|| s.strip_suffix(".rem()")) {
521 Self::RootEm(Factor(root_em.parse()?))
522 } else if let Some(vw) = s.strip_suffix("vw").or_else(|| s.strip_suffix(".vw()")) {
523 Self::ViewportWidth(Factor(vw.parse()?))
524 } else if let Some(vh) = s.strip_suffix("vh").or_else(|| s.strip_suffix(".vh()")) {
525 Self::ViewportHeight(Factor(vh.parse()?))
526 } else if let Some(v_min) = s.strip_suffix("vmin").or_else(|| s.strip_suffix(".vmin()")) {
527 Self::ViewportMin(Factor(v_min.parse()?))
528 } else if let Some(v_max) = s.strip_suffix("vmax").or_else(|| s.strip_suffix(".vmax()")) {
529 Self::ViewportMax(Factor(v_max.parse()?))
530 } else if let Ok(int) = s.parse::<i32>() {
531 Self::Dip(Dip::new(int))
532 } else if let Ok(float) = s.parse::<f32>() {
533 Self::DipF32(float)
534 } else {
535 Self::Expr(Box::new(s.parse()?))
536 };
537 r.simplify();
538 Ok(r)
539 }
540}
541impl_from_and_into_var! {
542 fn from(percent: FactorPercent) -> Length {
544 Length::Factor(percent.into())
545 }
546
547 fn from(norm: Factor) -> Length {
549 Length::Factor(norm)
550 }
551
552 fn from(f: f32) -> Length {
554 Length::DipF32(f)
555 }
556
557 fn from(i: i32) -> Length {
559 Length::Dip(Dip::new(i))
560 }
561
562 fn from(l: Px) -> Length {
564 Length::Px(l)
565 }
566
567 fn from(l: Dip) -> Length {
569 Length::Dip(l)
570 }
571
572 fn from(expr: LengthExpr) -> Length {
573 Length::Expr(Box::new(expr))
574 }
575
576 fn from(length: Length) -> LengthExpr {
577 match length {
578 Length::Expr(e) => *e,
579 l => LengthExpr::Unit(l),
580 }
581 }
582}
583impl Length {
584 pub const fn zero() -> Length {
586 Length::Px(Px(0))
587 }
588
589 pub const fn fill() -> Length {
591 Length::Factor(Factor(1.0))
592 }
593
594 pub const fn half() -> Length {
596 Length::Factor(Factor(0.5))
597 }
598
599 pub fn max(&self, other: impl Into<Length>) -> Length {
601 let mut self_ = self.clone();
603 let mut other = other.into();
604 if self_.try_max(&mut other) {
605 self_
606 } else {
607 LengthExpr::Max(self_, other).to_length_checked()
608 }
609 }
610 pub(crate) fn try_max(&mut self, other: &mut Self) -> bool {
611 use Length::*;
612 let ok = match (mem::take(self), mem::take(other)) {
613 (Default, Default) => Default,
614 (Dip(a), Dip(b)) => Dip(a.max(b)),
615 (Px(a), Px(b)) => Px(a.max(b)),
616 (Pt(a), Pt(b)) => Pt(a.max(b)),
617 (Factor(a), Factor(b)) => Factor(a.max(b)),
618 (Leftover(a), Leftover(b)) => Leftover(a.max(b)),
619 (Em(a), Em(b)) => Em(a.max(b)),
620 (RootEm(a), RootEm(b)) => RootEm(a.max(b)),
621 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.max(b)),
622 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.max(b)),
623 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.max(b)),
624 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.max(b)),
625 (DipF32(a), DipF32(b)) => DipF32(a.max(b)),
626 (PxF32(a), PxF32(b)) => PxF32(a.max(b)),
627 (DipF32(a), Dip(b)) | (Dip(b), DipF32(a)) => DipF32(a.max(b.to_f32())),
628 (PxF32(a), Px(b)) | (Px(b), PxF32(a)) => PxF32(a.max(b.0 as f32)),
629 (a, b) => {
630 *self = a;
631 *other = b;
632 return false;
633 }
634 };
635 *self = ok;
636 true
637 }
638
639 pub fn min(&self, other: impl Into<Length>) -> Length {
641 let mut self_ = self.clone();
643 let mut other = other.into();
644 if self_.try_min(&mut other) {
645 self_
646 } else {
647 LengthExpr::Min(self_, other).to_length_checked()
648 }
649 }
650 pub(crate) fn try_min(&mut self, other: &mut Self) -> bool {
651 use Length::*;
652 let ok = match (mem::take(self), mem::take(other)) {
653 (Default, Default) => Default,
654 (Dip(a), Dip(b)) => Dip(a.min(b)),
655 (Px(a), Px(b)) => Px(a.min(b)),
656 (Pt(a), Pt(b)) => Pt(a.min(b)),
657 (Factor(a), Factor(b)) => Factor(a.min(b)),
658 (Leftover(a), Leftover(b)) => Leftover(a.min(b)),
659 (Em(a), Em(b)) => Em(a.min(b)),
660 (RootEm(a), RootEm(b)) => RootEm(a.min(b)),
661 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.min(b)),
662 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.min(b)),
663 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.min(b)),
664 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.min(b)),
665 (DipF32(a), DipF32(b)) => DipF32(a.min(b)),
666 (PxF32(a), PxF32(b)) => PxF32(a.min(b)),
667 (DipF32(a), Dip(b)) | (Dip(b), DipF32(a)) => DipF32(a.min(b.to_f32())),
668 (PxF32(a), Px(b)) | (Px(b), PxF32(a)) => PxF32(a.min(b.0 as f32)),
669 (a, b) => {
670 *self = a;
671 *other = b;
672 return false;
673 }
674 };
675 *self = ok;
676 true
677 }
678
679 pub fn clamp(&self, min: impl Into<Length>, max: impl Into<Length>) -> Length {
681 self.max(min).min(max)
683 }
684
685 pub fn abs(&self) -> Length {
687 use Length::*;
689 match self {
690 Default => LengthExpr::Abs(Length::Default).to_length_checked(),
691 Dip(e) => Dip(e.abs()),
692 Px(e) => Px(e.abs()),
693 Pt(e) => Pt(e.abs()),
694 Factor(r) => Factor(r.abs()),
695 Leftover(r) => Leftover(r.abs()),
696 Em(e) => Em(e.abs()),
697 RootEm(r) => RootEm(r.abs()),
698 ViewportWidth(w) => ViewportWidth(w.abs()),
699 ViewportHeight(h) => ViewportHeight(h.abs()),
700 ViewportMin(m) => ViewportMin(m.abs()),
701 ViewportMax(m) => ViewportMax(m.abs()),
702 DipF32(e) => DipF32(e.abs()),
703 PxF32(e) => PxF32(e.abs()),
704 Expr(e) => LengthExpr::Abs(Length::Expr(e.clone())).to_length_checked(),
705 }
706 }
707
708 pub fn is_zero(&self) -> Option<bool> {
712 use Length::*;
713 match self {
714 Default => None,
715 Dip(l) => Some(*l == self::Dip::new(0)),
716 Px(l) => Some(*l == self::Px(0)),
717 Pt(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY)),
718 Factor(f) | Leftover(f) | Em(f) | RootEm(f) | ViewportWidth(f) | ViewportHeight(f) | ViewportMin(f) | ViewportMax(f) => {
719 Some(*f == 0.fct())
720 }
721 DipF32(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY_100)),
722 PxF32(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY_100)),
723 Expr(_) => None,
724 }
725 }
726
727 pub fn is_sign_negative(&self) -> Option<bool> {
731 use Length::*;
732 match self {
733 Default => None,
734 Dip(l) => Some(*l < self::Dip::new(0)),
735 Px(l) => Some(*l < self::Px(0)),
736 Pt(l) => Some(about_eq(*l, 0.0, EQ_GRANULARITY)),
737 Factor(f) | Leftover(f) | Em(f) | RootEm(f) | ViewportWidth(f) | ViewportHeight(f) | ViewportMin(f) | ViewportMax(f) => {
738 Some(*f < 0.fct())
739 }
740 DipF32(l) => Some(l.is_sign_negative()),
741 PxF32(l) => Some(l.is_sign_negative()),
742 Expr(_) => None,
743 }
744 }
745
746 pub fn pt_to_px(pt: f32, scale_factor: Factor) -> Px {
748 let px = Self::pt_to_px_f32(pt, scale_factor);
749 Px(px.round() as i32)
750 }
751
752 pub fn pt_to_px_f32(pt: f32, scale_factor: Factor) -> f32 {
756 pt * Self::PT_TO_DIP * scale_factor.0
757 }
758
759 pub fn px_to_pt(px: Px, scale_factor: Factor) -> f32 {
761 let dip = px.0 as f32 / scale_factor.0;
762 dip / Self::PT_TO_DIP
763 }
764
765 pub fn is_default(&self) -> bool {
769 matches!(self, Length::Default)
770 }
771
772 pub fn has_default(&self) -> bool {
777 match self {
778 Length::Default => true,
779 Length::Expr(e) => e.has_default(),
780 _ => false,
781 }
782 }
783
784 pub fn replace_default(&mut self, overwrite: &Length) {
789 match self {
790 Length::Default => *self = overwrite.clone(),
791 Length::Expr(e) => e.replace_default(overwrite),
792 _ => {}
793 }
794 }
795
796 pub fn round_exact(&mut self) {
803 match self {
804 Length::PxF32(l) => *self = Length::Px(Px(l.round() as i32)),
805 Length::DipF32(l) => *self = Length::Dip(Dip::new_f32(*l)),
806 Length::Expr(e) => e.round_exact(),
807 _ => {}
808 }
809 }
810
811 pub fn simplify(&mut self) {
813 if let Length::Expr(e) = self {
814 e.simplify();
815 if let LengthExpr::Unit(u) = &mut **e {
816 *self = mem::take(u);
817 }
818 }
819 if self.is_zero().unwrap_or(false) {
820 *self = Length::Px(Px(0));
821 }
822 }
823
824 pub fn memory_used(&self) -> ByteLength {
828 std::mem::size_of::<Length>().bytes() + self.heap_memory_used()
829 }
830
831 pub fn heap_memory_used(&self) -> ByteLength {
833 if let Length::Expr(e) = self { e.memory_used() } else { 0.bytes() }
834 }
835
836 const PT_TO_DIP: f32 = 96.0 / 72.0; }
839impl super::Layout1d for Length {
840 fn layout_dft(&self, axis: LayoutAxis, default: Px) -> Px {
841 use Length::*;
842 match self {
843 Default => default,
844 Dip(l) => l.to_px(LAYOUT.scale_factor()),
845 Px(l) => *l,
846 Pt(l) => Self::pt_to_px(*l, LAYOUT.scale_factor()),
847 Factor(f) => LAYOUT.constraints_for(axis).fill() * f.0,
848 Leftover(f) => {
849 if let Some(l) = LAYOUT.leftover_for(axis) {
850 l
851 } else {
852 let fill = LAYOUT.constraints_for(axis).fill();
853 (fill * f.0).clamp(self::Px(0), fill)
854 }
855 }
856 Em(f) => LAYOUT.font_size() * f.0,
857 RootEm(f) => LAYOUT.root_font_size() * f.0,
858 ViewportWidth(p) => LAYOUT.viewport().width * *p,
859 ViewportHeight(p) => LAYOUT.viewport().height * *p,
860 ViewportMin(p) => LAYOUT.viewport_min() * *p,
861 ViewportMax(p) => LAYOUT.viewport_max() * *p,
862 DipF32(l) => self::Px((l * LAYOUT.scale_factor().0).round() as i32),
863 PxF32(l) => self::Px(l.round() as i32),
864 Expr(e) => e.layout_dft(axis, default),
865 }
866 }
867
868 fn layout_f32_dft(&self, axis: LayoutAxis, default: f32) -> f32 {
869 use Length::*;
870 match self {
871 Default => default,
872 Dip(l) => l.to_f32() * LAYOUT.scale_factor().0,
873 Px(l) => l.0 as f32,
874 Pt(l) => Self::pt_to_px_f32(*l, LAYOUT.scale_factor()),
875 Factor(f) => LAYOUT.constraints_for(axis).fill().0 as f32 * f.0,
876 Leftover(f) => {
877 if let Some(l) = LAYOUT.leftover_for(axis) {
878 l.0 as f32
879 } else {
880 let fill = LAYOUT.constraints_for(axis).fill().0 as f32;
881 (fill * f.0).clamp(0.0, fill)
882 }
883 }
884 Em(f) => LAYOUT.font_size().0 as f32 * f.0,
885 RootEm(f) => LAYOUT.root_font_size().0 as f32 * f.0,
886 ViewportWidth(p) => LAYOUT.viewport().width.0 as f32 * *p,
887 ViewportHeight(p) => LAYOUT.viewport().height.0 as f32 * *p,
888 ViewportMin(p) => LAYOUT.viewport_min().0 as f32 * *p,
889 ViewportMax(p) => LAYOUT.viewport_max().0 as f32 * *p,
890 DipF32(l) => *l * LAYOUT.scale_factor().0,
891 PxF32(l) => *l,
892 Expr(e) => e.layout_f32_dft(axis, default),
893 }
894 }
895
896 fn affect_mask(&self) -> LayoutMask {
897 use Length::*;
898 match self {
899 Default => LayoutMask::DEFAULT_VALUE,
900 Dip(_) => LayoutMask::SCALE_FACTOR,
901 Px(_) => LayoutMask::empty(),
902 Pt(_) => LayoutMask::SCALE_FACTOR,
903 Factor(_) => LayoutMask::CONSTRAINTS,
904 Leftover(_) => LayoutMask::LEFTOVER,
905 Em(_) => LayoutMask::FONT_SIZE,
906 RootEm(_) => LayoutMask::ROOT_FONT_SIZE,
907 ViewportWidth(_) => LayoutMask::VIEWPORT,
908 ViewportHeight(_) => LayoutMask::VIEWPORT,
909 ViewportMin(_) => LayoutMask::VIEWPORT,
910 ViewportMax(_) => LayoutMask::VIEWPORT,
911 DipF32(_) => LayoutMask::SCALE_FACTOR,
912 PxF32(_) => LayoutMask::empty(),
913 Expr(e) => e.affect_mask(),
914 }
915 }
916}
917
918pub trait LengthUnits {
940 fn dip(self) -> Length;
944
945 fn px(self) -> Length;
949
950 fn pt(self) -> Length;
954
955 fn fct_l(self) -> Length;
962
963 fn pct_l(self) -> Length;
970
971 fn em(self) -> Length;
975
976 fn em_pct(self) -> Length;
980
981 fn rem(self) -> Length;
985
986 fn rem_pct(self) -> Length;
990
991 fn vw(self) -> Length;
995
996 fn vw_pct(self) -> Length;
1000
1001 fn vh(self) -> Length;
1005
1006 fn vh_pct(self) -> Length;
1010
1011 fn vmin(self) -> Length;
1015
1016 fn vmin_pct(self) -> Length;
1020
1021 fn vmax(self) -> Length;
1025
1026 fn vmax_pct(self) -> Length;
1030
1031 fn lft(self) -> Length;
1038}
1039impl LengthUnits for f32 {
1040 fn dip(self) -> Length {
1041 Length::DipF32(self)
1042 }
1043
1044 fn px(self) -> Length {
1045 Length::PxF32(self)
1046 }
1047
1048 fn pt(self) -> Length {
1049 Length::Pt(self)
1050 }
1051
1052 fn fct_l(self) -> Length {
1053 Length::Factor(self.fct())
1054 }
1055
1056 fn pct_l(self) -> Length {
1057 Length::Factor(self.pct().fct())
1058 }
1059
1060 fn em(self) -> Length {
1061 Length::Em(self.into())
1062 }
1063
1064 fn rem(self) -> Length {
1065 Length::RootEm(self.into())
1066 }
1067
1068 fn vw(self) -> Length {
1069 Length::ViewportWidth(self.into())
1070 }
1071
1072 fn vh(self) -> Length {
1073 Length::ViewportHeight(self.into())
1074 }
1075
1076 fn vmin(self) -> Length {
1077 Length::ViewportMin(self.into())
1078 }
1079
1080 fn vmax(self) -> Length {
1081 Length::ViewportMax(self.into())
1082 }
1083
1084 fn em_pct(self) -> Length {
1085 Length::Em(self.pct().into())
1086 }
1087
1088 fn rem_pct(self) -> Length {
1089 Length::RootEm(self.pct().into())
1090 }
1091
1092 fn vw_pct(self) -> Length {
1093 Length::ViewportWidth(self.pct().into())
1094 }
1095
1096 fn vh_pct(self) -> Length {
1097 Length::ViewportHeight(self.pct().into())
1098 }
1099
1100 fn vmin_pct(self) -> Length {
1101 Length::ViewportMin(self.pct().into())
1102 }
1103
1104 fn vmax_pct(self) -> Length {
1105 Length::ViewportMax(self.pct().into())
1106 }
1107
1108 fn lft(self) -> Length {
1109 Length::Leftover(self.fct())
1110 }
1111}
1112impl LengthUnits for i32 {
1113 fn dip(self) -> Length {
1114 Length::Dip(Dip::new(self))
1115 }
1116
1117 fn px(self) -> Length {
1118 Length::Px(Px(self))
1119 }
1120
1121 fn pt(self) -> Length {
1122 Length::Pt(self as f32)
1123 }
1124
1125 fn fct_l(self) -> Length {
1126 Length::Factor(self.fct())
1127 }
1128
1129 fn pct_l(self) -> Length {
1130 Length::Factor(self.pct().fct())
1131 }
1132
1133 fn em(self) -> Length {
1134 Length::Em(self.fct())
1135 }
1136
1137 fn rem(self) -> Length {
1138 Length::RootEm(self.fct())
1139 }
1140
1141 fn vw(self) -> Length {
1142 Length::ViewportWidth(self.fct())
1143 }
1144
1145 fn vh(self) -> Length {
1146 Length::ViewportHeight(self.fct())
1147 }
1148
1149 fn vmin(self) -> Length {
1150 Length::ViewportMin(self.fct())
1151 }
1152
1153 fn vmax(self) -> Length {
1154 Length::ViewportMax(self.fct())
1155 }
1156
1157 fn em_pct(self) -> Length {
1158 Length::Em(self.pct().into())
1159 }
1160
1161 fn rem_pct(self) -> Length {
1162 Length::RootEm(self.pct().into())
1163 }
1164
1165 fn vw_pct(self) -> Length {
1166 Length::ViewportWidth(self.pct().into())
1167 }
1168
1169 fn vh_pct(self) -> Length {
1170 Length::ViewportHeight(self.pct().into())
1171 }
1172
1173 fn vmin_pct(self) -> Length {
1174 Length::ViewportMin(self.pct().into())
1175 }
1176
1177 fn vmax_pct(self) -> Length {
1178 Length::ViewportMax(self.pct().into())
1179 }
1180
1181 fn lft(self) -> Length {
1182 Length::Leftover(self.fct())
1183 }
1184}