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