1use crate::text::wrapping::WrappingStrategy;
2use crate::text::PixelFont;
3use ici_files::prelude::*;
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7#[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}