typst_library/layout/
point.rs1use std::fmt::{self, Debug, Formatter};
2use std::ops::{Add, Div, Mul, Neg};
3
4use typst_utils::{Get, Numeric};
5
6use crate::layout::{Abs, Axis, Size, Transform};
7
8#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
10pub struct Point {
11 pub x: Abs,
13 pub y: Abs,
15}
16
17impl Point {
18 pub const fn zero() -> Self {
20 Self { x: Abs::zero(), y: Abs::zero() }
21 }
22
23 pub const fn new(x: Abs, y: Abs) -> Self {
25 Self { x, y }
26 }
27
28 pub const fn splat(value: Abs) -> Self {
30 Self { x: value, y: value }
31 }
32
33 pub const fn with_x(x: Abs) -> Self {
35 Self { x, y: Abs::zero() }
36 }
37
38 pub const fn with_y(y: Abs) -> Self {
40 Self { x: Abs::zero(), y }
41 }
42
43 pub fn min(self, other: Self) -> Self {
45 Self { x: self.x.min(other.x), y: self.y.min(other.y) }
46 }
47
48 pub fn max(self, other: Self) -> Self {
50 Self { x: self.x.max(other.x), y: self.y.max(other.y) }
51 }
52
53 pub fn map(self, f: impl Fn(Abs) -> Abs) -> Self {
55 Self { x: f(self.x), y: f(self.y) }
56 }
57
58 pub fn hypot(self) -> Abs {
60 Abs::raw(self.x.to_raw().hypot(self.y.to_raw()))
61 }
62
63 pub fn transform(self, ts: Transform) -> Self {
68 Self::new(
69 ts.sx.of(self.x) + ts.kx.of(self.y) + ts.tx,
70 ts.ky.of(self.x) + ts.sy.of(self.y) + ts.ty,
71 )
72 }
73
74 pub fn transform_inf(self, ts: Transform) -> Self {
77 Self::new(
78 ts.sx.get() * self.x + ts.kx.get() * self.y + ts.tx,
79 ts.ky.get() * self.x + ts.sy.get() * self.y + ts.ty,
80 )
81 }
82
83 pub fn to_size(self) -> Size {
85 Size::new(self.x, self.y)
86 }
87}
88
89impl Numeric for Point {
90 fn zero() -> Self {
91 Self::zero()
92 }
93
94 fn is_finite(self) -> bool {
95 self.x.is_finite() && self.y.is_finite()
96 }
97}
98
99impl Get<Axis> for Point {
100 type Component = Abs;
101
102 fn get_ref(&self, axis: Axis) -> &Abs {
103 match axis {
104 Axis::X => &self.x,
105 Axis::Y => &self.y,
106 }
107 }
108
109 fn get_mut(&mut self, axis: Axis) -> &mut Abs {
110 match axis {
111 Axis::X => &mut self.x,
112 Axis::Y => &mut self.y,
113 }
114 }
115}
116
117impl Debug for Point {
118 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
119 write!(f, "Point({:?}, {:?})", self.x, self.y)
120 }
121}
122
123impl Neg for Point {
124 type Output = Self;
125
126 fn neg(self) -> Self {
127 Self { x: -self.x, y: -self.y }
128 }
129}
130
131impl Add for Point {
132 type Output = Self;
133
134 fn add(self, other: Self) -> Self {
135 Self { x: self.x + other.x, y: self.y + other.y }
136 }
137}
138
139typst_utils::sub_impl!(Point - Point -> Point);
140
141impl Mul<f64> for Point {
142 type Output = Self;
143
144 fn mul(self, other: f64) -> Self {
145 Self { x: self.x * other, y: self.y * other }
146 }
147}
148
149impl Mul<Point> for f64 {
150 type Output = Point;
151
152 fn mul(self, other: Point) -> Point {
153 other * self
154 }
155}
156
157impl Div<f64> for Point {
158 type Output = Self;
159
160 fn div(self, other: f64) -> Self {
161 Self { x: self.x / other, y: self.y / other }
162 }
163}
164
165typst_utils::assign_impl!(Point += Point);
166typst_utils::assign_impl!(Point -= Point);
167typst_utils::assign_impl!(Point *= f64);
168typst_utils::assign_impl!(Point /= f64);