buffer_graphics_lib/text/
format.rs

1use crate::text::wrapping::WrappingStrategy;
2use crate::text::PixelFont;
3use ici_files::prelude::*;
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7/// Characters be drawn be at idx * char_width, idx * char_height
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9#[derive(Clone, Debug, PartialEq)]
10pub struct TextFormat {
11    color: Color,
12    font: PixelFont,
13    wrap_at: WrappingStrategy,
14    line_height: f32,
15    char_width: f32,
16    positioning: Positioning,
17}
18
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20#[derive(Debug, Clone, Eq, PartialEq, Copy, Default)]
21pub enum Positioning {
22    #[default]
23    LeftTop,
24    CenterTop,
25    RightTop,
26    LeftCenter,
27    Center,
28    RightCenter,
29    LeftBottom,
30    CenterBottom,
31    RightBottom,
32}
33
34impl Positioning {
35    pub fn calc(&self, xy: (isize, isize), width: usize, height: usize) -> (isize, isize) {
36        let factor = match self {
37            Positioning::LeftTop => (0.0, 0.0),
38            Positioning::CenterTop => (-0.5, 0.0),
39            Positioning::RightTop => (-1.0, 0.0),
40            Positioning::LeftCenter => (0.0, -0.5),
41            Positioning::Center => (-0.5, -0.5),
42            Positioning::RightCenter => (-1.0, -0.5),
43            Positioning::LeftBottom => (0.0, -1.0),
44            Positioning::CenterBottom => (-0.5, -1.0),
45            Positioning::RightBottom => (-1.0, -1.0),
46        };
47        (
48            xy.0 + (factor.0 * width as f32) as isize,
49            xy.1 + (factor.1 * height as f32) as isize,
50        )
51    }
52}
53
54impl TextFormat {
55    pub const fn new(
56        wrap_at: WrappingStrategy,
57        size: PixelFont,
58        color: Color,
59        positioning: Positioning,
60    ) -> Self {
61        Self {
62            wrap_at,
63            font: size,
64            color,
65            line_height: 1.0,
66            char_width: 1.0,
67            positioning,
68        }
69    }
70
71    pub const fn new_with_spacing(
72        wrap_at: WrappingStrategy,
73        size: PixelFont,
74        color: Color,
75        line_height: f32,
76        char_width: f32,
77        positioning: Positioning,
78    ) -> Self {
79        Self {
80            wrap_at,
81            font: size,
82            color,
83            line_height,
84            char_width,
85            positioning,
86        }
87    }
88}
89
90impl Default for TextFormat {
91    fn default() -> Self {
92        let size = PixelFont::default();
93        Self {
94            wrap_at: WrappingStrategy::default(),
95            font: size,
96            color: Color::default(),
97            line_height: 1.0,
98            char_width: 1.0,
99            positioning: Positioning::LeftTop,
100        }
101    }
102}
103
104impl TextFormat {
105    #[inline]
106    pub fn wrapping(&self) -> WrappingStrategy {
107        self.wrap_at
108    }
109
110    #[inline]
111    pub fn font(&self) -> PixelFont {
112        self.font
113    }
114
115    #[inline]
116    pub fn color(&self) -> Color {
117        self.color
118    }
119
120    #[inline]
121    pub fn line_height(&self) -> isize {
122        (self.line_height * (self.font.size().1 + self.font.spacing()) as f32).round() as isize
123    }
124
125    #[inline]
126    pub fn char_width(&self) -> isize {
127        (self.char_width * (self.font.size().0 + self.font.spacing()) as f32).round() as isize
128    }
129
130    #[inline]
131    pub fn positioning(&self) -> Positioning {
132        self.positioning
133    }
134
135    #[inline]
136    pub fn with_color(&self, color: Color) -> Self {
137        TextFormat { color, ..*self }
138    }
139}
140
141impl From<(Color, PixelFont, WrappingStrategy, f32, f32, Positioning)> for TextFormat {
142    fn from(
143        (color, size, wrap_at, line_height, char_width, positioning): (
144            Color,
145            PixelFont,
146            WrappingStrategy,
147            f32,
148            f32,
149            Positioning,
150        ),
151    ) -> Self {
152        TextFormat {
153            color,
154            font: size,
155            wrap_at,
156            line_height,
157            char_width,
158            positioning,
159        }
160    }
161}
162
163impl From<(Color, PixelFont, WrappingStrategy, f32, f32)> for TextFormat {
164    fn from(
165        (color, size, wrap_at, line_height, char_width): (
166            Color,
167            PixelFont,
168            WrappingStrategy,
169            f32,
170            f32,
171        ),
172    ) -> Self {
173        TextFormat {
174            color,
175            font: size,
176            wrap_at,
177            line_height,
178            char_width,
179            ..Self::default()
180        }
181    }
182}
183
184impl From<(Color, PixelFont, WrappingStrategy, f32)> for TextFormat {
185    fn from(
186        (color, size, wrap_at, line_height): (Color, PixelFont, WrappingStrategy, f32),
187    ) -> Self {
188        TextFormat {
189            color,
190            font: size,
191            wrap_at,
192            line_height,
193            ..Self::default()
194        }
195    }
196}
197
198impl From<(Color, PixelFont, WrappingStrategy)> for TextFormat {
199    fn from((color, size, wrap_at): (Color, PixelFont, WrappingStrategy)) -> Self {
200        TextFormat {
201            color,
202            font: size,
203            wrap_at,
204            ..Self::default()
205        }
206    }
207}
208
209impl From<(Color, PixelFont, WrappingStrategy, Positioning)> for TextFormat {
210    fn from(
211        (color, size, wrap_at, positioning): (Color, PixelFont, WrappingStrategy, Positioning),
212    ) -> Self {
213        TextFormat {
214            color,
215            font: size,
216            wrap_at,
217            positioning,
218            ..Self::default()
219        }
220    }
221}
222
223impl From<(Color, PixelFont)> for TextFormat {
224    fn from((color, size): (Color, PixelFont)) -> Self {
225        TextFormat {
226            color,
227            font: size,
228            ..Self::default()
229        }
230    }
231}
232
233impl From<(Color, PixelFont, Positioning)> for TextFormat {
234    fn from((color, size, positioning): (Color, PixelFont, Positioning)) -> Self {
235        TextFormat {
236            color,
237            font: size,
238            positioning,
239            ..Self::default()
240        }
241    }
242}
243
244impl From<Color> for TextFormat {
245    fn from(color: Color) -> Self {
246        TextFormat {
247            color,
248            ..Self::default()
249        }
250    }
251}