typst_library/layout/
fr.rs1use std::fmt::{self, Debug, Formatter};
2use std::iter::Sum;
3use std::ops::{Add, Div, Mul, Neg};
4
5use ecow::EcoString;
6use typst_utils::{Numeric, Scalar};
7
8use crate::foundations::{Repr, repr, ty};
9use crate::layout::Abs;
10
11#[ty(cast, name = "fraction")]
24#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
25pub struct Fr(Scalar);
26
27impl Fr {
28 pub const fn zero() -> Self {
30 Self(Scalar::ZERO)
31 }
32
33 pub const fn one() -> Self {
35 Self(Scalar::ONE)
36 }
37
38 pub const fn new(ratio: f64) -> Self {
40 Self(Scalar::new(ratio))
41 }
42
43 pub const fn get(self) -> f64 {
45 (self.0).get()
46 }
47
48 pub fn abs(self) -> Self {
50 Self::new(self.get().abs())
51 }
52
53 pub fn share(self, total: Self, remaining: Abs) -> Abs {
55 let ratio = self / total;
56 if ratio.is_finite() && remaining.is_finite() {
57 (ratio * remaining).max(Abs::zero())
58 } else {
59 Abs::zero()
60 }
61 }
62}
63
64impl Numeric for Fr {
65 fn zero() -> Self {
66 Self::zero()
67 }
68
69 fn is_finite(self) -> bool {
70 self.0.is_finite()
71 }
72}
73
74impl Debug for Fr {
75 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
76 write!(f, "{:?}fr", self.get())
77 }
78}
79
80impl Repr for Fr {
81 fn repr(&self) -> EcoString {
82 repr::format_float_with_unit(self.get(), "fr")
83 }
84}
85
86impl Neg for Fr {
87 type Output = Self;
88
89 fn neg(self) -> Self {
90 Self(-self.0)
91 }
92}
93
94impl Add for Fr {
95 type Output = Self;
96
97 fn add(self, other: Self) -> Self {
98 Self(self.0 + other.0)
99 }
100}
101
102typst_utils::sub_impl!(Fr - Fr -> Fr);
103
104impl Mul<f64> for Fr {
105 type Output = Self;
106
107 fn mul(self, other: f64) -> Self {
108 Self(self.0 * other)
109 }
110}
111
112impl Mul<Fr> for f64 {
113 type Output = Fr;
114
115 fn mul(self, other: Fr) -> Fr {
116 other * self
117 }
118}
119
120impl Div for Fr {
121 type Output = f64;
122
123 fn div(self, other: Self) -> f64 {
124 self.get() / other.get()
125 }
126}
127
128impl Div<f64> for Fr {
129 type Output = Self;
130
131 fn div(self, other: f64) -> Self {
132 Self(self.0 / other)
133 }
134}
135
136typst_utils::assign_impl!(Fr += Fr);
137typst_utils::assign_impl!(Fr -= Fr);
138typst_utils::assign_impl!(Fr *= f64);
139typst_utils::assign_impl!(Fr /= f64);
140
141impl Sum for Fr {
142 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
143 Self(iter.map(|s| s.0).sum())
144 }
145}