1use embedded_graphics::geometry::AnchorPoint;
34use embedded_graphics::geometry::Point;
35use embedded_graphics::geometry::Size;
36use saturating_cast::SaturatingCast;
37
38#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
61pub struct LwPoint<T> {
62 pub x: T,
64 pub y: T,
66}
67
68impl<T> LwPoint<T> {
69 pub const fn new(x: T, y: T) -> Self {
80 Self { x, y }
81 }
82}
83impl LwPoint<i8> {
85 pub const fn offset(&self, dx: i8, dy: i8) -> Self {
86 Self {
87 x: self.x + dx,
88 y: self.y + dy,
89 }
90 }
91}
92
93impl LwPoint<i16> {
95 pub const fn offset(&self, dx: i16, dy: i16) -> Self {
96 Self {
97 x: self.x + dx,
98 y: self.y + dy,
99 }
100 }
101}
102
103impl From<Point> for LwPoint<i8> {
105 fn from(point: Point) -> Self {
106 Self {
107 x: point.x.saturating_cast(),
108 y: point.y.saturating_cast(),
109 }
110 }
111}
112
113impl From<Point> for LwPoint<i16> {
115 fn from(point: Point) -> Self {
116 Self {
117 x: point.x.saturating_cast(),
118 y: point.y.saturating_cast(),
119 }
120 }
121}
122
123impl From<LwPoint<i8>> for Point {
125 fn from(lw_point: LwPoint<i8>) -> Self {
126 Point::new(lw_point.x as i32, lw_point.y as i32)
127 }
128}
129
130impl From<LwPoint<i16>> for Point {
132 fn from(lw_point: LwPoint<i16>) -> Self {
133 Point::new(lw_point.x as i32, lw_point.y as i32)
134 }
135}
136
137#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
160pub struct LwSize<T> {
161 pub width: T,
163 pub height: T,
165}
166
167impl<T> LwSize<T> {
168 pub const fn new(width: T, height: T) -> Self {
179 Self { width, height }
180 }
181}
182
183impl From<Size> for LwSize<u8> {
185 fn from(size: Size) -> Self {
186 Self {
187 width: size.width.saturating_cast(),
188 height: size.height.saturating_cast(),
189 }
190 }
191}
192
193impl From<Size> for LwSize<u16> {
195 fn from(size: Size) -> Self {
196 Self {
197 width: size.width.saturating_cast(),
198 height: size.height.saturating_cast(),
199 }
200 }
201}
202
203impl From<LwSize<u8>> for Size {
205 fn from(lw_size: LwSize<u8>) -> Self {
206 Size::new(lw_size.width as u32, lw_size.height as u32)
207 }
208}
209
210impl From<LwSize<u16>> for Size {
212 fn from(lw_size: LwSize<u16>) -> Self {
213 Size::new(lw_size.width as u32, lw_size.height as u32)
214 }
215}
216
217#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
235pub enum DeltaResize {
236 TopLeft(i16, i16),
238 TopCenter(i16, i16),
240 TopRight(i16, i16),
242 CenterLeft(i16, i16),
244 Center(i16, i16),
246 CenterRight(i16, i16),
248 BottomLeft(i16, i16),
250 BottomCenter(i16, i16),
252 BottomRight(i16, i16),
254}
255
256impl DeltaResize {
257 pub const fn unwrap(&self) -> (i32, i32, AnchorPoint) {
258 let (delta_w, delta_h, ap) = match *self {
259 DeltaResize::TopLeft(w, h) => (w, h, AnchorPoint::TopLeft),
260 DeltaResize::TopCenter(w, h) => (w, h, AnchorPoint::TopCenter),
261 DeltaResize::TopRight(w, h) => (w, h, AnchorPoint::TopRight),
262 DeltaResize::CenterLeft(w, h) => (w, h, AnchorPoint::CenterLeft),
263 DeltaResize::Center(w, h) => (w, h, AnchorPoint::Center),
264 DeltaResize::CenterRight(w, h) => (w, h, AnchorPoint::CenterRight),
265 DeltaResize::BottomLeft(w, h) => (w, h, AnchorPoint::BottomLeft),
266 DeltaResize::BottomCenter(w, h) => (w, h, AnchorPoint::BottomCenter),
267 DeltaResize::BottomRight(w, h) => (w, h, AnchorPoint::BottomRight),
268 };
269
270 (delta_w as i32, delta_h as i32, ap)
271 }
272
273 pub const fn transform(&self, size: &Size) -> (Size, AnchorPoint) {
286 let (delta_w, delta_h, anchor_point) = self.unwrap();
287 let width = size.width as i32 + delta_w;
288 let height = size.height as i32 + delta_h;
289
290 (Size::new(width as u32, height as u32), anchor_point)
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297
298 #[test]
299 fn test_lw_point_i8_from_point() {
300 let point = Point::new(10, -20);
301 let lw_point: LwPoint<i8> = point.into();
302 assert_eq!(lw_point.x, 10);
303 assert_eq!(lw_point.y, -20);
304 }
305
306 #[test]
307 fn test_lw_point_i8_to_point() {
308 let lw_point = LwPoint { x: 5i8, y: -10i8 };
309 let point: Point = lw_point.into();
310 assert_eq!(point, Point::new(5, -10));
311 }
312
313 #[test]
314 fn test_lw_point_i8_overflow() {
315 let point = Point::new(200, -200);
316 let lw_point: LwPoint<i8> = point.into();
317 assert_eq!(lw_point.x, 127);
318 assert_eq!(lw_point.y, -128);
319 }
320
321 #[test]
322 fn test_lw_point_i16_from_point() {
323 let point = Point::new(1000, -2000);
324 let lw_point: LwPoint<i16> = point.into();
325 assert_eq!(lw_point.x, 1000);
326 assert_eq!(lw_point.y, -2000);
327 }
328
329 #[test]
330 fn test_lw_point_i16_to_point() {
331 let lw_point = LwPoint {
332 x: 500i16,
333 y: -1000i16,
334 };
335 let point: Point = lw_point.into();
336 assert_eq!(point, Point::new(500, -1000));
337 }
338
339 #[test]
340 fn test_lw_point_i16_large_value() {
341 let point = Point::new(i32::MAX, i32::MIN);
342 let lw_point: LwPoint<i16> = point.into();
343 assert_eq!(lw_point.x, i16::MAX);
344 assert_eq!(lw_point.y, i16::MIN);
345 }
346
347 #[test]
348 fn test_lw_point_zero() {
349 let point = Point::new(0, 0);
350 let lw_point_i8: LwPoint<i8> = point.into();
351 let lw_point_i16: LwPoint<i16> = point.into();
352 assert_eq!(lw_point_i8.x, 0);
353 assert_eq!(lw_point_i16.y, 0);
354 }
355
356 #[test]
357 fn test_lw_point_into_i8() {
358 let point = Point::new(10, -20);
359 let lw_point: LwPoint<i8> = point.into();
360 assert_eq!(lw_point.x, 10);
361 assert_eq!(lw_point.y, -20);
362 }
363
364 #[test]
365 fn test_lw_point_into_i16() {
366 let point = Point::new(1000, -2000);
367 let lw_point: LwPoint<i16> = point.into();
368 assert_eq!(lw_point.x, 1000);
369 assert_eq!(lw_point.y, -2000);
370 }
371
372 #[test]
373 fn test_lw_point_from_i8() {
374 let lw_point = LwPoint { x: 5i8, y: -10i8 };
375 let point: Point = lw_point.into();
376 assert_eq!(point, Point::new(5, -10));
377 }
378
379 #[test]
380 fn test_lw_point_from_i16() {
381 let lw_point = LwPoint {
382 x: 500i16,
383 y: -1000i16,
384 };
385 let point: Point = lw_point.into();
386 assert_eq!(point, Point::new(500, -1000));
387 }
388
389 #[test]
390 fn test_lw_size_u8_from_size() {
391 let size = Size::new(100, 200);
392 let lw_size: LwSize<u8> = size.into();
393 assert_eq!(lw_size.width, 100);
394 assert_eq!(lw_size.height, 200);
395 }
396
397 #[test]
398 fn test_lw_size_u8_to_size() {
399 let lw_size = LwSize {
400 width: 50u8,
401 height: 100u8,
402 };
403 let size: Size = lw_size.into();
404 assert_eq!(size, Size::new(50, 100));
405 }
406
407 #[test]
408 fn test_lw_size_u8_overflow() {
409 let size = Size::new(300, 300);
410 let lw_size: LwSize<u8> = size.into();
411 assert_eq!(lw_size.width, u8::MAX);
412 assert_eq!(lw_size.height, u8::MAX);
413 }
414
415 #[test]
416 fn test_lw_size_u16_from_size() {
417 let size = Size::new(1000, 2000);
418 let lw_size: LwSize<u16> = size.into();
419 assert_eq!(lw_size.width, 1000);
420 assert_eq!(lw_size.height, 2000);
421 }
422
423 #[test]
424 fn test_lw_size_u16_to_size() {
425 let lw_size = LwSize {
426 width: 500u16,
427 height: 1000u16,
428 };
429 let size: Size = lw_size.into();
430 assert_eq!(size, Size::new(500, 1000));
431 }
432
433 #[test]
434 fn test_lw_size_u16_large_value() {
435 let size = Size::new(u32::MAX, u32::MAX);
436 let lw_size: LwSize<u16> = size.into();
437 assert_eq!(lw_size.width, u16::MAX);
438 assert_eq!(lw_size.height, u16::MAX);
439 }
440
441 #[test]
442 fn test_lw_size_zero() {
443 let size = Size::new(0, 0);
444 let lw_size_u8: LwSize<u8> = size.into();
445 let lw_size_u16: LwSize<u16> = size.into();
446 assert_eq!(lw_size_u8.width, 0);
447 assert_eq!(lw_size_u16.height, 0);
448 }
449}