1use crate::tartan_register_shades::SHADES;
2use alloc::collections::BTreeMap;
3use alloc::vec::Vec;
4use core::iter::repeat;
5use no_std_compat::cmp::Ordering;
6
7#[derive(Debug, PartialEq)]
8pub enum Pivot {
9 True,
10 False,
11 Maybe,
12}
13
14#[derive(Debug, PartialEq)]
15pub struct Span {
16 pub colour: Colour,
17 pub count: usize,
18 pub pivot: Pivot,
19}
20
21impl Span {
22 pub fn new(colour: &str, count: &str) -> Self {
23 Self {
24 colour: Colour::get(colour).unwrap(),
25 count: count.parse::<usize>().unwrap(),
26 pivot: Pivot::Maybe,
27 }
28 }
29 pub fn pivot(colour: &str, count: &str) -> Self {
30 Self {
31 colour: Colour::get(colour).unwrap(),
32 count: count.parse::<usize>().unwrap(),
33 pivot: Pivot::True,
34 }
35 }
36}
37
38#[derive(Debug, PartialEq)]
39pub enum Weft {
40 Identical,
41 Different,
42}
43
44#[derive(Debug, PartialEq)]
45pub struct Sett {
46 pub pattern: Vec<Span>,
47 pub symmetric: bool,
48 pub weft: Weft,
49}
50
51impl Default for Sett {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57impl Sett {
58 pub fn new() -> Self {
59 Self {
60 pattern: vec![],
61 symmetric: true,
62 weft: Weft::Identical,
63 }
64 }
65
66 pub fn shuttle(&self) -> impl Iterator<Item = &Span> {
68 let len = self.pattern.len();
69 self.pattern
70 .iter()
71 .chain(self.pattern.iter().rev().skip(1).take(len - 2))
72 .cycle()
73 }
74
75 pub fn colours(&self, skip: usize) -> impl Iterator<Item = &Colour> {
76 self.shuttle()
77 .skip(skip)
78 .flat_map(|span| repeat(&span.colour).take(span.count))
79 }
80
81 pub fn coord_colours(
82 &self,
83 width: u32,
84 height: u32,
85 skip: usize,
86 ) -> impl Iterator<Item = (u32, u32, &Colour)> {
87 (0..height).flat_map(move |y| {
88 (0..width).zip(self.colours(skip)).map(move |(x, colour)| {
89 if (x + y) / 2 % 2 == 0 {
90 (x, y, colour)
91 } else {
92 (y, x, colour)
93 }
94 })
95 })
96 }
97}
98
99#[derive(Copy, Clone, Debug, PartialEq)]
100pub struct Shade {
101 pub colour: Colour,
102 pub tone: Tone,
103 pub rgb: [u8; 3],
104}
105
106#[derive(Copy, Clone, Debug, PartialEq)]
107pub enum Tone {
108 Light,
109 Medium,
110 Dark,
111}
112
113#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd)]
114pub enum Colour {
115 Red,
116 Orange,
117 Yellow,
118 Green,
119 Blue,
120 Purple,
121 White,
122 Grey,
123 Black,
124 Brown,
125}
126
127impl Colour {
128 pub fn get(letter: &str) -> Option<Self> {
129 use Colour::*;
130
131 match letter {
132 "R" => Some(Red),
133 "O" => Some(Orange),
134 "Y" => Some(Yellow),
135 "G" => Some(Green),
136 "B" => Some(Blue),
137 "RB" => Some(Blue), "P" => Some(Purple),
139 "W" => Some(White),
140 "N" => Some(Grey), "K" => Some(Black),
142 "Bk" => Some(Black),
143 "T" => Some(Brown), _ => None,
145 }
146 }
147
148 pub fn to_array(&self, palette: &Palette) -> [u8; 3] {
149 if let Some(shade) = palette.shades.get(self) {
150 shade.rgb
151 } else {
152 [0, 255, 0]
153 }
154 }
155}
156
157#[allow(clippy::derive_ord_xor_partial_ord)]
158impl Ord for Colour {
159 fn cmp(&self, other: &Self) -> Ordering {
160 (format!("{:?}", &self)).cmp(&format!("{:?}", &other))
161 }
162}
163
164#[derive(Debug, PartialEq)]
165pub enum Colourway {
166 Modern,
167 Ancient,
168 Reproduction,
169 Weathered, Muted,
171 Standard,
172}
173impl Default for Colourway {
174 fn default() -> Self {
175 Colourway::Modern
176 }
177}
178
179#[derive(Debug, PartialEq)]
180pub enum Variation {
181 Hunting,
182 Dress,
183}
184
185#[derive(Debug)]
186pub struct Palette {
187 pub colourway: Option<Colourway>,
188 pub variation: Option<Variation>,
189 pub shades: BTreeMap<Colour, Shade>,
190}
191
192impl Default for Palette {
193 fn default() -> Self {
194 use Colour::*;
195
196 let shades = BTreeMap::from([
197 (Red, SHADES[7]),
198 (Orange, SHADES[20]),
199 (Yellow, SHADES[32]),
200 (Green, SHADES[62]),
201 (Blue, SHADES[89]),
202 (Purple, SHADES[99]),
203 (White, SHADES[106]),
204 (Grey, SHADES[113]),
205 (Black, SHADES[119]),
206 (Brown, SHADES[131]),
207 ]);
208 Palette {
209 colourway: Some(Colourway::default()),
210 variation: None,
211 shades,
212 }
213 }
214}