typst_library/layout/
point.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use std::fmt::{self, Debug, Formatter};
use std::ops::{Add, Div, Mul, Neg};

use typst_utils::{Get, Numeric};

use crate::layout::{Abs, Axis, Size, Transform};

/// A point in 2D.
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
pub struct Point {
    /// The x coordinate.
    pub x: Abs,
    /// The y coordinate.
    pub y: Abs,
}

impl Point {
    /// The origin point.
    pub const fn zero() -> Self {
        Self { x: Abs::zero(), y: Abs::zero() }
    }

    /// Create a new point from x and y coordinates.
    pub const fn new(x: Abs, y: Abs) -> Self {
        Self { x, y }
    }

    /// Create an instance with two equal components.
    pub const fn splat(value: Abs) -> Self {
        Self { x: value, y: value }
    }

    /// Create a new point with y set to zero.
    pub const fn with_x(x: Abs) -> Self {
        Self { x, y: Abs::zero() }
    }

    /// Create a new point with x set to zero.
    pub const fn with_y(y: Abs) -> Self {
        Self { x: Abs::zero(), y }
    }

    /// The component-wise minimum of this and another point.
    pub fn min(self, other: Self) -> Self {
        Self { x: self.x.min(other.x), y: self.y.min(other.y) }
    }

    /// The component-wise minimum of this and another point.
    pub fn max(self, other: Self) -> Self {
        Self { x: self.x.max(other.x), y: self.y.max(other.y) }
    }

    /// Maps the point with the given function.
    pub fn map(self, f: impl Fn(Abs) -> Abs) -> Self {
        Self { x: f(self.x), y: f(self.y) }
    }

    /// The distance between this point and the origin.
    pub fn hypot(self) -> Abs {
        Abs::raw(self.x.to_raw().hypot(self.y.to_raw()))
    }

    /// Transform the point with the given transformation.
    ///
    /// In the event that one of the coordinates is infinite, the result will
    /// be zero.
    pub fn transform(self, ts: Transform) -> Self {
        Self::new(
            ts.sx.of(self.x) + ts.kx.of(self.y) + ts.tx,
            ts.ky.of(self.x) + ts.sy.of(self.y) + ts.ty,
        )
    }

    /// Transforms the point with the given transformation, without accounting
    /// for infinite values.
    pub fn transform_inf(self, ts: Transform) -> Self {
        Self::new(
            ts.sx.get() * self.x + ts.kx.get() * self.y + ts.tx,
            ts.ky.get() * self.x + ts.sy.get() * self.y + ts.ty,
        )
    }

    /// Convert to a size.
    pub fn to_size(self) -> Size {
        Size::new(self.x, self.y)
    }
}

impl Numeric for Point {
    fn zero() -> Self {
        Self::zero()
    }

    fn is_finite(self) -> bool {
        self.x.is_finite() && self.y.is_finite()
    }
}

impl Get<Axis> for Point {
    type Component = Abs;

    fn get_ref(&self, axis: Axis) -> &Abs {
        match axis {
            Axis::X => &self.x,
            Axis::Y => &self.y,
        }
    }

    fn get_mut(&mut self, axis: Axis) -> &mut Abs {
        match axis {
            Axis::X => &mut self.x,
            Axis::Y => &mut self.y,
        }
    }
}

impl Debug for Point {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Point({:?}, {:?})", self.x, self.y)
    }
}

impl Neg for Point {
    type Output = Self;

    fn neg(self) -> Self {
        Self { x: -self.x, y: -self.y }
    }
}

impl Add for Point {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        Self { x: self.x + other.x, y: self.y + other.y }
    }
}

typst_utils::sub_impl!(Point - Point -> Point);

impl Mul<f64> for Point {
    type Output = Self;

    fn mul(self, other: f64) -> Self {
        Self { x: self.x * other, y: self.y * other }
    }
}

impl Mul<Point> for f64 {
    type Output = Point;

    fn mul(self, other: Point) -> Point {
        other * self
    }
}

impl Div<f64> for Point {
    type Output = Self;

    fn div(self, other: f64) -> Self {
        Self { x: self.x / other, y: self.y / other }
    }
}

typst_utils::assign_impl!(Point += Point);
typst_utils::assign_impl!(Point -= Point);
typst_utils::assign_impl!(Point *= f64);
typst_utils::assign_impl!(Point /= f64);