1use super::{
2 ByteLength, ByteUnits, Dip, DipToPx, EQ_EPSILON, EQ_EPSILON_100, Factor, FactorPercent, FactorUnits, LayoutAxis, Px, about_eq,
3};
4use std::{fmt, mem, ops};
5
6use zng_var::{
7 animation::{Transitionable, easing::EasingStep},
8 impl_from_and_into_var,
9};
10
11use crate::context::{LAYOUT, LayoutMask};
12
13#[derive(Clone, serde::Serialize, serde::Deserialize)]
25pub enum Length {
26 Default,
28 Dip(Dip),
30 Px(Px),
32 Pt(f32),
34 Factor(Factor),
36 Leftover(Factor),
38 Em(Factor),
40 RootEm(Factor),
42 ViewportWidth(Factor),
44 ViewportHeight(Factor),
46 ViewportMin(Factor),
48 ViewportMax(Factor),
50
51 DipF32(f32),
56 PxF32(f32),
61
62 Expr(Box<LengthExpr>),
64}
65impl<L: Into<Length>> ops::Add<L> for Length {
66 type Output = Length;
67
68 fn add(self, rhs: L) -> Self::Output {
69 use Length::*;
70
71 let rhs = rhs.into();
72
73 if self.is_zero() == Some(true) {
74 return rhs; } else if rhs.is_zero() == Some(true) {
76 return self; }
78
79 match (self, rhs) {
80 (Dip(a), Dip(b)) => Dip(a + b),
81 (Px(a), Px(b)) => Px(a + b),
82 (Pt(a), Pt(b)) => Pt(a + b),
83 (Factor(a), Factor(b)) => Factor(a + b),
84 (Leftover(a), Leftover(b)) => Leftover(a + b),
85 (Em(a), Em(b)) => Em(a + b),
86 (RootEm(a), RootEm(b)) => RootEm(a + b),
87 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a + b),
88 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a + b),
89 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a + b),
90 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a + b),
91 (PxF32(a), PxF32(b)) => PxF32(a + b),
92 (DipF32(a), DipF32(b)) => DipF32(a + b),
93 (Px(a), PxF32(b)) | (PxF32(b), Px(a)) => PxF32(a.0 as f32 + b),
94 (Dip(a), DipF32(b)) | (DipF32(b), Dip(a)) => DipF32(a.to_f32() + b),
95 (a, b) => LengthExpr::Add(a, b).to_length_checked(),
96 }
97 }
98}
99impl<L: Into<Length>> ops::AddAssign<L> for Length {
100 fn add_assign(&mut self, rhs: L) {
101 let lhs = mem::take(self);
102 *self = lhs + rhs.into();
103 }
104}
105impl<L: Into<Length>> ops::Sub<L> for Length {
106 type Output = Length;
107
108 fn sub(self, rhs: L) -> Self::Output {
109 use Length::*;
110
111 let rhs = rhs.into();
112
113 if rhs.is_zero() == Some(true) {
114 return self; } else if self.is_zero() == Some(true) {
116 return -rhs; }
118
119 match (self, rhs) {
120 (Dip(a), Dip(b)) => Dip(a - b),
121 (Px(a), Px(b)) => Px(a - b),
122 (Pt(a), Pt(b)) => Pt(a - b),
123 (Factor(a), Factor(b)) => Factor(a - b),
124 (Leftover(a), Leftover(b)) => Leftover(a - b),
125 (Em(a), Em(b)) => Em(a - b),
126 (RootEm(a), RootEm(b)) => RootEm(a - b),
127 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a - b),
128 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a - b),
129 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a - b),
130 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a - b),
131 (PxF32(a), PxF32(b)) => PxF32(a - b),
132 (DipF32(a), DipF32(b)) => DipF32(a - b),
133 (Px(a), PxF32(b)) => PxF32(a.0 as f32 - b),
134 (PxF32(a), Px(b)) => PxF32(a - b.0 as f32),
135 (Dip(a), DipF32(b)) => DipF32(a.to_f32() - b),
136 (DipF32(a), Dip(b)) => DipF32(a - b.to_f32()),
137 (a, b) => LengthExpr::Sub(a, b).to_length_checked(),
138 }
139 }
140}
141impl<L: Into<Length>> ops::SubAssign<L> for Length {
142 fn sub_assign(&mut self, rhs: L) {
143 let lhs = mem::take(self);
144 *self = lhs - rhs.into();
145 }
146}
147impl<F: Into<Factor>> ops::Mul<F> for Length {
148 type Output = Length;
149
150 fn mul(self, rhs: F) -> Self::Output {
151 use Length::*;
152 let rhs = rhs.into();
153
154 if self.is_zero() == Some(true) || rhs == 1.fct() {
155 return self; } else if rhs == 0.fct() {
157 return Self::zero(); }
159
160 match self {
161 Dip(e) => DipF32(e.to_f32() * rhs.0),
162 Px(e) => PxF32(e.0 as f32 * rhs.0),
163 Pt(e) => Pt(e * rhs.0),
164 Factor(r) => Factor(r * rhs),
165 Leftover(r) => Leftover(r * rhs),
166 Em(e) => Em(e * rhs),
167 RootEm(e) => RootEm(e * rhs),
168 ViewportWidth(w) => ViewportWidth(w * rhs),
169 ViewportHeight(h) => ViewportHeight(h * rhs),
170 ViewportMin(m) => ViewportMin(m * rhs),
171 ViewportMax(m) => ViewportMax(m * rhs),
172 DipF32(e) => DipF32(e * rhs.0),
173 PxF32(e) => PxF32(e * rhs.0),
174 e => LengthExpr::Mul(e, rhs).to_length_checked(),
175 }
176 }
177}
178impl<F: Into<Factor>> ops::MulAssign<F> for Length {
179 fn mul_assign(&mut self, rhs: F) {
180 let lhs = mem::take(self);
181 *self = lhs * rhs.into();
182 }
183}
184impl<F: Into<Factor>> ops::Div<F> for Length {
185 type Output = Length;
186
187 fn div(self, rhs: F) -> Self::Output {
188 use Length::*;
189
190 let rhs = rhs.into();
191
192 if self.is_zero() == Some(true) && rhs != 0.fct() {
193 return self; }
195
196 match self {
197 Dip(e) => DipF32(e.to_f32() / rhs.0),
198 Px(e) => PxF32(e.0 as f32 / rhs.0),
199 Pt(e) => Pt(e / rhs.0),
200 Factor(r) => Factor(r / rhs),
201 Leftover(r) => Leftover(r / rhs),
202 Em(e) => Em(e / rhs),
203 RootEm(e) => RootEm(e / rhs),
204 ViewportWidth(w) => ViewportWidth(w / rhs),
205 ViewportHeight(h) => ViewportHeight(h / rhs),
206 ViewportMin(m) => ViewportMin(m / rhs),
207 ViewportMax(m) => ViewportMax(m / rhs),
208 DipF32(e) => DipF32(e / rhs.0),
209 PxF32(e) => PxF32(e / rhs.0),
210 e => LengthExpr::Mul(e, rhs).to_length_checked(),
211 }
212 }
213}
214impl<F: Into<Factor>> ops::DivAssign<F> for Length {
215 fn div_assign(&mut self, rhs: F) {
216 let lhs = mem::take(self);
217 *self = lhs / rhs.into();
218 }
219}
220impl Transitionable for Length {
221 fn lerp(self, to: &Self, step: EasingStep) -> Self {
222 use Length::*;
223
224 if step == 0.fct() {
225 return self;
226 }
227 if step == 1.fct() {
228 return to.clone();
229 }
230
231 match (self, to) {
232 (Dip(a), Dip(b)) => Dip(a.lerp(b, step)),
233 (Px(a), Px(b)) => Px(a.lerp(b, step)),
234 (Pt(a), Pt(b)) => Pt(a.lerp(b, step)),
235 (Factor(a), Factor(b)) => Factor(a.lerp(b, step)),
236 (Leftover(a), Leftover(b)) => Leftover(a.lerp(b, step)),
237 (Em(a), Em(b)) => Em(a.lerp(b, step)),
238 (RootEm(a), RootEm(b)) => RootEm(a.lerp(b, step)),
239 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.lerp(b, step)),
240 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.lerp(b, step)),
241 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.lerp(b, step)),
242 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.lerp(b, step)),
243 (PxF32(a), PxF32(b)) => PxF32(a.lerp(b, step)),
244 (DipF32(a), DipF32(b)) => DipF32(a.lerp(b, step)),
245 (Px(a), PxF32(b)) => PxF32((a.0 as f32).lerp(b, step)),
246 (PxF32(a), Px(b)) => PxF32(a.lerp(&(b.0 as f32), step)),
247 (Dip(a), DipF32(b)) => DipF32(a.to_f32().lerp(b, step)),
248 (DipF32(a), Dip(b)) => DipF32(a.lerp(&b.to_f32(), step)),
249 (a, b) => LengthExpr::Lerp(a, b.clone(), step).to_length_checked(),
250 }
251 }
252}
253impl ops::Neg for Length {
254 type Output = Self;
255
256 fn neg(self) -> Self::Output {
257 match self {
258 Length::Default => LengthExpr::Neg(Length::Default).to_length_checked(),
259 Length::Dip(e) => Length::Dip(-e),
260 Length::Px(e) => Length::Px(-e),
261 Length::Pt(e) => Length::Pt(-e),
262 Length::Factor(e) => Length::Factor(-e),
263 Length::Leftover(e) => Length::Leftover(-e),
264 Length::Em(e) => Length::Em(-e),
265 Length::RootEm(e) => Length::RootEm(-e),
266 Length::ViewportWidth(e) => Length::ViewportWidth(-e),
267 Length::ViewportHeight(e) => Length::ViewportHeight(-e),
268 Length::ViewportMin(e) => Length::ViewportMin(-e),
269 Length::ViewportMax(e) => Length::ViewportMax(-e),
270 Length::DipF32(e) => Length::DipF32(-e),
271 Length::PxF32(e) => Length::PxF32(-e),
272 Length::Expr(e) => LengthExpr::Neg(Length::Expr(e)).to_length_checked(),
273 }
274 }
275}
276impl Default for Length {
277 fn default() -> Self {
279 Length::Default
280 }
281}
282impl PartialEq for Length {
283 fn eq(&self, other: &Self) -> bool {
284 use Length::*;
285 match (self, other) {
286 (Default, Default) => true,
287
288 (Dip(a), Dip(b)) => a == b,
289 (Px(a), Px(b)) => a == b,
290 (Pt(a), Pt(b)) => about_eq(*a, *b, EQ_EPSILON_100),
291
292 (DipF32(a), DipF32(b)) | (PxF32(a), PxF32(b)) => about_eq(*a, *b, EQ_EPSILON_100),
293
294 (Factor(a), Factor(b)) | (Em(a), Em(b)) | (RootEm(a), RootEm(b)) | (Leftover(a), Leftover(b)) => a == b,
295
296 (ViewportWidth(a), ViewportWidth(b))
297 | (ViewportHeight(a), ViewportHeight(b))
298 | (ViewportMin(a), ViewportMin(b))
299 | (ViewportMax(a), ViewportMax(b)) => about_eq(a.0, b.0, EQ_EPSILON),
300
301 (Expr(a), Expr(b)) => a == b,
302
303 (Dip(a), DipF32(b)) | (DipF32(b), Dip(a)) => about_eq(a.to_f32(), *b, EQ_EPSILON_100),
304 (Px(a), PxF32(b)) | (PxF32(b), Px(a)) => about_eq(a.0 as f32, *b, EQ_EPSILON_100),
305
306 _ => false,
307 }
308 }
309}
310impl fmt::Debug for Length {
311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312 use Length::*;
313 if f.alternate() {
314 match self {
315 Default => write!(f, "Length::Default"),
316 Dip(e) => f.debug_tuple("Length::Dip").field(e).finish(),
317 Px(e) => f.debug_tuple("Length::Px").field(e).finish(),
318 Pt(e) => f.debug_tuple("Length::Pt").field(e).finish(),
319 Factor(e) => f.debug_tuple("Length::Factor").field(e).finish(),
320 Leftover(e) => f.debug_tuple("Length::Leftover").field(e).finish(),
321 Em(e) => f.debug_tuple("Length::Em").field(e).finish(),
322 RootEm(e) => f.debug_tuple("Length::RootEm").field(e).finish(),
323 ViewportWidth(e) => f.debug_tuple("Length::ViewportWidth").field(e).finish(),
324 ViewportHeight(e) => f.debug_tuple("Length::ViewportHeight").field(e).finish(),
325 ViewportMin(e) => f.debug_tuple("Length::ViewportMin").field(e).finish(),
326 ViewportMax(e) => f.debug_tuple("Length::ViewportMax").field(e).finish(),
327 DipF32(e) => f.debug_tuple("Length::DipF32").field(e).finish(),
328 PxF32(e) => f.debug_tuple("Length::PxF32").field(e).finish(),
329 Expr(e) => f.debug_tuple("Length::Expr").field(e).finish(),
330 }
331 } else {
332 match self {
333 Default => write!(f, "Default"),
334 Dip(e) => write!(f, "{}.dip()", e.to_f32()),
335 Px(e) => write!(f, "{}.px()", e.0),
336 Pt(e) => write!(f, "{e}.pt()"),
337 Factor(e) => write!(f, "{}.pct()", e.0 * 100.0),
338 Leftover(e) => write!(f, "{}.lft()", e.0),
339 Em(e) => write!(f, "{}.em()", e.0),
340 RootEm(e) => write!(f, "{}.rem()", e.0),
341 ViewportWidth(e) => write!(f, "{e}.vw()"),
342 ViewportHeight(e) => write!(f, "{e}.vh()"),
343 ViewportMin(e) => write!(f, "{e}.vmin()"),
344 ViewportMax(e) => write!(f, "{e}.vmax()"),
345 DipF32(e) => write!(f, "{e}.dip()"),
346 PxF32(e) => write!(f, "{e}.px()"),
347 Expr(e) => write!(f, "{e}"),
348 }
349 }
350 }
351}
352impl fmt::Display for Length {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 use Length::*;
355 match self {
356 Default => write!(f, "Default"),
357 Dip(l) => write!(f, "{l}"),
358 Px(l) => write!(f, "{l}"),
359 Pt(l) => write!(f, "{l}pt"),
360 Factor(n) => write!(f, "{:.*}%", f.precision().unwrap_or(0), n.0 * 100.0),
361 Leftover(l) => write!(f, "{l}lft"),
362 Em(e) => write!(f, "{e}em"),
363 RootEm(re) => write!(f, "{re}rem"),
364 ViewportWidth(vw) => write!(f, "{vw}vw"),
365 ViewportHeight(vh) => write!(f, "{vh}vh"),
366 ViewportMin(vmin) => write!(f, "{vmin}vmin"),
367 ViewportMax(vmax) => write!(f, "{vmax}vmax"),
368 DipF32(l) => write!(f, "{l}dip"),
369 PxF32(l) => write!(f, "{l}px"),
370 Expr(e) => write!(f, "{e}"),
371 }
372 }
373}
374impl_from_and_into_var! {
375 fn from(percent: FactorPercent) -> Length {
377 Length::Factor(percent.into())
378 }
379
380 fn from(norm: Factor) -> Length {
382 Length::Factor(norm)
383 }
384
385 fn from(f: f32) -> Length {
387 Length::DipF32(f)
388 }
389
390 fn from(i: i32) -> Length {
392 Length::Dip(Dip::new(i))
393 }
394
395 fn from(l: Px) -> Length {
397 Length::Px(l)
398 }
399
400 fn from(l: Dip) -> Length {
402 Length::Dip(l)
403 }
404}
405impl Length {
406 pub const fn zero() -> Length {
408 Length::Px(Px(0))
409 }
410
411 pub const fn fill() -> Length {
413 Length::Factor(Factor(1.0))
414 }
415
416 pub const fn half() -> Length {
418 Length::Factor(Factor(0.5))
419 }
420
421 pub fn max(&self, other: impl Into<Length>) -> Length {
423 use Length::*;
424 match (self.clone(), other.into()) {
425 (Default, Default) => Default,
426 (Dip(a), Dip(b)) => Dip(a.max(b)),
427 (Px(a), Px(b)) => Px(a.max(b)),
428 (Pt(a), Pt(b)) => Pt(a.max(b)),
429 (Factor(a), Factor(b)) => Factor(a.max(b)),
430 (Leftover(a), Leftover(b)) => Leftover(a.max(b)),
431 (Em(a), Em(b)) => Em(a.max(b)),
432 (RootEm(a), RootEm(b)) => RootEm(a.max(b)),
433 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.max(b)),
434 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.max(b)),
435 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.max(b)),
436 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.max(b)),
437 (DipF32(a), DipF32(b)) => DipF32(a.max(b)),
438 (PxF32(a), PxF32(b)) => PxF32(a.max(b)),
439 (DipF32(a), Dip(b)) | (Dip(b), DipF32(a)) => DipF32(a.max(b.to_f32())),
440 (PxF32(a), Px(b)) | (Px(b), PxF32(a)) => PxF32(a.max(b.0 as f32)),
441 (a, b) => LengthExpr::Max(a, b).to_length_checked(),
442 }
443 }
444
445 pub fn min(&self, other: impl Into<Length>) -> Length {
447 use Length::*;
448 match (self.clone(), other.into()) {
449 (Default, Default) => Default,
450 (Dip(a), Dip(b)) => Dip(a.min(b)),
451 (Px(a), Px(b)) => Px(a.min(b)),
452 (Pt(a), Pt(b)) => Pt(a.min(b)),
453 (Factor(a), Factor(b)) => Factor(a.min(b)),
454 (Leftover(a), Leftover(b)) => Leftover(a.min(b)),
455 (Em(a), Em(b)) => Em(a.min(b)),
456 (RootEm(a), RootEm(b)) => RootEm(a.min(b)),
457 (ViewportWidth(a), ViewportWidth(b)) => ViewportWidth(a.min(b)),
458 (ViewportHeight(a), ViewportHeight(b)) => ViewportHeight(a.min(b)),
459 (ViewportMin(a), ViewportMin(b)) => ViewportMin(a.min(b)),
460 (ViewportMax(a), ViewportMax(b)) => ViewportMax(a.min(b)),
461 (DipF32(a), DipF32(b)) => DipF32(a.min(b)),
462 (PxF32(a), PxF32(b)) => PxF32(a.min(b)),
463 (DipF32(a), Dip(b)) | (Dip(b), DipF32(a)) => DipF32(a.min(b.to_f32())),
464 (PxF32(a), Px(b)) | (Px(b), PxF32(a)) => PxF32(a.min(b.0 as f32)),
465 (a, b) => LengthExpr::Min(a, b).to_length_checked(),
466 }
467 }
468
469 pub fn clamp(&self, min: impl Into<Length>, max: impl Into<Length>) -> Length {
471 self.max(min).min(max)
472 }
473
474 pub fn abs(&self) -> Length {
476 use Length::*;
477 match self {
478 Default => LengthExpr::Abs(Length::Default).to_length_checked(),
479 Dip(e) => Dip(e.abs()),
480 Px(e) => Px(e.abs()),
481 Pt(e) => Pt(e.abs()),
482 Factor(r) => Factor(r.abs()),
483 Leftover(r) => Leftover(r.abs()),
484 Em(e) => Em(e.abs()),
485 RootEm(r) => RootEm(r.abs()),
486 ViewportWidth(w) => ViewportWidth(w.abs()),
487 ViewportHeight(h) => ViewportHeight(h.abs()),
488 ViewportMin(m) => ViewportMin(m.abs()),
489 ViewportMax(m) => ViewportMax(m.abs()),
490 DipF32(e) => DipF32(e.abs()),
491 PxF32(e) => PxF32(e.abs()),
492 Expr(e) => LengthExpr::Abs(Length::Expr(e.clone())).to_length_checked(),
493 }
494 }
495
496 pub fn is_zero(&self) -> Option<bool> {
502 use Length::*;
503 match self {
504 Default => None,
505 Dip(l) => Some(*l == self::Dip::new(0)),
506 Px(l) => Some(*l == self::Px(0)),
507 Pt(l) => Some(l.abs() < EQ_EPSILON),
508 Factor(f) => Some(f.0.abs() < EQ_EPSILON),
509 Leftover(f) => Some(f.0.abs() < EQ_EPSILON),
510 Em(f) => Some(f.0.abs() < EQ_EPSILON),
511 RootEm(f) => Some(f.0.abs() < EQ_EPSILON),
512 ViewportWidth(p) => Some(p.0.abs() < EQ_EPSILON),
513 ViewportHeight(p) => Some(p.0.abs() < EQ_EPSILON),
514 ViewportMin(p) => Some(p.0.abs() < EQ_EPSILON),
515 ViewportMax(p) => Some(p.0.abs() < EQ_EPSILON),
516 DipF32(l) => Some(about_eq(*l, 0.0, EQ_EPSILON_100)),
517 PxF32(l) => Some(about_eq(*l, 0.0, EQ_EPSILON_100)),
518 Expr(_) => None,
519 }
520 }
521
522 pub fn pt_to_px(pt: f32, scale_factor: Factor) -> Px {
524 let px = Self::pt_to_px_f32(pt, scale_factor);
525 Px(px.round() as i32)
526 }
527
528 pub fn pt_to_px_f32(pt: f32, scale_factor: Factor) -> f32 {
532 pt * Self::PT_TO_DIP * scale_factor.0
533 }
534
535 pub fn px_to_pt(px: Px, scale_factor: Factor) -> f32 {
537 let dip = px.0 as f32 / scale_factor.0;
538 dip / Self::PT_TO_DIP
539 }
540
541 pub fn is_default(&self) -> bool {
543 matches!(self, Length::Default)
544 }
545
546 pub fn replace_default(&mut self, overwrite: &Length) {
550 if self.is_default() {
551 *self = overwrite.clone();
552 }
553 }
554
555 pub fn round_exact(&mut self) {
562 match self {
563 Length::PxF32(l) => *self = Length::Px(Px(l.round() as i32)),
564 Length::DipF32(l) => *self = Length::Dip(Dip::new_f32(*l)),
565 _ => {}
566 }
567 }
568
569 pub fn memory_used(&self) -> ByteLength {
573 std::mem::size_of::<Length>().bytes() + self.heap_memory_used()
574 }
575
576 pub fn heap_memory_used(&self) -> ByteLength {
578 if let Length::Expr(e) = self { e.memory_used() } else { 0.bytes() }
579 }
580
581 const PT_TO_DIP: f32 = 96.0 / 72.0; }
584impl super::Layout1d for Length {
585 fn layout_dft(&self, axis: LayoutAxis, default: Px) -> Px {
586 use Length::*;
587 match self {
588 Default => default,
589 Dip(l) => l.to_px(LAYOUT.scale_factor()),
590 Px(l) => *l,
591 Pt(l) => Self::pt_to_px(*l, LAYOUT.scale_factor()),
592 Factor(f) => LAYOUT.constraints_for(axis).fill() * f.0,
593 Leftover(f) => {
594 if let Some(l) = LAYOUT.leftover_for(axis) {
595 l
596 } else {
597 let fill = LAYOUT.constraints_for(axis).fill();
598 (fill * f.0).clamp(self::Px(0), fill)
599 }
600 }
601 Em(f) => LAYOUT.font_size() * f.0,
602 RootEm(f) => LAYOUT.root_font_size() * f.0,
603 ViewportWidth(p) => LAYOUT.viewport().width * *p,
604 ViewportHeight(p) => LAYOUT.viewport().height * *p,
605 ViewportMin(p) => LAYOUT.viewport_min() * *p,
606 ViewportMax(p) => LAYOUT.viewport_max() * *p,
607 DipF32(l) => self::Px((l * LAYOUT.scale_factor().0).round() as i32),
608 PxF32(l) => self::Px(l.round() as i32),
609 Expr(e) => e.layout_dft(axis, default),
610 }
611 }
612
613 fn layout_f32_dft(&self, axis: LayoutAxis, default: f32) -> f32 {
614 use Length::*;
615 match self {
616 Default => default,
617 Dip(l) => l.to_f32() * LAYOUT.scale_factor().0,
618 Px(l) => l.0 as f32,
619 Pt(l) => Self::pt_to_px_f32(*l, LAYOUT.scale_factor()),
620 Factor(f) => LAYOUT.constraints_for(axis).fill().0 as f32 * f.0,
621 Leftover(f) => {
622 if let Some(l) = LAYOUT.leftover_for(axis) {
623 l.0 as f32
624 } else {
625 let fill = LAYOUT.constraints_for(axis).fill().0 as f32;
626 (fill * f.0).clamp(0.0, fill)
627 }
628 }
629 Em(f) => LAYOUT.font_size().0 as f32 * f.0,
630 RootEm(f) => LAYOUT.root_font_size().0 as f32 * f.0,
631 ViewportWidth(p) => LAYOUT.viewport().width.0 as f32 * *p,
632 ViewportHeight(p) => LAYOUT.viewport().height.0 as f32 * *p,
633 ViewportMin(p) => LAYOUT.viewport_min().0 as f32 * *p,
634 ViewportMax(p) => LAYOUT.viewport_max().0 as f32 * *p,
635 DipF32(l) => *l * LAYOUT.scale_factor().0,
636 PxF32(l) => *l,
637 Expr(e) => e.layout_f32_dft(axis, default),
638 }
639 }
640
641 fn affect_mask(&self) -> LayoutMask {
642 use Length::*;
643 match self {
644 Default => LayoutMask::DEFAULT_VALUE,
645 Dip(_) => LayoutMask::SCALE_FACTOR,
646 Px(_) => LayoutMask::empty(),
647 Pt(_) => LayoutMask::SCALE_FACTOR,
648 Factor(_) => LayoutMask::CONSTRAINTS,
649 Leftover(_) => LayoutMask::LEFTOVER,
650 Em(_) => LayoutMask::FONT_SIZE,
651 RootEm(_) => LayoutMask::ROOT_FONT_SIZE,
652 ViewportWidth(_) => LayoutMask::VIEWPORT,
653 ViewportHeight(_) => LayoutMask::VIEWPORT,
654 ViewportMin(_) => LayoutMask::VIEWPORT,
655 ViewportMax(_) => LayoutMask::VIEWPORT,
656 DipF32(_) => LayoutMask::SCALE_FACTOR,
657 PxF32(_) => LayoutMask::empty(),
658 Expr(e) => e.affect_mask(),
659 }
660 }
661}
662
663#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
665pub enum LengthExpr {
666 Add(Length, Length),
668 Sub(Length, Length),
670 Mul(Length, Factor),
672 Div(Length, Factor),
674 Max(Length, Length),
676 Min(Length, Length),
678 Abs(Length),
680 Neg(Length),
682 Lerp(Length, Length, Factor),
684}
685impl LengthExpr {
686 pub fn memory_used(&self) -> ByteLength {
690 use LengthExpr::*;
691 std::mem::size_of::<LengthExpr>().bytes()
692 + match self {
693 Add(a, b) => a.heap_memory_used() + b.heap_memory_used(),
694 Sub(a, b) => a.heap_memory_used() + b.heap_memory_used(),
695 Mul(a, _) => a.heap_memory_used(),
696 Div(a, _) => a.heap_memory_used(),
697 Max(a, b) => a.heap_memory_used() + b.heap_memory_used(),
698 Min(a, b) => a.heap_memory_used() + b.heap_memory_used(),
699 Abs(a) => a.heap_memory_used(),
700 Neg(a) => a.heap_memory_used(),
701 Lerp(a, b, _) => a.heap_memory_used() + b.heap_memory_used(),
702 }
703 }
704
705 pub fn to_length_checked(self) -> Length {
711 let bytes = self.memory_used();
712 if bytes > 20.kibibytes() {
713 tracing::error!(target: "to_length_checked", "length alloc > 20kB, replaced with zero");
714 return Length::zero();
715 }
716 Length::Expr(Box::new(self))
717 }
718}
719impl super::Layout1d for LengthExpr {
720 fn layout_dft(&self, axis: LayoutAxis, default: Px) -> Px {
721 let l = self.layout_f32_dft(axis, default.0 as f32);
722 Px(l.round() as i32)
723 }
724
725 fn layout_f32_dft(&self, axis: LayoutAxis, default: f32) -> f32 {
726 use LengthExpr::*;
727 match self {
728 Add(a, b) => a.layout_f32_dft(axis, default) + b.layout_f32_dft(axis, default),
729 Sub(a, b) => a.layout_f32_dft(axis, default) - b.layout_f32_dft(axis, default),
730 Mul(l, s) => l.layout_f32_dft(axis, default) * s.0,
731 Div(l, s) => l.layout_f32_dft(axis, default) / s.0,
732 Max(a, b) => {
733 let a = a.layout_f32_dft(axis, default);
734 let b = b.layout_f32_dft(axis, default);
735 a.max(b)
736 }
737 Min(a, b) => {
738 let a = a.layout_f32_dft(axis, default);
739 let b = b.layout_f32_dft(axis, default);
740 a.min(b)
741 }
742 Abs(e) => e.layout_f32_dft(axis, default).abs(),
743 Neg(e) => -e.layout_f32_dft(axis, default),
744 Lerp(a, b, f) => a.layout_f32_dft(axis, default).lerp(&b.layout_f32_dft(axis, default), *f),
745 }
746 }
747
748 fn affect_mask(&self) -> LayoutMask {
749 use LengthExpr::*;
750 match self {
751 Add(a, b) => a.affect_mask() | b.affect_mask(),
752 Sub(a, b) => a.affect_mask() | b.affect_mask(),
753 Mul(a, _) => a.affect_mask(),
754 Div(a, _) => a.affect_mask(),
755 Max(a, b) => a.affect_mask() | b.affect_mask(),
756 Min(a, b) => a.affect_mask() | b.affect_mask(),
757 Abs(a) => a.affect_mask(),
758 Neg(a) => a.affect_mask(),
759 Lerp(a, b, _) => a.affect_mask() | b.affect_mask(),
760 }
761 }
762}
763impl fmt::Debug for LengthExpr {
764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765 use LengthExpr::*;
766 if f.alternate() {
767 match self {
768 Add(a, b) => f.debug_tuple("LengthExpr::Add").field(a).field(b).finish(),
769 Sub(a, b) => f.debug_tuple("LengthExpr::Sub").field(a).field(b).finish(),
770 Mul(l, s) => f.debug_tuple("LengthExpr::Mul").field(l).field(s).finish(),
771 Div(l, s) => f.debug_tuple("LengthExpr::Div").field(l).field(s).finish(),
772 Max(a, b) => f.debug_tuple("LengthExpr::Max").field(a).field(b).finish(),
773 Min(a, b) => f.debug_tuple("LengthExpr::Min").field(a).field(b).finish(),
774 Abs(e) => f.debug_tuple("LengthExpr::Abs").field(e).finish(),
775 Neg(e) => f.debug_tuple("LengthExpr::Neg").field(e).finish(),
776 Lerp(a, b, n) => f.debug_tuple("LengthExpr::Lerp").field(a).field(b).field(n).finish(),
777 }
778 } else {
779 match self {
780 Add(a, b) => write!(f, "({a:?} + {b:?})"),
781 Sub(a, b) => write!(f, "({a:?} - {b:?})"),
782 Mul(l, s) => write!(f, "({l:?} * {:?}.pct())", s.0 * 100.0),
783 Div(l, s) => write!(f, "({l:?} / {:?}.pct())", s.0 * 100.0),
784 Max(a, b) => write!(f, "max({a:?}, {b:?})"),
785 Min(a, b) => write!(f, "min({a:?}, {b:?})"),
786 Abs(e) => write!(f, "abs({e:?})"),
787 Neg(e) => write!(f, "-({e:?})"),
788 Lerp(a, b, n) => write!(f, "lerp({a:?}, {b:?}, {n:?})"),
789 }
790 }
791 }
792}
793impl fmt::Display for LengthExpr {
794 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
795 use LengthExpr::*;
796 match self {
797 Add(a, b) => write!(f, "({a} + {b})"),
798 Sub(a, b) => write!(f, "({a} - {b})"),
799 Mul(l, s) => write!(f, "({l} * {}%)", s.0 * 100.0),
800 Div(l, s) => write!(f, "({l} / {}%)", s.0 * 100.0),
801 Max(a, b) => write!(f, "max({a}, {b})"),
802 Min(a, b) => write!(f, "min({a}, {b})"),
803 Abs(e) => write!(f, "abs({e})"),
804 Neg(e) => write!(f, "-({e})"),
805 Lerp(a, b, n) => write!(f, "lerp({a}, {b}, {n})"),
806 }
807 }
808}
809
810pub trait LengthUnits {
832 fn dip(self) -> Length;
836
837 fn px(self) -> Length;
841
842 fn pt(self) -> Length;
846
847 fn fct_l(self) -> Length;
854
855 fn pct_l(self) -> Length;
862
863 fn em(self) -> Length;
867
868 fn em_pct(self) -> Length;
872
873 fn rem(self) -> Length;
877
878 fn rem_pct(self) -> Length;
882
883 fn vw(self) -> Length;
887
888 fn vw_pct(self) -> Length;
892
893 fn vh(self) -> Length;
897
898 fn vh_pct(self) -> Length;
902
903 fn vmin(self) -> Length;
907
908 fn vmin_pct(self) -> Length;
912
913 fn vmax(self) -> Length;
917
918 fn vmax_pct(self) -> Length;
922
923 fn lft(self) -> Length;
930}
931impl LengthUnits for f32 {
932 fn dip(self) -> Length {
933 Length::DipF32(self)
934 }
935
936 fn px(self) -> Length {
937 Length::PxF32(self)
938 }
939
940 fn pt(self) -> Length {
941 Length::Pt(self)
942 }
943
944 fn fct_l(self) -> Length {
945 Length::Factor(self.fct())
946 }
947
948 fn pct_l(self) -> Length {
949 Length::Factor(self.pct().fct())
950 }
951
952 fn em(self) -> Length {
953 Length::Em(self.into())
954 }
955
956 fn rem(self) -> Length {
957 Length::RootEm(self.into())
958 }
959
960 fn vw(self) -> Length {
961 Length::ViewportWidth(self.into())
962 }
963
964 fn vh(self) -> Length {
965 Length::ViewportHeight(self.into())
966 }
967
968 fn vmin(self) -> Length {
969 Length::ViewportMin(self.into())
970 }
971
972 fn vmax(self) -> Length {
973 Length::ViewportMax(self.into())
974 }
975
976 fn em_pct(self) -> Length {
977 Length::Em(self.pct().into())
978 }
979
980 fn rem_pct(self) -> Length {
981 Length::RootEm(self.pct().into())
982 }
983
984 fn vw_pct(self) -> Length {
985 Length::ViewportWidth(self.pct().into())
986 }
987
988 fn vh_pct(self) -> Length {
989 Length::ViewportHeight(self.pct().into())
990 }
991
992 fn vmin_pct(self) -> Length {
993 Length::ViewportMin(self.pct().into())
994 }
995
996 fn vmax_pct(self) -> Length {
997 Length::ViewportMax(self.pct().into())
998 }
999
1000 fn lft(self) -> Length {
1001 Length::Leftover(self.fct())
1002 }
1003}
1004impl LengthUnits for i32 {
1005 fn dip(self) -> Length {
1006 Length::Dip(Dip::new(self))
1007 }
1008
1009 fn px(self) -> Length {
1010 Length::Px(Px(self))
1011 }
1012
1013 fn pt(self) -> Length {
1014 Length::Pt(self as f32)
1015 }
1016
1017 fn fct_l(self) -> Length {
1018 Length::Factor(self.fct())
1019 }
1020
1021 fn pct_l(self) -> Length {
1022 Length::Factor(self.pct().fct())
1023 }
1024
1025 fn em(self) -> Length {
1026 Length::Em(self.fct())
1027 }
1028
1029 fn rem(self) -> Length {
1030 Length::RootEm(self.fct())
1031 }
1032
1033 fn vw(self) -> Length {
1034 Length::ViewportWidth(self.fct())
1035 }
1036
1037 fn vh(self) -> Length {
1038 Length::ViewportHeight(self.fct())
1039 }
1040
1041 fn vmin(self) -> Length {
1042 Length::ViewportMin(self.fct())
1043 }
1044
1045 fn vmax(self) -> Length {
1046 Length::ViewportMax(self.fct())
1047 }
1048
1049 fn em_pct(self) -> Length {
1050 Length::Em(self.pct().into())
1051 }
1052
1053 fn rem_pct(self) -> Length {
1054 Length::RootEm(self.pct().into())
1055 }
1056
1057 fn vw_pct(self) -> Length {
1058 Length::ViewportWidth(self.pct().into())
1059 }
1060
1061 fn vh_pct(self) -> Length {
1062 Length::ViewportHeight(self.pct().into())
1063 }
1064
1065 fn vmin_pct(self) -> Length {
1066 Length::ViewportMin(self.pct().into())
1067 }
1068
1069 fn vmax_pct(self) -> Length {
1070 Length::ViewportMax(self.pct().into())
1071 }
1072
1073 fn lft(self) -> Length {
1074 Length::Leftover(self.fct())
1075 }
1076}