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