1#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize))]
10pub struct Color {
11 pub r: u8,
13 pub g: u8,
15 pub b: u8,
17}
18
19impl Color {
20 pub const BLACK: Color = Color { r: 0, g: 0, b: 0 };
22 pub const WHITE: Color = Color { r: 2, g: 2, b: 2 };
24
25 #[must_use]
27 pub const fn new(r: u8, g: u8, b: u8) -> Self {
28 Color {
29 r: r & 0x03,
30 g: g & 0x03,
31 b: b & 0x03,
32 }
33 }
34
35 #[must_use]
38 pub const fn to_8_color(self) -> Color {
39 const fn q(c: u8) -> u8 {
40 match c {
41 0 | 1 => 0,
42 _ => 2,
43 }
44 }
45 Color {
46 r: q(self.r),
47 g: q(self.g),
48 b: q(self.b),
49 }
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
56#[cfg_attr(feature = "serde", derive(serde::Serialize))]
57#[non_exhaustive]
58pub enum Opacity {
59 #[default]
61 Solid,
62 Flash,
64 Translucent,
66 Transparent,
68}
69
70impl Opacity {
71 #[must_use]
73 pub fn from_bits(v: u8) -> Self {
74 match v & 0x03 {
75 0 => Self::Solid,
76 1 => Self::Flash,
77 2 => Self::Translucent,
78 _ => Self::Transparent,
79 }
80 }
81 #[must_use]
83 pub fn name(&self) -> &'static str {
84 match self {
85 Self::Solid => "solid",
86 Self::Flash => "flash",
87 Self::Translucent => "translucent",
88 Self::Transparent => "transparent",
89 }
90 }
91}
92dvb_common::impl_spec_display!(Opacity);
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
96#[cfg_attr(feature = "serde", derive(serde::Serialize))]
97#[non_exhaustive]
98pub enum EdgeType {
99 #[default]
101 None,
102 Raised,
104 Depressed,
106 Uniform,
108 LeftDropShadow,
110 RightDropShadow,
112}
113
114impl EdgeType {
115 #[must_use]
117 pub fn from_bits(v: u8) -> Self {
118 match v & 0x07 {
119 0 => Self::None,
120 1 => Self::Raised,
121 2 => Self::Depressed,
122 3 => Self::Uniform,
123 4 => Self::LeftDropShadow,
124 5 => Self::RightDropShadow,
125 _ => Self::None,
126 }
127 }
128 #[must_use]
130 pub fn name(&self) -> &'static str {
131 match self {
132 Self::None => "none",
133 Self::Raised => "raised",
134 Self::Depressed => "depressed",
135 Self::Uniform => "uniform",
136 Self::LeftDropShadow => "left_drop_shadow",
137 Self::RightDropShadow => "right_drop_shadow",
138 }
139 }
140}
141dvb_common::impl_spec_display!(EdgeType);
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
145#[cfg_attr(feature = "serde", derive(serde::Serialize))]
146#[non_exhaustive]
147pub enum PenSize {
148 Small,
150 #[default]
152 Standard,
153 Large,
155}
156
157impl PenSize {
158 #[must_use]
160 pub fn from_bits(v: u8) -> Self {
161 match v & 0x03 {
162 0 => Self::Small,
163 2 => Self::Large,
164 _ => Self::Standard,
165 }
166 }
167 #[must_use]
169 pub fn name(&self) -> &'static str {
170 match self {
171 Self::Small => "small",
172 Self::Standard => "standard",
173 Self::Large => "large",
174 }
175 }
176}
177dvb_common::impl_spec_display!(PenSize);
178
179#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
181#[cfg_attr(feature = "serde", derive(serde::Serialize))]
182#[non_exhaustive]
183pub enum PenOffset {
184 Subscript,
186 #[default]
188 Normal,
189 Superscript,
191}
192
193impl PenOffset {
194 #[must_use]
196 pub fn from_bits(v: u8) -> Self {
197 match v & 0x03 {
198 0 => Self::Subscript,
199 2 => Self::Superscript,
200 _ => Self::Normal,
201 }
202 }
203 #[must_use]
205 pub fn name(&self) -> &'static str {
206 match self {
207 Self::Subscript => "subscript",
208 Self::Normal => "normal",
209 Self::Superscript => "superscript",
210 }
211 }
212}
213dvb_common::impl_spec_display!(PenOffset);
214
215#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
217#[cfg_attr(feature = "serde", derive(serde::Serialize))]
218#[non_exhaustive]
219pub enum FontStyle {
220 #[default]
222 Default,
223 MonospacedSerif,
225 ProportionalSerif,
227 MonospacedSansSerif,
229 ProportionalSansSerif,
231 Casual,
233 Cursive,
235 SmallCapitals,
237}
238
239impl FontStyle {
240 #[must_use]
242 pub fn from_bits(v: u8) -> Self {
243 match v & 0x07 {
244 0 => Self::Default,
245 1 => Self::MonospacedSerif,
246 2 => Self::ProportionalSerif,
247 3 => Self::MonospacedSansSerif,
248 4 => Self::ProportionalSansSerif,
249 5 => Self::Casual,
250 6 => Self::Cursive,
251 _ => Self::SmallCapitals,
252 }
253 }
254 #[must_use]
256 pub fn name(&self) -> &'static str {
257 match self {
258 Self::Default => "default",
259 Self::MonospacedSerif => "monospaced_serif",
260 Self::ProportionalSerif => "proportional_serif",
261 Self::MonospacedSansSerif => "monospaced_sans_serif",
262 Self::ProportionalSansSerif => "proportional_sans_serif",
263 Self::Casual => "casual",
264 Self::Cursive => "cursive",
265 Self::SmallCapitals => "small_capitals",
266 }
267 }
268}
269dvb_common::impl_spec_display!(FontStyle);
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
273#[cfg_attr(feature = "serde", derive(serde::Serialize))]
274#[non_exhaustive]
275pub enum Justify {
276 #[default]
278 Left,
279 Right,
281 Center,
283 Full,
285}
286
287impl Justify {
288 #[must_use]
290 pub fn from_bits(v: u8) -> Self {
291 match v & 0x03 {
292 0 => Self::Left,
293 1 => Self::Right,
294 2 => Self::Center,
295 _ => Self::Full,
296 }
297 }
298 #[must_use]
300 pub fn name(&self) -> &'static str {
301 match self {
302 Self::Left => "left",
303 Self::Right => "right",
304 Self::Center => "center",
305 Self::Full => "full",
306 }
307 }
308}
309dvb_common::impl_spec_display!(Justify);
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
313#[cfg_attr(feature = "serde", derive(serde::Serialize))]
314#[non_exhaustive]
315pub enum PrintDirection {
316 #[default]
318 LeftToRight,
319 RightToLeft,
321 TopToBottom,
323 BottomToTop,
325}
326
327impl PrintDirection {
328 #[must_use]
330 pub fn from_bits(v: u8) -> Self {
331 match v & 0x03 {
332 0 => Self::LeftToRight,
333 1 => Self::RightToLeft,
334 2 => Self::TopToBottom,
335 _ => Self::BottomToTop,
336 }
337 }
338 #[must_use]
340 pub fn name(&self) -> &'static str {
341 match self {
342 Self::LeftToRight => "left_to_right",
343 Self::RightToLeft => "right_to_left",
344 Self::TopToBottom => "top_to_bottom",
345 Self::BottomToTop => "bottom_to_top",
346 }
347 }
348}
349dvb_common::impl_spec_display!(PrintDirection);
350
351#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
354#[cfg_attr(feature = "serde", derive(serde::Serialize))]
355#[non_exhaustive]
356pub enum ScrollDirection {
357 LeftToRight,
359 RightToLeft,
361 TopToBottom,
363 #[default]
365 BottomToTop,
366}
367
368impl ScrollDirection {
369 #[must_use]
371 pub fn from_bits(v: u8) -> Self {
372 match v & 0x03 {
373 0 => Self::LeftToRight,
374 1 => Self::RightToLeft,
375 2 => Self::TopToBottom,
376 _ => Self::BottomToTop,
377 }
378 }
379 #[must_use]
381 pub fn name(&self) -> &'static str {
382 match self {
383 Self::LeftToRight => "left_to_right",
384 Self::RightToLeft => "right_to_left",
385 Self::TopToBottom => "top_to_bottom",
386 Self::BottomToTop => "bottom_to_top",
387 }
388 }
389}
390dvb_common::impl_spec_display!(ScrollDirection);
391
392#[cfg(test)]
393mod tests {
394 use super::*;
395 use alloc::string::ToString;
396
397 #[test]
398 fn color_8_color_mapping() {
399 assert_eq!(Color::new(1, 2, 3).to_8_color(), Color::new(0, 2, 2));
401 assert_eq!(Color::new(3, 3, 3).to_8_color(), Color::WHITE);
402 assert_eq!(Color::new(1, 1, 1).to_8_color(), Color::BLACK);
403 }
404
405 #[test]
406 fn opacity_bits() {
407 assert_eq!(Opacity::from_bits(0), Opacity::Solid);
408 assert_eq!(Opacity::from_bits(3), Opacity::Transparent);
409 assert_eq!(Opacity::Translucent.to_string(), "translucent");
410 }
411
412 #[test]
413 fn edge_bits() {
414 assert_eq!(EdgeType::from_bits(5), EdgeType::RightDropShadow);
415 assert_eq!(EdgeType::from_bits(7), EdgeType::None);
416 }
417
418 #[test]
419 fn font_bits() {
420 assert_eq!(FontStyle::from_bits(7), FontStyle::SmallCapitals);
421 assert_eq!(FontStyle::from_bits(1).to_string(), "monospaced_serif");
422 }
423}