smart_leds_matrix/
layout.rs1use core::marker::PhantomData;
4
5use embedded_graphics_core::geometry::{Point, Size};
6use invert_axis::{InvertX, InvertXY, InvertY, NoInvert};
7
8pub trait Layout {
16 fn map(&self, p: Point) -> Option<usize>;
17 fn size(&self) -> Size;
18}
19
20pub struct Rectangular<I> {
22 size: Size,
23 invert_axis: PhantomData<I>,
24}
25
26impl<I> Rectangular<I> {
27 const fn new_common(width: u32, height: u32) -> Self {
28 Self {
29 size: Size::new(width, height),
30 invert_axis: PhantomData,
31 }
32 }
33}
34
35impl Rectangular<NoInvert> {
36 pub const fn new(width: u32, height: u32) -> Self {
38 Self::new_common(width, height)
39 }
40}
41
42impl Rectangular<InvertX> {
43 pub const fn new_invert_x(width: u32, height: u32) -> Self {
45 Self::new_common(width, height)
46 }
47}
48
49impl Rectangular<InvertY> {
50 pub const fn new_invert_y(width: u32, height: u32) -> Self {
52 Self::new_common(width, height)
53 }
54}
55
56impl Rectangular<InvertXY> {
57 pub const fn new_invert_xy(width: u32, height: u32) -> Self {
59 Self::new_common(width, height)
60 }
61}
62
63macro_rules! impl_layout {
64 ($invert_type:ty, $invert_x:expr, $invert_y:expr) => {
65 impl Layout for Rectangular<$invert_type> {
66 fn map(&self, mut p: Point) -> Option<usize> {
67 if $invert_x {
68 p.x = (self.size.width - 1) as i32 - p.x;
69 }
70 if $invert_y {
71 p.y = (self.size.height - 1) as i32 - p.y;
72 }
73
74 (p.x >= 0
75 && p.y >= 0
76 && p.x < self.size.width as i32
77 && p.y < self.size.height as i32)
78 .then(|| p.y as usize * self.size.width as usize + p.x as usize)
79 }
80
81 fn size(&self) -> Size {
82 return self.size;
83 }
84 }
85 };
86}
87
88impl_layout!(NoInvert, false, false);
89impl_layout!(InvertX, true, false);
90impl_layout!(InvertY, false, true);
91impl_layout!(InvertXY, true, true);
92
93pub mod invert_axis {
95 pub enum NoInvert {}
97
98 pub enum InvertX {}
100
101 pub enum InvertY {}
103
104 pub enum InvertXY {}
106}