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, ty, Repr};
8
9#[ty(cast)]
21#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
22pub struct Ratio(Scalar);
23
24impl Ratio {
25 pub const fn zero() -> Self {
27 Self(Scalar::ZERO)
28 }
29
30 pub const fn one() -> Self {
32 Self(Scalar::ONE)
33 }
34
35 pub const fn new(ratio: f64) -> Self {
37 Self(Scalar::new(ratio))
38 }
39
40 pub const fn get(self) -> f64 {
42 (self.0).get()
43 }
44
45 pub fn is_zero(self) -> bool {
47 self.0 == 0.0
48 }
49
50 pub fn is_one(self) -> bool {
52 self.0 == 1.0
53 }
54
55 pub fn abs(self) -> Self {
57 Self::new(self.get().abs())
58 }
59
60 pub fn of<T: Numeric>(self, whole: T) -> T {
62 let resolved = whole * self.get();
63 if resolved.is_finite() {
64 resolved
65 } else {
66 T::zero()
67 }
68 }
69}
70
71impl Debug for Ratio {
72 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
73 write!(f, "{:?}%", self.get() * 100.0)
74 }
75}
76
77impl Repr for Ratio {
78 fn repr(&self) -> EcoString {
79 repr::format_float_with_unit(self.get() * 100.0, "%")
80 }
81}
82
83impl Neg for Ratio {
84 type Output = Self;
85
86 fn neg(self) -> Self {
87 Self(-self.0)
88 }
89}
90
91impl Add for Ratio {
92 type Output = Self;
93
94 fn add(self, other: Self) -> Self {
95 Self(self.0 + other.0)
96 }
97}
98
99typst_utils::sub_impl!(Ratio - Ratio -> Ratio);
100
101impl Mul for Ratio {
102 type Output = Self;
103
104 fn mul(self, other: Self) -> Self {
105 Self(self.0 * other.0)
106 }
107}
108
109impl Mul<f64> for Ratio {
110 type Output = Self;
111
112 fn mul(self, other: f64) -> Self {
113 Self(self.0 * other)
114 }
115}
116
117impl Mul<Ratio> for f64 {
118 type Output = Ratio;
119
120 fn mul(self, other: Ratio) -> Ratio {
121 other * self
122 }
123}
124
125impl Div for Ratio {
126 type Output = f64;
127
128 fn div(self, other: Self) -> f64 {
129 self.get() / other.get()
130 }
131}
132
133impl Div<f64> for Ratio {
134 type Output = Self;
135
136 fn div(self, other: f64) -> Self {
137 Self(self.0 / other)
138 }
139}
140
141impl Div<Ratio> for f64 {
142 type Output = Self;
143
144 fn div(self, other: Ratio) -> Self {
145 self / other.get()
146 }
147}
148
149typst_utils::assign_impl!(Ratio += Ratio);
150typst_utils::assign_impl!(Ratio -= Ratio);
151typst_utils::assign_impl!(Ratio *= Ratio);
152typst_utils::assign_impl!(Ratio *= f64);
153typst_utils::assign_impl!(Ratio /= f64);