1#[cfg(feature = "serde")]
22use crate::LoadPaletteErr;
23use ratatui::style::{Color, Style};
24#[cfg(feature = "serde")]
25use serde::de::{Error, MapAccess, SeqAccess, Unexpected, Visitor};
26#[cfg(feature = "serde")]
27use serde::ser::SerializeStruct;
28#[cfg(feature = "serde")]
29use serde::{Deserialize, Deserializer, Serialize, Serializer};
30#[cfg(feature = "serde")]
31use std::array;
32use std::borrow::Cow;
33use std::fmt::{Display, Formatter};
34use std::mem;
35use std::str::FromStr;
36
37#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub struct ColorIdx(pub Colors, pub usize);
41
42#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
44pub enum Colors {
45 TextLight = 0,
47 TextDark,
49 Primary,
51 Secondary,
53 White,
54 Black,
55 Gray,
56 Red,
57 Orange,
58 Yellow,
59 LimeGreen,
60 Green,
61 BlueGreen,
62 Cyan,
63 Blue,
64 DeepBlue,
65 Purple,
66 Magenta,
67 RedPink,
68 #[default]
73 None,
74}
75
76impl Display for ColorIdx {
77 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78 write!(f, "{}:{}", self.0, self.1)
79 }
80}
81
82#[derive(Debug)]
83pub struct ColorIdxError;
84
85impl Display for ColorIdxError {
86 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
87 write!(f, "{:?}", self)
88 }
89}
90
91impl std::error::Error for ColorIdxError {}
92
93impl FromStr for ColorIdx {
94 type Err = ColorIdxError;
95
96 fn from_str(s: &str) -> Result<Self, Self::Err> {
97 let mut ss = s.split(':');
98 let Some(name) = ss.next() else {
99 return Err(ColorIdxError);
100 };
101 let Ok(c) = Colors::from_str(name) else {
102 return Err(ColorIdxError);
103 };
104 let Some(idx) = ss.next() else {
105 return Err(ColorIdxError);
106 };
107 let Ok(idx) = idx.parse::<usize>() else {
108 return Err(ColorIdxError);
109 };
110 Ok(ColorIdx(c, idx))
111 }
112}
113
114#[cfg(feature = "serde")]
115impl Serialize for ColorIdx {
116 fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
117 where
118 S: Serializer,
119 {
120 ser.serialize_str(&self.to_string())
121 }
122}
123
124#[cfg(feature = "serde")]
125struct ColorIdxVisitor;
126
127#[cfg(feature = "serde")]
128impl<'de> Visitor<'de> for ColorIdxVisitor {
129 type Value = ColorIdx;
130
131 fn expecting(&self, f: &mut Formatter) -> std::fmt::Result {
132 write!(f, "ColorIdx")
133 }
134
135 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
136 where
137 E: serde::de::Error,
138 {
139 v.parse::<ColorIdx>()
140 .map_err(|_| serde::de::Error::invalid_value(Unexpected::Str(v), &self))
141 }
142}
143
144#[cfg(feature = "serde")]
145impl<'de> Deserialize<'de> for ColorIdx {
146 fn deserialize<D>(des: D) -> Result<Self, D::Error>
147 where
148 D: Deserializer<'de>,
149 {
150 des.deserialize_str(ColorIdxVisitor)
151 }
152}
153
154impl Display for Colors {
155 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
156 write!(f, "{}", self.str())
157 }
158}
159
160impl FromStr for Colors {
161 type Err = ();
162
163 fn from_str(s: &str) -> Result<Self, Self::Err> {
164 match s {
165 "text-light" => Ok(Colors::TextLight),
166 "text-dark" => Ok(Colors::TextDark),
167 "primary" => Ok(Colors::Primary),
168 "secondary" => Ok(Colors::Secondary),
169 "white" => Ok(Colors::White),
170 "black" => Ok(Colors::Black),
171 "gray" => Ok(Colors::Gray),
172 "red" => Ok(Colors::Red),
173 "orange" => Ok(Colors::Orange),
174 "yellow" => Ok(Colors::Yellow),
175 "lime-green" => Ok(Colors::LimeGreen),
176 "green" => Ok(Colors::Green),
177 "blue-green" => Ok(Colors::BlueGreen),
178 "cyan" => Ok(Colors::Cyan),
179 "blue" => Ok(Colors::Blue),
180 "deep-blue" => Ok(Colors::DeepBlue),
181 "purple" => Ok(Colors::Purple),
182 "magenta" => Ok(Colors::Magenta),
183 "red-pink" => Ok(Colors::RedPink),
184 "none" => Ok(Colors::None),
185 _ => Err(()),
186 }
187 }
188}
189
190impl Colors {
191 pub const LEN: usize = 19;
192
193 pub fn array() -> &'static [Colors] {
194 use Colors::*;
195 &[
197 TextLight, TextDark, Primary, Secondary, White, Black, Gray, Red, Orange, Yellow,
198 LimeGreen, Green, BlueGreen, Cyan, Blue, DeepBlue, Purple, Magenta, RedPink,
199 ]
200 }
201
202 pub const fn str(self) -> &'static str {
203 match self {
204 Colors::TextLight => "text-light",
205 Colors::TextDark => "text-dark",
206 Colors::Primary => "primary",
207 Colors::Secondary => "secondary",
208 Colors::White => "white",
209 Colors::Black => "black",
210 Colors::Gray => "gray",
211 Colors::Red => "red",
212 Colors::Orange => "orange",
213 Colors::Yellow => "yellow",
214 Colors::LimeGreen => "lime-green",
215 Colors::Green => "green",
216 Colors::BlueGreen => "blue-green",
217 Colors::Cyan => "cyan",
218 Colors::Blue => "blue",
219 Colors::DeepBlue => "deep-blue",
220 Colors::Purple => "purple",
221 Colors::Magenta => "magenta",
222 Colors::RedPink => "red-pink",
223 Colors::None => "none",
224 }
225 }
226}
227
228#[derive(Debug, Default, Clone, PartialEq, Eq)]
232pub struct Palette {
233 pub theme_name: Cow<'static, str>,
235 pub theme: Cow<'static, str>,
250 pub name: Cow<'static, str>,
252 pub doc: Cow<'static, str>,
254 pub generator: Cow<'static, str>,
275 pub color: [[Color; 8]; Colors::LEN],
277 pub aliased: Cow<'static, [(Cow<'static, str>, ColorIdx)]>,
280}
281
282#[cfg(feature = "serde")]
283impl Serialize for Palette {
284 fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
285 where
286 S: Serializer,
287 {
288 let mut pal = ser.serialize_struct("Palette", 25)?;
289 pal.serialize_field("theme_name", &self.theme_name)?;
290 pal.serialize_field("theme", &self.theme)?;
291 pal.serialize_field("name", &self.name)?;
292 pal.serialize_field("doc", &self.doc)?;
293 pal.serialize_field("generator", &self.generator)?;
294 if self.generator.starts_with("light-dark") {
295 for cc in Colors::array() {
296 pal.serialize_field(
297 cc.str(),
298 &(self.color[*cc as usize][0], self.color[*cc as usize][3]),
299 )?;
300 }
301 } else if self.generator.starts_with("color-1") {
302 for cc in Colors::array() {
303 pal.serialize_field(cc.str(), &self.color[*cc as usize][0])?;
304 }
305 } else if self.generator.starts_with("color-2") {
306 for cc in Colors::array() {
307 pal.serialize_field(
308 cc.str(),
309 &(self.color[*cc as usize][0], self.color[*cc as usize][4]),
310 )?;
311 }
312 } else if self.generator.starts_with("color-4") {
313 for cc in Colors::array() {
314 pal.serialize_field(
315 cc.str(),
316 &(
317 self.color[*cc as usize][0],
318 self.color[*cc as usize][1],
319 self.color[*cc as usize][2],
320 self.color[*cc as usize][3],
321 ),
322 )?;
323 }
324 } else if self.generator.starts_with("color-4-dark") {
325 for cc in Colors::array() {
326 pal.serialize_field(
327 cc.str(),
328 &(
329 self.color[*cc as usize][0],
330 self.color[*cc as usize][1],
331 self.color[*cc as usize][2],
332 self.color[*cc as usize][3],
333 ),
334 )?;
335 }
336 } else if self.generator.starts_with("color-8") {
337 for cc in Colors::array() {
338 pal.serialize_field(
339 cc.str(),
340 &(
341 self.color[*cc as usize][0],
342 self.color[*cc as usize][1],
343 self.color[*cc as usize][2],
344 self.color[*cc as usize][3],
345 self.color[*cc as usize][4],
346 self.color[*cc as usize][5],
347 self.color[*cc as usize][6],
348 self.color[*cc as usize][7],
349 ),
350 )?;
351 }
352 } else {
353 use serde::ser::Error;
354 return Err(S::Error::custom(LoadPaletteErr(format!(
355 "Invalid generator format {:?}",
356 self.generator
357 ))));
358 }
359 pal.serialize_field("aliased", &self.aliased)?;
360 pal.end()
361 }
362}
363
364#[cfg(feature = "serde")]
365struct PaletteVisitor;
366
367#[cfg(feature = "serde")]
368impl<'de> Visitor<'de> for PaletteVisitor {
369 type Value = Palette;
370
371 fn expecting(&self, f: &mut Formatter) -> std::fmt::Result {
372 write!(f, "struct Palette")
373 }
374
375 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
376 where
377 A: SeqAccess<'de>,
378 {
379 let mut pal = Palette::default();
380 pal.theme_name = seq
381 .next_element::<Cow<'static, str>>()?
382 .ok_or(A::Error::invalid_length(0, &"Palette.theme_name"))?;
383 pal.theme = seq
384 .next_element::<Cow<'static, str>>()?
385 .ok_or(A::Error::invalid_length(0, &"Palette.theme"))?;
386 pal.name = seq
387 .next_element::<Cow<'static, str>>()?
388 .ok_or(A::Error::invalid_length(0, &"Palette.name"))?;
389 pal.doc = seq
390 .next_element::<Cow<'static, str>>()?
391 .ok_or(A::Error::invalid_length(0, &"Palette.doc"))?;
392 pal.generator = seq
393 .next_element::<Cow<'static, str>>()?
394 .ok_or(A::Error::invalid_length(0, &"Palette.generator"))?;
395 if pal.generator.starts_with("light-dark") {
396 let mut dark = 63;
397 if let Some(s) = pal.generator.split(':').nth(1) {
398 dark = s.trim().parse::<u8>().unwrap_or(63);
399 }
400
401 for cn in Colors::array() {
402 let (c0, c3) = seq
403 .next_element::<(Color, Color)>()?
404 .ok_or(A::Error::invalid_length(0, &"Palette.color"))?;
405
406 if *cn == Colors::TextLight || *cn == Colors::TextDark {
407 pal.color[*cn as usize] =
408 Palette::interpolatec2(c0, c3, Color::default(), Color::default())
409 } else {
410 pal.color[*cn as usize] = Palette::interpolatec(c0, c3, dark);
411 }
412 }
413 } else if pal.generator.starts_with("color-1") {
414 for cn in Colors::array() {
415 let c0 = seq
416 .next_element::<Color>()?
417 .ok_or(A::Error::invalid_length(0, &"Palette.color"))?;
418 pal.color[*cn as usize] = array::from_fn(|_| c0);
419 }
420 } else if pal.generator.starts_with("color-2") {
421 for cn in Colors::array() {
422 let (c0, c1) = seq
423 .next_element::<(Color, Color)>()?
424 .ok_or(A::Error::invalid_length(0, &"Palette.color"))?;
425 pal.color[*cn as usize][0] = c0;
426 pal.color[*cn as usize][1] = c0;
427 pal.color[*cn as usize][2] = c0;
428 pal.color[*cn as usize][3] = c0;
429 pal.color[*cn as usize][4] = c1;
430 pal.color[*cn as usize][5] = c1;
431 pal.color[*cn as usize][6] = c1;
432 pal.color[*cn as usize][7] = c1;
433 }
434 } else if pal.generator.starts_with("color-4") {
435 for cn in Colors::array() {
436 let (c0, c1, c2, c3) = seq
437 .next_element::<(Color, Color, Color, Color)>()?
438 .ok_or(A::Error::invalid_length(0, &"Palette.color"))?;
439 pal.color[*cn as usize][0] = c0;
440 pal.color[*cn as usize][1] = c1;
441 pal.color[*cn as usize][2] = c2;
442 pal.color[*cn as usize][3] = c3;
443 pal.color[*cn as usize][4] = c0;
444 pal.color[*cn as usize][5] = c1;
445 pal.color[*cn as usize][6] = c2;
446 pal.color[*cn as usize][7] = c3;
447 }
448 } else if pal.generator.starts_with("color-4-dark") {
449 let mut dark = 63;
450 if let Some(s) = pal.generator.split(':').nth(1) {
451 dark = s.trim().parse::<u8>().unwrap_or(63);
452 }
453
454 for cn in Colors::array() {
455 let (c0, c1, c2, c3) = seq
456 .next_element::<(Color, Color, Color, Color)>()?
457 .ok_or(A::Error::invalid_length(0, &"Palette.color"))?;
458 pal.color[*cn as usize][0] = c0;
459 pal.color[*cn as usize][1] = c1;
460 pal.color[*cn as usize][2] = c2;
461 pal.color[*cn as usize][3] = c3;
462 pal.color[*cn as usize][4] = Palette::scale_color_to(c0, dark);
463 pal.color[*cn as usize][5] = Palette::scale_color_to(c1, dark);
464 pal.color[*cn as usize][6] = Palette::scale_color_to(c2, dark);
465 pal.color[*cn as usize][7] = Palette::scale_color_to(c3, dark);
466 }
467 } else if pal.generator.starts_with("color-8") {
468 for cn in Colors::array() {
469 let (c0, c1, c2, c3, c4, c5, c6, c7) = seq
470 .next_element::<(Color, Color, Color, Color, Color, Color, Color, Color)>()?
471 .ok_or(A::Error::invalid_length(0, &"Palette.color"))?;
472 pal.color[*cn as usize][0] = c0;
473 pal.color[*cn as usize][1] = c1;
474 pal.color[*cn as usize][2] = c2;
475 pal.color[*cn as usize][3] = c3;
476 pal.color[*cn as usize][4] = c4;
477 pal.color[*cn as usize][5] = c5;
478 pal.color[*cn as usize][6] = c6;
479 pal.color[*cn as usize][7] = c7;
480 }
481 } else {
482 return Err(A::Error::invalid_type(
483 Unexpected::Str(&pal.generator),
484 &"expected 'light-dark:N'",
485 ));
486 }
487 pal.aliased = seq
488 .next_element::<Cow<'static, [(Cow<'static, str>, ColorIdx)]>>()?
489 .ok_or(A::Error::invalid_length(0, &"Palette.aliased"))?;
490
491 Ok(pal)
492 }
493
494 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
495 where
496 A: MapAccess<'de>,
497 {
498 let mut pal = Palette::default();
499 while let Some(key) = map.next_key::<&str>()? {
500 match key {
501 "theme_name" => pal.theme_name = map.next_value::<Cow<'static, str>>()?,
502 "theme" => pal.theme = map.next_value::<Cow<'static, str>>()?,
503 "name" => pal.name = map.next_value::<Cow<'static, str>>()?,
504 "doc" => pal.doc = map.next_value::<Cow<'static, str>>()?,
505 "generator" => {
506 pal.generator = map.next_value::<Cow<'static, str>>()?;
507 }
508 "aliased" => {
509 pal.aliased =
510 map.next_value::<Cow<'static, [(Cow<'static, str>, ColorIdx)]>>()?
511 }
512 c_str => {
513 let cn =
514 Colors::from_str(c_str).map_err(|_| A::Error::unknown_field(c_str, &[]))?;
515 if pal.generator.starts_with("light-dark") {
516 let mut dark = 63;
517 if let Some(s) = pal.generator.split(':').nth(1) {
518 dark = s.trim().parse::<u8>().unwrap_or(63);
519 }
520 let (c0, c3) = map.next_value::<(Color, Color)>()?;
521 if cn == Colors::TextLight || cn == Colors::TextDark {
522 pal.color[cn as usize] =
523 Palette::interpolatec2(c0, c3, Color::default(), Color::default())
524 } else {
525 pal.color[cn as usize] = Palette::interpolatec(c0, c3, dark);
526 }
527 } else if pal.generator.starts_with("color-1") {
528 let c0 = map.next_value::<Color>()?;
529 pal.color[cn as usize] = array::from_fn(|_| c0);
530 } else if pal.generator.starts_with("color-2") {
531 let (c0, c1) = map.next_value::<(Color, Color)>()?;
532 pal.color[cn as usize][0] = c0;
533 pal.color[cn as usize][1] = c0;
534 pal.color[cn as usize][2] = c0;
535 pal.color[cn as usize][3] = c0;
536 pal.color[cn as usize][4] = c1;
537 pal.color[cn as usize][5] = c1;
538 pal.color[cn as usize][6] = c1;
539 pal.color[cn as usize][7] = c1;
540 } else if pal.generator.starts_with("color-4") {
541 let (c0, c1, c2, c3) = map.next_value::<(Color, Color, Color, Color)>()?;
542 pal.color[cn as usize][0] = c0;
543 pal.color[cn as usize][1] = c1;
544 pal.color[cn as usize][2] = c2;
545 pal.color[cn as usize][3] = c3;
546 pal.color[cn as usize][4] = c0;
547 pal.color[cn as usize][5] = c1;
548 pal.color[cn as usize][6] = c2;
549 pal.color[cn as usize][7] = c3;
550 } else if pal.generator.starts_with("color-4-dark") {
551 let mut dark = 63;
552 if let Some(s) = pal.generator.split(':').nth(1) {
553 dark = s.trim().parse::<u8>().unwrap_or(63);
554 }
555 let (c0, c1, c2, c3) = map.next_value::<(Color, Color, Color, Color)>()?;
556 pal.color[cn as usize][0] = c0;
557 pal.color[cn as usize][1] = c1;
558 pal.color[cn as usize][2] = c2;
559 pal.color[cn as usize][3] = c3;
560 pal.color[cn as usize][4] = Palette::scale_color_to(c0, dark);
561 pal.color[cn as usize][5] = Palette::scale_color_to(c1, dark);
562 pal.color[cn as usize][6] = Palette::scale_color_to(c2, dark);
563 pal.color[cn as usize][7] = Palette::scale_color_to(c3, dark);
564 } else if pal.generator.starts_with("color-8") {
565 let (c0, c1, c2, c3, c4, c5, c6, c7) = map.next_value::<(
566 Color,
567 Color,
568 Color,
569 Color,
570 Color,
571 Color,
572 Color,
573 Color,
574 )>()?;
575 pal.color[cn as usize][0] = c0;
576 pal.color[cn as usize][1] = c1;
577 pal.color[cn as usize][2] = c2;
578 pal.color[cn as usize][3] = c3;
579 pal.color[cn as usize][4] = c4;
580 pal.color[cn as usize][5] = c5;
581 pal.color[cn as usize][6] = c6;
582 pal.color[cn as usize][7] = c7;
583 } else {
584 return Err(A::Error::invalid_type(
585 Unexpected::Str(&pal.generator),
586 &"expected 'light-dark:N'",
587 ));
588 }
589 }
590 }
591 }
592
593 Ok(pal)
594 }
595}
596
597#[cfg(feature = "serde")]
598impl<'de> Deserialize<'de> for Palette {
599 fn deserialize<D>(des: D) -> Result<Self, D::Error>
600 where
601 D: Deserializer<'de>,
602 {
603 use Colors::*;
604 const FIELDS: &'static [&'static str] = &[
605 "theme_name",
606 "theme",
607 "name",
608 "doc",
609 "generator",
610 TextLight.str(),
611 TextDark.str(),
612 Primary.str(),
613 Secondary.str(),
614 White.str(),
615 Black.str(),
616 Gray.str(),
617 Red.str(),
618 Orange.str(),
619 Yellow.str(),
620 LimeGreen.str(),
621 Green.str(),
622 BlueGreen.str(),
623 Cyan.str(),
624 Blue.str(),
625 DeepBlue.str(),
626 Purple.str(),
627 Magenta.str(),
628 RedPink.str(),
629 "aliased",
630 ];
631 let mut pal = des.deserialize_struct("Palette", FIELDS, PaletteVisitor)?;
632
633 if !pal.aliased.is_sorted() {
635 let mut aliased = pal.aliased.into_owned();
636 aliased.sort();
637 pal.aliased = Cow::Owned(aliased);
638 }
639
640 Ok(pal)
641 }
642}
643
644#[derive(Debug)]
646pub(crate) enum Rating {
647 Light,
649 Dark,
651}
652
653pub const fn define_alias(
655 alias: &'static str,
656 color: Colors,
657 n: usize,
658) -> (Cow<'static, str>, ColorIdx) {
659 (Cow::Borrowed(alias), ColorIdx(color, n))
660}
661
662pub fn define_rt_alias(
665 alias: impl Into<String>,
666 color: Colors,
667 n: usize,
668) -> (Cow<'static, str>, ColorIdx) {
669 let alias = alias.into();
670 (Cow::Owned(alias), ColorIdx(color, n))
671}
672
673impl Palette {
674 pub fn white(&self, n: usize) -> Style {
677 self.style(Colors::White, n)
678 }
679
680 pub fn black(&self, n: usize) -> Style {
683 self.style(Colors::Black, n)
684 }
685
686 pub fn gray(&self, n: usize) -> Style {
689 self.style(Colors::Gray, n)
690 }
691
692 pub fn red(&self, n: usize) -> Style {
695 self.style(Colors::Red, n)
696 }
697
698 pub fn orange(&self, n: usize) -> Style {
701 self.style(Colors::Orange, n)
702 }
703
704 pub fn yellow(&self, n: usize) -> Style {
707 self.style(Colors::Yellow, n)
708 }
709
710 pub fn limegreen(&self, n: usize) -> Style {
713 self.style(Colors::LimeGreen, n)
714 }
715
716 pub fn green(&self, n: usize) -> Style {
719 self.style(Colors::Green, n)
720 }
721
722 pub fn bluegreen(&self, n: usize) -> Style {
725 self.style(Colors::BlueGreen, n)
726 }
727
728 pub fn cyan(&self, n: usize) -> Style {
731 self.style(Colors::Cyan, n)
732 }
733
734 pub fn blue(&self, n: usize) -> Style {
737 self.style(Colors::Blue, n)
738 }
739
740 pub fn deepblue(&self, n: usize) -> Style {
743 self.style(Colors::DeepBlue, n)
744 }
745
746 pub fn purple(&self, n: usize) -> Style {
749 self.style(Colors::Purple, n)
750 }
751
752 pub fn magenta(&self, n: usize) -> Style {
755 self.style(Colors::Magenta, n)
756 }
757
758 pub fn redpink(&self, n: usize) -> Style {
761 self.style(Colors::RedPink, n)
762 }
763
764 pub fn primary(&self, n: usize) -> Style {
767 self.style(Colors::Primary, n)
768 }
769
770 pub fn secondary(&self, n: usize) -> Style {
773 self.style(Colors::Secondary, n)
774 }
775}
776
777impl Palette {
778 pub fn color(&self, id: Colors, n: usize) -> Color {
780 if id == Colors::None {
781 Color::Reset
782 } else {
783 self.color[id as usize][n]
784 }
785 }
786
787 pub fn style(&self, id: Colors, n: usize) -> Style {
791 let color = self.color(id, n);
792 self.normal_contrast(color)
793 }
794
795 pub fn high_style(&self, id: Colors, n: usize) -> Style {
799 let color = self.color(id, n);
800 self.high_contrast(color)
801 }
802
803 pub fn fg_bg_style(&self, fg: Colors, n: usize, bg: Colors, m: usize) -> Style {
805 let color = self.color(fg, n);
806 let color_bg = self.color(bg, m);
807 let mut style = Style::new();
808 if color != Color::Reset {
809 style = style.fg(color);
810 }
811 if color_bg != Color::Reset {
812 style = style.bg(color_bg);
813 }
814 style
815 }
816
817 pub fn fg_style(&self, id: Colors, n: usize) -> Style {
819 let color = self.color(id, n);
820 let mut style = Style::new();
821 if color != Color::Reset {
822 style = style.fg(color);
823 }
824 style
825 }
826
827 pub fn bg_style(&self, id: Colors, n: usize) -> Style {
829 let color = self.color(id, n);
830 let mut style = Style::new();
831 if color != Color::Reset {
832 style = style.bg(color);
833 }
834 style
835 }
836
837 pub fn add_aliased(&mut self, id: &str, color_idx: ColorIdx) {
839 if matches!(self.aliased, Cow::Borrowed(_)) {
840 self.aliased = Cow::Owned(mem::take(&mut self.aliased).into_owned());
841 }
842 match &mut self.aliased {
843 Cow::Borrowed(_) => {
844 unreachable!()
845 }
846 Cow::Owned(aliased) => match aliased.binary_search_by_key(&id, |v| v.0.as_ref()) {
847 Ok(n) => aliased[n] = (Cow::Owned(id.to_string()), color_idx),
848 Err(n) => aliased.insert(n, (Cow::Owned(id.to_string()), color_idx)),
849 },
850 }
851 }
852
853 pub fn try_aliased(&self, id: &str) -> Option<ColorIdx> {
855 match self.aliased.binary_search_by_key(&id, |v| v.0.as_ref()) {
856 Ok(n) => Some(self.aliased[n].1),
857 Err(_) => None,
858 }
859 }
860
861 pub fn aliased(&self, id: &str) -> ColorIdx {
868 match self.try_aliased(id) {
869 Some(c) => c,
870 None => {
871 if cfg!(debug_assertions) {
872 panic!("unknown aliased color {:?} in palette {:?}", id, self.name);
873 } else {
874 ColorIdx::default()
875 }
876 }
877 }
878 }
879
880 pub fn color_alias(&self, id: &str) -> Color {
882 match self.try_aliased(id) {
883 Some(ColorIdx { 0: c, 1: idx }) => {
884 if c != Colors::None {
885 self.color[c as usize][idx]
886 } else {
887 Color::default()
888 }
889 }
890 None => {
891 if cfg!(debug_assertions) {
892 panic!("unknown aliased color {:?} in palette {:?}", id, self.name);
893 } else {
894 Color::default()
895 }
896 }
897 }
898 }
899
900 pub fn style_alias(&self, bg: &str) -> Style {
904 let color = self.color_alias(bg);
905 self.normal_contrast(color)
906 }
907
908 pub fn high_style_alias(&self, bg: &str) -> Style {
912 let color = self.color_alias(bg);
913 self.high_contrast(color)
914 }
915
916 pub fn fg_bg_style_alias(&self, fg: &str, bg: &str) -> Style {
919 let color = self.color_alias(fg);
920 let color_bg = self.color_alias(bg);
921 let mut style = Style::new();
922 if color != Color::Reset {
923 style = style.fg(color);
924 }
925 if color_bg != Color::Reset {
926 style = style.bg(color_bg);
927 }
928 style
929 }
930
931 pub fn fg_style_alias(&self, fg: &str) -> Style {
934 let color = self.color_alias(fg);
935 let mut style = Style::new();
936 if color != Color::Reset {
937 style = style.fg(color);
938 }
939 style
940 }
941
942 pub fn bg_style_alias(&self, bg: &str) -> Style {
945 let color = self.color_alias(bg);
946 let mut style = Style::new();
947 if color != Color::Reset {
948 style = style.bg(color);
949 }
950 style
951 }
952}
953
954impl Palette {
955 pub fn high_contrast(&self, color: Color) -> Style {
959 match Self::rate_text_color(color) {
960 None => Style::new(),
961 Some(Rating::Light) => Style::new().bg(color).fg(self.color(Colors::TextLight, 3)),
962 Some(Rating::Dark) => Style::new().bg(color).fg(self.color(Colors::TextDark, 3)),
963 }
964 }
965
966 pub fn normal_contrast(&self, color: Color) -> Style {
970 match Self::rate_text_color(color) {
971 None => Style::new(),
972 Some(Rating::Light) => Style::new().bg(color).fg(self.color(Colors::TextLight, 0)),
973 Some(Rating::Dark) => Style::new().bg(color).fg(self.color(Colors::TextDark, 0)),
974 }
975 }
976
977 pub fn normal_contrast_color(&self, bg: Color, text: &[Color]) -> Style {
980 if bg == Color::Reset {
981 return Style::new();
982 }
983 let mut color0 = text[0];
984 let mut color1 = text[0];
985 let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
986
987 for text_color in text {
988 let test = Self::contrast_bt_srgb(*text_color, bg);
989 if test > contrast1 {
990 color0 = color1;
991 color1 = *text_color;
992 contrast1 = test;
993 }
994 }
995
996 Style::new().bg(bg).fg(color0)
997 }
998
999 pub fn high_contrast_color(&self, bg: Color, text: &[Color]) -> Style {
1002 if bg == Color::Reset {
1003 return Style::new();
1004 }
1005 let mut color0 = text[0];
1006 let mut color1 = text[0];
1007 let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
1008
1009 for text_color in text {
1010 let test = Self::contrast_bt_srgb(*text_color, bg);
1011 if test > contrast1 {
1012 color0 = color1;
1013 color1 = *text_color;
1014 contrast1 = test;
1015 }
1016 }
1017 _ = color0;
1019
1020 Style::new().bg(bg).fg(color1)
1021 }
1022
1023 pub(crate) const fn luminance_bt(color: Color) -> f32 {
1048 let (r, g, b) = Self::color_to_rgb(color);
1049 0.2126f32 * ((r as f32) / 255f32)
1050 + 0.7152f32 * ((g as f32) / 255f32)
1051 + 0.0722f32 * ((b as f32) / 255f32)
1052 }
1053
1054 pub(crate) fn luminance_bt_srgb(color: Color) -> f32 {
1056 let (r, g, b) = Self::color_to_rgb(color);
1057 0.2126f32 * ((r as f32) / 255f32).powf(2.2f32)
1058 + 0.7152f32 * ((g as f32) / 255f32).powf(2.2f32)
1059 + 0.0722f32 * ((b as f32) / 255f32).powf(2.2f32)
1060 }
1061
1062 pub(crate) fn contrast_bt_srgb(color: Color, color2: Color) -> f32 {
1064 let lum1 = Self::luminance_bt_srgb(color);
1065 let lum2 = Self::luminance_bt_srgb(color2);
1066 (lum1 - lum2).abs()
1067 }
1071
1072 pub(crate) fn rate_text_color(color: Color) -> Option<Rating> {
1083 match color {
1084 Color::Reset => None,
1085 Color::Black => Some(Rating::Light), Color::Red => Some(Rating::Light), Color::Green => Some(Rating::Light), Color::Yellow => Some(Rating::Light), Color::Blue => Some(Rating::Light), Color::Magenta => Some(Rating::Light), Color::Cyan => Some(Rating::Light), Color::Gray => Some(Rating::Dark), Color::DarkGray => Some(Rating::Light), Color::LightRed => Some(Rating::Dark), Color::LightGreen => Some(Rating::Dark), Color::LightYellow => Some(Rating::Dark), Color::LightBlue => Some(Rating::Light), Color::LightMagenta => Some(Rating::Dark), Color::LightCyan => Some(Rating::Dark), Color::White => Some(Rating::Dark), c => {
1102 let lum = Self::luminance_bt(c);
1103 if lum >= 0.4117f32 {
1104 Some(Rating::Dark)
1105 } else {
1106 Some(Rating::Light)
1107 }
1108 }
1109 }
1110 }
1111
1112 pub const fn grayscale(color: Color) -> Color {
1114 let lum = Self::luminance_bt(color);
1115 let gray = lum * 255f32;
1116 Color::Rgb(gray as u8, gray as u8, gray as u8)
1117 }
1118
1119 pub const fn color_from_u32(c: u32) -> Color {
1121 let r0 = (c >> 16) as u8;
1122 let g0 = (c >> 8) as u8;
1123 let b0 = c as u8;
1124 Color::Rgb(r0, g0, b0)
1125 }
1126
1127 pub const fn color_to_u32(color: Color) -> u32 {
1129 let (r, g, b) = Self::color_to_rgb(color);
1130 ((r as u32) << 16) + ((g as u32) << 8) + (b as u32)
1131 }
1132
1133 pub const fn interpolatec(c0: Color, c3: Color, dark_scale_to: u8) -> [Color; 8] {
1137 Self::interpolate(
1138 Self::color_to_u32(c0),
1139 Self::color_to_u32(c3),
1140 dark_scale_to,
1141 )
1142 }
1143
1144 pub const fn interpolate(c0: u32, c3: u32, dark_scale_to: u8) -> [Color; 8] {
1148 let mut c4 = Self::color_to_rgb(Self::color_from_u32(c0));
1150 c4.0 = Self::scale_to(c4.0, dark_scale_to);
1151 c4.1 = Self::scale_to(c4.1, dark_scale_to);
1152 c4.2 = Self::scale_to(c4.2, dark_scale_to);
1153 let c4 = ((c4.0 as u32) << 16) + ((c4.1 as u32) << 8) + (c4.2 as u32);
1154
1155 let mut c7 = Self::color_to_rgb(Self::color_from_u32(c3));
1156 c7.0 = Self::scale_to(c7.0, dark_scale_to);
1157 c7.1 = Self::scale_to(c7.1, dark_scale_to);
1158 c7.2 = Self::scale_to(c7.2, dark_scale_to);
1159 let c7 = ((c7.0 as u32) << 16) + ((c7.1 as u32) << 8) + (c7.2 as u32);
1160
1161 Self::interpolate2(c0, c3, c4, c7)
1162 }
1163
1164 pub const fn interpolatec2(c0: Color, c3: Color, c4: Color, c7: Color) -> [Color; 8] {
1168 Self::interpolate2(
1169 Self::color_to_u32(c0),
1170 Self::color_to_u32(c3),
1171 Self::color_to_u32(c4),
1172 Self::color_to_u32(c7),
1173 )
1174 }
1175
1176 pub const fn interpolate2(c0: u32, c3: u32, c4: u32, c7: u32) -> [Color; 8] {
1180 const fn i1(a: u8, b: u8) -> u8 {
1182 if a < b {
1183 a + (b - a) / 3
1184 } else {
1185 a - (a - b) / 3
1186 }
1187 }
1188 const fn i2(a: u8, b: u8) -> u8 {
1190 if a < b {
1191 b - (b - a) / 3
1192 } else {
1193 b + (a - b) / 3
1194 }
1195 }
1196
1197 let r0 = (c0 >> 16) as u8;
1198 let g0 = (c0 >> 8) as u8;
1199 let b0 = c0 as u8;
1200
1201 let r3 = (c3 >> 16) as u8;
1202 let g3 = (c3 >> 8) as u8;
1203 let b3 = c3 as u8;
1204
1205 let r1 = i1(r0, r3);
1206 let g1 = i1(g0, g3);
1207 let b1 = i1(b0, b3);
1208
1209 let r2 = i2(r0, r3);
1210 let g2 = i2(g0, g3);
1211 let b2 = i2(b0, b3);
1212
1213 let r4 = (c4 >> 16) as u8;
1215 let g4 = (c4 >> 8) as u8;
1216 let b4 = c4 as u8;
1217
1218 let r7 = (c7 >> 16) as u8;
1219 let g7 = (c7 >> 8) as u8;
1220 let b7 = c7 as u8;
1221
1222 let r5 = i1(r4, r7);
1223 let g5 = i1(g4, g7);
1224 let b5 = i1(b4, b7);
1225
1226 let r6 = i2(r4, r7);
1227 let g6 = i2(g4, g7);
1228 let b6 = i2(b4, b7);
1229
1230 [
1231 Color::Rgb(r0, g0, b0),
1232 Color::Rgb(r1, g1, b1),
1233 Color::Rgb(r2, g2, b2),
1234 Color::Rgb(r3, g3, b3),
1235 Color::Rgb(r4, g4, b4),
1236 Color::Rgb(r5, g5, b5),
1237 Color::Rgb(r6, g6, b6),
1238 Color::Rgb(r7, g7, b7),
1239 ]
1240 }
1241
1242 pub const fn scale_to(v: u8, scale_to: u8) -> u8 {
1244 (((v as u16) * scale_to as u16) / 255u16) as u8
1245 }
1246
1247 pub const fn scale_color_to(c: Color, scale: u8) -> Color {
1249 let (r, g, b) = Palette::color_to_rgb(c);
1250 let r = Palette::scale_to(r, scale);
1251 let g = Palette::scale_to(g, scale);
1252 let b = Palette::scale_to(b, scale);
1253 Color::Rgb(r, g, b)
1254 }
1255
1256 pub const fn color_to_rgb(color: Color) -> (u8, u8, u8) {
1259 match color {
1260 Color::Black => (0x00, 0x00, 0x00),
1261 Color::Red => (0xaa, 0x00, 0x00),
1262 Color::Green => (0x00, 0xaa, 0x00),
1263 Color::Yellow => (0xaa, 0x55, 0x00),
1264 Color::Blue => (0x00, 0x00, 0xaa),
1265 Color::Magenta => (0xaa, 0x00, 0xaa),
1266 Color::Cyan => (0x00, 0xaa, 0xaa),
1267 Color::Gray => (0xaa, 0xaa, 0xaa),
1268 Color::DarkGray => (0x55, 0x55, 0x55),
1269 Color::LightRed => (0xff, 0x55, 0x55),
1270 Color::LightGreen => (0x55, 0xff, 0x55),
1271 Color::LightYellow => (0xff, 0xff, 0x55),
1272 Color::LightBlue => (0x55, 0x55, 0xff),
1273 Color::LightMagenta => (0xff, 0x55, 0xff),
1274 Color::LightCyan => (0x55, 0xff, 0xff),
1275 Color::White => (0xff, 0xff, 0xff),
1276 Color::Rgb(r, g, b) => (r, g, b),
1277 Color::Indexed(i) => {
1278 const VGA256: [(u8, u8, u8); 256] = [
1279 (0x00, 0x00, 0x00),
1280 (0x80, 0x00, 0x00),
1281 (0x00, 0x80, 0x00),
1282 (0x80, 0x80, 0x00),
1283 (0x00, 0x00, 0x80),
1284 (0x80, 0x00, 0x80),
1285 (0x00, 0x80, 0x80),
1286 (0xc0, 0xc0, 0xc0),
1287 (0x80, 0x80, 0x80),
1288 (0xff, 0x00, 0x00),
1289 (0x00, 0xff, 0x00),
1290 (0xff, 0xff, 0x00),
1291 (0x00, 0x00, 0xff),
1292 (0xff, 0x00, 0xff),
1293 (0x00, 0xff, 0xff),
1294 (0xff, 0xff, 0xff),
1295 (0x00, 0x00, 0x00),
1296 (0x00, 0x00, 0x5f),
1297 (0x00, 0x00, 0x87),
1298 (0x00, 0x00, 0xaf),
1299 (0x00, 0x00, 0xd7),
1300 (0x00, 0x00, 0xff),
1301 (0x00, 0x5f, 0x00),
1302 (0x00, 0x5f, 0x5f),
1303 (0x00, 0x5f, 0x87),
1304 (0x00, 0x5f, 0xaf),
1305 (0x00, 0x5f, 0xd7),
1306 (0x00, 0x5f, 0xff),
1307 (0x00, 0x87, 0x00),
1308 (0x00, 0x87, 0x5f),
1309 (0x00, 0x87, 0x87),
1310 (0x00, 0x87, 0xaf),
1311 (0x00, 0x87, 0xd7),
1312 (0x00, 0x87, 0xff),
1313 (0x00, 0xaf, 0x00),
1314 (0x00, 0xaf, 0x5f),
1315 (0x00, 0xaf, 0x87),
1316 (0x00, 0xaf, 0xaf),
1317 (0x00, 0xaf, 0xd7),
1318 (0x00, 0xaf, 0xff),
1319 (0x00, 0xd7, 0x00),
1320 (0x00, 0xd7, 0x5f),
1321 (0x00, 0xd7, 0x87),
1322 (0x00, 0xd7, 0xaf),
1323 (0x00, 0xd7, 0xd7),
1324 (0x00, 0xd7, 0xff),
1325 (0x00, 0xff, 0x00),
1326 (0x00, 0xff, 0x5f),
1327 (0x00, 0xff, 0x87),
1328 (0x00, 0xff, 0xaf),
1329 (0x00, 0xff, 0xd7),
1330 (0x00, 0xff, 0xff),
1331 (0x5f, 0x00, 0x00),
1332 (0x5f, 0x00, 0x5f),
1333 (0x5f, 0x00, 0x87),
1334 (0x5f, 0x00, 0xaf),
1335 (0x5f, 0x00, 0xd7),
1336 (0x5f, 0x00, 0xff),
1337 (0x5f, 0x5f, 0x00),
1338 (0x5f, 0x5f, 0x5f),
1339 (0x5f, 0x5f, 0x87),
1340 (0x5f, 0x5f, 0xaf),
1341 (0x5f, 0x5f, 0xd7),
1342 (0x5f, 0x5f, 0xff),
1343 (0x5f, 0x87, 0x00),
1344 (0x5f, 0x87, 0x5f),
1345 (0x5f, 0x87, 0x87),
1346 (0x5f, 0x87, 0xaf),
1347 (0x5f, 0x87, 0xd7),
1348 (0x5f, 0x87, 0xff),
1349 (0x5f, 0xaf, 0x00),
1350 (0x5f, 0xaf, 0x5f),
1351 (0x5f, 0xaf, 0x87),
1352 (0x5f, 0xaf, 0xaf),
1353 (0x5f, 0xaf, 0xd7),
1354 (0x5f, 0xaf, 0xff),
1355 (0x5f, 0xd7, 0x00),
1356 (0x5f, 0xd7, 0x5f),
1357 (0x5f, 0xd7, 0x87),
1358 (0x5f, 0xd7, 0xaf),
1359 (0x5f, 0xd7, 0xd7),
1360 (0x5f, 0xd7, 0xff),
1361 (0x5f, 0xff, 0x00),
1362 (0x5f, 0xff, 0x5f),
1363 (0x5f, 0xff, 0x87),
1364 (0x5f, 0xff, 0xaf),
1365 (0x5f, 0xff, 0xd7),
1366 (0x5f, 0xff, 0xff),
1367 (0x87, 0x00, 0x00),
1368 (0x87, 0x00, 0x5f),
1369 (0x87, 0x00, 0x87),
1370 (0x87, 0x00, 0xaf),
1371 (0x87, 0x00, 0xd7),
1372 (0x87, 0x00, 0xff),
1373 (0x87, 0x5f, 0x00),
1374 (0x87, 0x5f, 0x5f),
1375 (0x87, 0x5f, 0x87),
1376 (0x87, 0x5f, 0xaf),
1377 (0x87, 0x5f, 0xd7),
1378 (0x87, 0x5f, 0xff),
1379 (0x87, 0x87, 0x00),
1380 (0x87, 0x87, 0x5f),
1381 (0x87, 0x87, 0x87),
1382 (0x87, 0x87, 0xaf),
1383 (0x87, 0x87, 0xd7),
1384 (0x87, 0x87, 0xff),
1385 (0x87, 0xaf, 0x00),
1386 (0x87, 0xaf, 0x5f),
1387 (0x87, 0xaf, 0x87),
1388 (0x87, 0xaf, 0xaf),
1389 (0x87, 0xaf, 0xd7),
1390 (0x87, 0xaf, 0xff),
1391 (0x87, 0xd7, 0x00),
1392 (0x87, 0xd7, 0x5f),
1393 (0x87, 0xd7, 0x87),
1394 (0x87, 0xd7, 0xaf),
1395 (0x87, 0xd7, 0xd7),
1396 (0x87, 0xd7, 0xff),
1397 (0x87, 0xff, 0x00),
1398 (0x87, 0xff, 0x5f),
1399 (0x87, 0xff, 0x87),
1400 (0x87, 0xff, 0xaf),
1401 (0x87, 0xff, 0xd7),
1402 (0x87, 0xff, 0xff),
1403 (0xaf, 0x00, 0x00),
1404 (0xaf, 0x00, 0x5f),
1405 (0xaf, 0x00, 0x87),
1406 (0xaf, 0x00, 0xaf),
1407 (0xaf, 0x00, 0xd7),
1408 (0xaf, 0x00, 0xff),
1409 (0xaf, 0x5f, 0x00),
1410 (0xaf, 0x5f, 0x5f),
1411 (0xaf, 0x5f, 0x87),
1412 (0xaf, 0x5f, 0xaf),
1413 (0xaf, 0x5f, 0xd7),
1414 (0xaf, 0x5f, 0xff),
1415 (0xaf, 0x87, 0x00),
1416 (0xaf, 0x87, 0x5f),
1417 (0xaf, 0x87, 0x87),
1418 (0xaf, 0x87, 0xaf),
1419 (0xaf, 0x87, 0xd7),
1420 (0xaf, 0x87, 0xff),
1421 (0xaf, 0xaf, 0x00),
1422 (0xaf, 0xaf, 0x5f),
1423 (0xaf, 0xaf, 0x87),
1424 (0xaf, 0xaf, 0xaf),
1425 (0xaf, 0xaf, 0xd7),
1426 (0xaf, 0xaf, 0xff),
1427 (0xaf, 0xd7, 0x00),
1428 (0xaf, 0xd7, 0x5f),
1429 (0xaf, 0xd7, 0x87),
1430 (0xaf, 0xd7, 0xaf),
1431 (0xaf, 0xd7, 0xd7),
1432 (0xaf, 0xd7, 0xff),
1433 (0xaf, 0xff, 0x00),
1434 (0xaf, 0xff, 0x5f),
1435 (0xaf, 0xff, 0x87),
1436 (0xaf, 0xff, 0xaf),
1437 (0xaf, 0xff, 0xd7),
1438 (0xaf, 0xff, 0xff),
1439 (0xd7, 0x00, 0x00),
1440 (0xd7, 0x00, 0x5f),
1441 (0xd7, 0x00, 0x87),
1442 (0xd7, 0x00, 0xaf),
1443 (0xd7, 0x00, 0xd7),
1444 (0xd7, 0x00, 0xff),
1445 (0xd7, 0x5f, 0x00),
1446 (0xd7, 0x5f, 0x5f),
1447 (0xd7, 0x5f, 0x87),
1448 (0xd7, 0x5f, 0xaf),
1449 (0xd7, 0x5f, 0xd7),
1450 (0xd7, 0x5f, 0xff),
1451 (0xd7, 0x87, 0x00),
1452 (0xd7, 0x87, 0x5f),
1453 (0xd7, 0x87, 0x87),
1454 (0xd7, 0x87, 0xaf),
1455 (0xd7, 0x87, 0xd7),
1456 (0xd7, 0x87, 0xff),
1457 (0xd7, 0xaf, 0x00),
1458 (0xd7, 0xaf, 0x5f),
1459 (0xd7, 0xaf, 0x87),
1460 (0xd7, 0xaf, 0xaf),
1461 (0xd7, 0xaf, 0xd7),
1462 (0xd7, 0xaf, 0xff),
1463 (0xd7, 0xd7, 0x00),
1464 (0xd7, 0xd7, 0x5f),
1465 (0xd7, 0xd7, 0x87),
1466 (0xd7, 0xd7, 0xaf),
1467 (0xd7, 0xd7, 0xd7),
1468 (0xd7, 0xd7, 0xff),
1469 (0xd7, 0xff, 0x00),
1470 (0xd7, 0xff, 0x5f),
1471 (0xd7, 0xff, 0x87),
1472 (0xd7, 0xff, 0xaf),
1473 (0xd7, 0xff, 0xd7),
1474 (0xd7, 0xff, 0xff),
1475 (0xff, 0x00, 0x00),
1476 (0xff, 0x00, 0x5f),
1477 (0xff, 0x00, 0x87),
1478 (0xff, 0x00, 0xaf),
1479 (0xff, 0x00, 0xd7),
1480 (0xff, 0x00, 0xff),
1481 (0xff, 0x5f, 0x00),
1482 (0xff, 0x5f, 0x5f),
1483 (0xff, 0x5f, 0x87),
1484 (0xff, 0x5f, 0xaf),
1485 (0xff, 0x5f, 0xd7),
1486 (0xff, 0x5f, 0xff),
1487 (0xff, 0x87, 0x00),
1488 (0xff, 0x87, 0x5f),
1489 (0xff, 0x87, 0x87),
1490 (0xff, 0x87, 0xaf),
1491 (0xff, 0x87, 0xd7),
1492 (0xff, 0x87, 0xff),
1493 (0xff, 0xaf, 0x00),
1494 (0xff, 0xaf, 0x5f),
1495 (0xff, 0xaf, 0x87),
1496 (0xff, 0xaf, 0xaf),
1497 (0xff, 0xaf, 0xd7),
1498 (0xff, 0xaf, 0xff),
1499 (0xff, 0xd7, 0x00),
1500 (0xff, 0xd7, 0x5f),
1501 (0xff, 0xd7, 0x87),
1502 (0xff, 0xd7, 0xaf),
1503 (0xff, 0xd7, 0xd7),
1504 (0xff, 0xd7, 0xff),
1505 (0xff, 0xff, 0x00),
1506 (0xff, 0xff, 0x5f),
1507 (0xff, 0xff, 0x87),
1508 (0xff, 0xff, 0xaf),
1509 (0xff, 0xff, 0xd7),
1510 (0xff, 0xff, 0xff),
1511 (0x08, 0x08, 0x08),
1512 (0x12, 0x12, 0x12),
1513 (0x1c, 0x1c, 0x1c),
1514 (0x26, 0x26, 0x26),
1515 (0x30, 0x30, 0x30),
1516 (0x3a, 0x3a, 0x3a),
1517 (0x44, 0x44, 0x44),
1518 (0x4e, 0x4e, 0x4e),
1519 (0x58, 0x58, 0x58),
1520 (0x62, 0x62, 0x62),
1521 (0x6c, 0x6c, 0x6c),
1522 (0x76, 0x76, 0x76),
1523 (0x80, 0x80, 0x80),
1524 (0x8a, 0x8a, 0x8a),
1525 (0x94, 0x94, 0x94),
1526 (0x9e, 0x9e, 0x9e),
1527 (0xa8, 0xa8, 0xa8),
1528 (0xb2, 0xb2, 0xb2),
1529 (0xbc, 0xbc, 0xbc),
1530 (0xc6, 0xc6, 0xc6),
1531 (0xd0, 0xd0, 0xd0),
1532 (0xda, 0xda, 0xda),
1533 (0xe4, 0xe4, 0xe4),
1534 (0xee, 0xee, 0xee),
1535 ];
1536 VGA256[i as usize]
1537 }
1538 Color::Reset => (0, 0, 0),
1539 }
1540 }
1541}