typst_library/layout/
ratio.rs1use std::fmt::{self, Debug, Formatter};
2use std::ops::{Add, Div, Mul, Neg};
3
4use ecow::EcoString;
5use typst_utils::{Numeric, Scalar};
6
7use crate::foundations::{Repr, repr, ty};
8
9#[ty(cast)]
63#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
64pub struct Ratio(Scalar);
65
66impl Ratio {
67 pub const fn zero() -> Self {
69 Self(Scalar::ZERO)
70 }
71
72 pub const fn one() -> Self {
74 Self(Scalar::ONE)
75 }
76
77 pub const fn new(ratio: f64) -> Self {
79 Self(Scalar::new(ratio))
80 }
81
82 pub const fn get(self) -> f64 {
84 (self.0).get()
85 }
86
87 pub const fn scalar(self) -> Scalar {
89 self.0
90 }
91
92 pub fn is_zero(self) -> bool {
94 self.0 == 0.0
95 }
96
97 pub fn is_one(self) -> bool {
99 self.0 == 1.0
100 }
101
102 pub fn abs(self) -> Self {
104 Self::new(self.get().abs())
105 }
106
107 pub fn of<T: Numeric>(self, whole: T) -> T {
109 let resolved = whole * self.get();
110 if resolved.is_finite() { resolved } else { T::zero() }
111 }
112
113 pub fn recip(self) -> Self {
115 Self::new(self.get().recip())
116 }
117}
118
119impl Numeric for Ratio {
120 fn zero() -> Self {
121 Ratio::zero()
122 }
123
124 fn is_finite(self) -> bool {
125 self.0.is_finite()
126 }
127}
128
129impl Debug for Ratio {
130 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
131 write!(f, "{:?}%", self.get() * 100.0)
132 }
133}
134
135impl Repr for Ratio {
136 fn repr(&self) -> EcoString {
137 repr::format_float_with_unit(self.get() * 100.0, "%")
138 }
139}
140
141impl Neg for Ratio {
142 type Output = Self;
143
144 fn neg(self) -> Self {
145 Self(-self.0)
146 }
147}
148
149impl Add for Ratio {
150 type Output = Self;
151
152 fn add(self, other: Self) -> Self {
153 Self(self.0 + other.0)
154 }
155}
156
157typst_utils::sub_impl!(Ratio - Ratio -> Ratio);
158
159impl Mul for Ratio {
160 type Output = Self;
161
162 fn mul(self, other: Self) -> Self {
163 Self(self.0 * other.0)
164 }
165}
166
167impl Mul<f64> for Ratio {
168 type Output = Self;
169
170 fn mul(self, other: f64) -> Self {
171 Self(self.0 * other)
172 }
173}
174
175impl Mul<Ratio> for f64 {
176 type Output = Ratio;
177
178 fn mul(self, other: Ratio) -> Ratio {
179 other * self
180 }
181}
182
183impl Div for Ratio {
184 type Output = f64;
185
186 fn div(self, other: Self) -> f64 {
187 self.get() / other.get()
188 }
189}
190
191impl Div<f64> for Ratio {
192 type Output = Self;
193
194 fn div(self, other: f64) -> Self {
195 Self(self.0 / other)
196 }
197}
198
199impl Div<Ratio> for f64 {
200 type Output = Self;
201
202 fn div(self, other: Ratio) -> Self {
203 self / other.get()
204 }
205}
206
207typst_utils::assign_impl!(Ratio += Ratio);
208typst_utils::assign_impl!(Ratio -= Ratio);
209typst_utils::assign_impl!(Ratio *= Ratio);
210typst_utils::assign_impl!(Ratio *= f64);
211typst_utils::assign_impl!(Ratio /= f64);