ab_glyph_rasterizer/
geometry.rs

1#[cfg(all(feature = "libm", not(feature = "std")))]
2use crate::nostd_float::FloatExt;
3
4/// An (x, y) coordinate.
5///
6/// # Example
7/// ```
8/// use ab_glyph_rasterizer::{point, Point};
9/// let p: Point = point(0.1, 23.2);
10/// ```
11#[derive(Clone, Copy, Default, PartialEq, PartialOrd)]
12pub struct Point {
13    pub x: f32,
14    pub y: f32,
15}
16
17impl core::fmt::Debug for Point {
18    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19        write!(f, "point({:?}, {:?})", self.x, self.y)
20    }
21}
22
23impl Point {
24    #[inline]
25    pub(crate) fn distance_to(self, other: Point) -> f32 {
26        let d = other - self;
27        (d.x * d.x + d.y * d.y).sqrt()
28    }
29}
30
31/// [`Point`](struct.Point.html) constructor.
32///
33/// # Example
34/// ```
35/// # use ab_glyph_rasterizer::{point, Point};
36/// let p = point(0.1, 23.2);
37/// ```
38#[inline]
39pub fn point(x: f32, y: f32) -> Point {
40    Point { x, y }
41}
42
43/// Linear interpolation between points.
44#[inline]
45pub(crate) fn lerp(t: f32, p0: Point, p1: Point) -> Point {
46    point(p0.x + t * (p1.x - p0.x), p0.y + t * (p1.y - p0.y))
47}
48
49impl core::ops::Sub for Point {
50    type Output = Point;
51    /// Subtract rhs.x from x, rhs.y from y.
52    ///
53    /// ```
54    /// # use ab_glyph_rasterizer::*;
55    /// let p1 = point(1.0, 2.0) - point(2.0, 1.5);
56    ///
57    /// assert!((p1.x - -1.0).abs() <= core::f32::EPSILON);
58    /// assert!((p1.y - 0.5).abs() <= core::f32::EPSILON);
59    /// ```
60    #[inline]
61    fn sub(self, rhs: Point) -> Point {
62        point(self.x - rhs.x, self.y - rhs.y)
63    }
64}
65
66impl core::ops::Add for Point {
67    type Output = Point;
68    /// Add rhs.x to x, rhs.y to y.
69    ///
70    /// ```
71    /// # use ab_glyph_rasterizer::*;
72    /// let p1 = point(1.0, 2.0) + point(2.0, 1.5);
73    ///
74    /// assert!((p1.x - 3.0).abs() <= core::f32::EPSILON);
75    /// assert!((p1.y - 3.5).abs() <= core::f32::EPSILON);
76    /// ```
77    #[inline]
78    fn add(self, rhs: Point) -> Point {
79        point(self.x + rhs.x, self.y + rhs.y)
80    }
81}
82
83impl core::ops::AddAssign for Point {
84    /// ```
85    /// # use ab_glyph_rasterizer::*;
86    /// let mut p1 = point(1.0, 2.0);
87    /// p1 += point(2.0, 1.5);
88    ///
89    /// assert!((p1.x - 3.0).abs() <= core::f32::EPSILON);
90    /// assert!((p1.y - 3.5).abs() <= core::f32::EPSILON);
91    /// ```
92    #[inline]
93    fn add_assign(&mut self, other: Self) {
94        self.x += other.x;
95        self.y += other.y;
96    }
97}
98
99impl core::ops::SubAssign for Point {
100    /// ```
101    /// # use ab_glyph_rasterizer::*;
102    /// let mut p1 = point(1.0, 2.0);
103    /// p1 -= point(2.0, 1.5);
104    ///
105    /// assert!((p1.x - -1.0).abs() <= core::f32::EPSILON);
106    /// assert!((p1.y - 0.5).abs() <= core::f32::EPSILON);
107    /// ```
108    #[inline]
109    fn sub_assign(&mut self, other: Self) {
110        self.x -= other.x;
111        self.y -= other.y;
112    }
113}
114
115impl<F: Into<f32>> From<(F, F)> for Point {
116    /// ```
117    /// # use ab_glyph_rasterizer::*;
118    /// let p: Point = (23_f32, 34.5_f32).into();
119    /// let p2: Point = (5u8, 44u8).into();
120    /// ```
121    #[inline]
122    fn from((x, y): (F, F)) -> Self {
123        point(x.into(), y.into())
124    }
125}
126
127impl<F: Into<f32>> From<[F; 2]> for Point {
128    /// ```
129    /// # use ab_glyph_rasterizer::*;
130    /// let p: Point = [23_f32, 34.5].into();
131    /// let p2: Point = [5u8, 44].into();
132    /// ```
133    #[inline]
134    fn from([x, y]: [F; 2]) -> Self {
135        point(x.into(), y.into())
136    }
137}
138
139#[cfg(test)]
140mod test {
141    use super::*;
142
143    #[test]
144    fn distance_to() {
145        let distance = point(0.0, 0.0).distance_to(point(3.0, 4.0));
146        assert!((distance - 5.0).abs() <= core::f32::EPSILON);
147    }
148}