| 1 | #[cfg (all(feature = "libm" , not(feature = "std" )))] |
| 2 | use 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)] |
| 12 | pub struct Point { |
| 13 | pub x: f32, |
| 14 | pub y: f32, |
| 15 | } |
| 16 | |
| 17 | impl 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 | |
| 23 | impl Point { |
| 24 | #[inline ] |
| 25 | pub(crate) fn distance_to(self, other: Point) -> f32 { |
| 26 | let d: Point = 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 ] |
| 39 | pub fn point(x: f32, y: f32) -> Point { |
| 40 | Point { x, y } |
| 41 | } |
| 42 | |
| 43 | /// Linear interpolation between points. |
| 44 | #[inline ] |
| 45 | pub(crate) fn lerp(t: f32, p0: Point, p1: Point) -> Point { |
| 46 | point(x:p0.x + t * (p1.x - p0.x), y:p0.y + t * (p1.y - p0.y)) |
| 47 | } |
| 48 | |
| 49 | impl 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 | |
| 66 | impl 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 | |
| 83 | impl 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 | |
| 99 | impl 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 | |
| 115 | impl<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: F, y: F): (F, F)) -> Self { |
| 123 | point(x.into(), y.into()) |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | impl<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: F, y: F]: [F; 2]) -> Self { |
| 135 | point(x.into(), y.into()) |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | #[cfg (test)] |
| 140 | mod 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 | } |
| 149 | |