1use crate::Twips;
2use std::fmt;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5pub trait Coordinate:
6 Copy
7 + Add<Output = Self>
8 + AddAssign
9 + Sub<Output = Self>
10 + SubAssign
11 + Mul<i32, Output = Self>
12 + MulAssign<i32>
13 + Div<i32, Output = Self>
14 + DivAssign<i32>
15 + Neg<Output = Self>
16 + fmt::Display
17{
18 const ZERO: Self;
19}
20
21impl Coordinate for i32 {
22 const ZERO: Self = 0;
23}
24
25impl Coordinate for Twips {
26 const ZERO: Self = Self::ZERO;
27}
28
29#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
31pub struct Point<T: Coordinate> {
32 pub x: T,
33 pub y: T,
34}
35
36impl<T: Coordinate> Point<T> {
37 pub const ZERO: Self = Self {
46 x: T::ZERO,
47 y: T::ZERO,
48 };
49
50 pub const fn new(x: T, y: T) -> Self {
51 Self { x, y }
52 }
53}
54
55impl Point<Twips> {
56 #[inline]
74 pub fn from_pixels(x: f64, y: f64) -> Self {
75 Self {
76 x: Twips::from_pixels(x),
77 y: Twips::from_pixels(y),
78 }
79 }
80}
81
82impl<T: Coordinate> Add<PointDelta<T>> for Point<T> {
84 type Output = Self;
85
86 #[inline]
87 fn add(self, other: PointDelta<T>) -> Self {
88 Self {
89 x: self.x + other.dx,
90 y: self.y + other.dy,
91 }
92 }
93}
94
95impl<T: Coordinate> AddAssign<PointDelta<T>> for Point<T> {
97 #[inline]
98 fn add_assign(&mut self, other: PointDelta<T>) {
99 self.x += other.dx;
100 self.y += other.dy;
101 }
102}
103
104impl<T: Coordinate> Sub<PointDelta<T>> for Point<T> {
106 type Output = Self;
107
108 #[inline]
109 fn sub(self, other: PointDelta<T>) -> Self {
110 Self {
111 x: self.x - other.dx,
112 y: self.y - other.dy,
113 }
114 }
115}
116
117impl<T: Coordinate> SubAssign<PointDelta<T>> for Point<T> {
119 #[inline]
120 fn sub_assign(&mut self, other: PointDelta<T>) {
121 self.x -= other.dx;
122 self.y -= other.dy;
123 }
124}
125
126impl<T: Coordinate> Sub for Point<T> {
128 type Output = PointDelta<T>;
129
130 #[inline]
131 fn sub(self, other: Self) -> PointDelta<T> {
132 PointDelta {
133 dx: self.x - other.x,
134 dy: self.y - other.y,
135 }
136 }
137}
138
139impl<T: Coordinate> fmt::Display for Point<T> {
140 #[inline]
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 write!(f, "({}, {})", self.x, self.y)
143 }
144}
145
146#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
148pub struct PointDelta<T: Coordinate> {
149 pub dx: T,
150 pub dy: T,
151}
152
153impl<T: Coordinate> PointDelta<T> {
154 pub const ZERO: Self = Self {
163 dx: T::ZERO,
164 dy: T::ZERO,
165 };
166
167 pub const fn new(dx: T, dy: T) -> Self {
168 Self { dx, dy }
169 }
170}
171
172impl PointDelta<Twips> {
173 #[inline]
191 pub fn from_pixels(dx: f64, dy: f64) -> Self {
192 Self {
193 dx: Twips::from_pixels(dx),
194 dy: Twips::from_pixels(dy),
195 }
196 }
197}
198
199impl<T: Coordinate> Mul<i32> for PointDelta<T> {
201 type Output = Self;
202
203 #[inline]
204 fn mul(self, other: i32) -> Self {
205 Self {
206 dx: self.dx * other,
207 dy: self.dy * other,
208 }
209 }
210}
211
212impl<T: Coordinate> MulAssign<i32> for PointDelta<T> {
214 #[inline]
215 fn mul_assign(&mut self, other: i32) {
216 self.dx *= other;
217 self.dy *= other;
218 }
219}
220
221impl<T: Coordinate> Div<i32> for PointDelta<T> {
223 type Output = Self;
224
225 #[inline]
226 fn div(self, other: i32) -> Self {
227 Self {
228 dx: self.dx / other,
229 dy: self.dy / other,
230 }
231 }
232}
233
234impl<T: Coordinate> DivAssign<i32> for PointDelta<T> {
236 #[inline]
237 fn div_assign(&mut self, other: i32) {
238 self.dx /= other;
239 self.dy /= other;
240 }
241}
242
243impl<T: Coordinate> Neg for PointDelta<T> {
245 type Output = Self;
246
247 #[inline]
248 fn neg(self) -> Self {
249 Self {
250 dx: -self.dx,
251 dy: -self.dy,
252 }
253 }
254}