1#[cfg(feature = "serde")]
22use crate::LoadPaletteErr;
23use ratatui_core::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 normal_bg_style(&self, fg: Colors, bg: Colors, m: usize) -> Style {
806 let colors_fg = &self.color[fg as usize];
807 let color_bg = self.color(bg, m);
808 self.normal_contrast_color(color_bg, colors_fg)
809 }
810
811 pub fn high_bg_style(&self, fg: Colors, bg: Colors, m: usize) -> Style {
814 let colors_fg = &self.color[fg as usize];
815 let color_bg = self.color(bg, m);
816 self.high_contrast_color(color_bg, colors_fg)
817 }
818
819 pub fn fg_bg_style(&self, fg: Colors, n: usize, bg: Colors, m: usize) -> Style {
821 let color = self.color(fg, n);
822 let color_bg = self.color(bg, m);
823 let mut style = Style::new();
824 if color != Color::Reset {
825 style = style.fg(color);
826 }
827 if color_bg != Color::Reset {
828 style = style.bg(color_bg);
829 }
830 style
831 }
832
833 pub fn fg_style(&self, id: Colors, n: usize) -> Style {
835 let color = self.color(id, n);
836 let mut style = Style::new();
837 if color != Color::Reset {
838 style = style.fg(color);
839 }
840 style
841 }
842
843 pub fn bg_style(&self, id: Colors, n: usize) -> Style {
845 let color = self.color(id, n);
846 let mut style = Style::new();
847 if color != Color::Reset {
848 style = style.bg(color);
849 }
850 style
851 }
852
853 pub fn add_aliased(&mut self, id: &str, color_idx: ColorIdx) {
855 if matches!(self.aliased, Cow::Borrowed(_)) {
856 self.aliased = Cow::Owned(mem::take(&mut self.aliased).into_owned());
857 }
858 match &mut self.aliased {
859 Cow::Borrowed(_) => {
860 unreachable!()
861 }
862 Cow::Owned(aliased) => match aliased.binary_search_by_key(&id, |v| v.0.as_ref()) {
863 Ok(n) => aliased[n] = (Cow::Owned(id.to_string()), color_idx),
864 Err(n) => aliased.insert(n, (Cow::Owned(id.to_string()), color_idx)),
865 },
866 }
867 }
868
869 pub fn try_aliased(&self, id: &str) -> Option<ColorIdx> {
871 match self.aliased.binary_search_by_key(&id, |v| v.0.as_ref()) {
872 Ok(n) => Some(self.aliased[n].1),
873 Err(_) => None,
874 }
875 }
876
877 pub fn aliased(&self, id: &str) -> ColorIdx {
884 match self.try_aliased(id) {
885 Some(c) => c,
886 None => {
887 if cfg!(debug_assertions) {
888 panic!("unknown aliased color {:?} in palette {:?}", id, self.name);
889 } else {
890 ColorIdx::default()
891 }
892 }
893 }
894 }
895
896 pub fn color_alias(&self, id: &str) -> Color {
898 match self.try_aliased(id) {
899 Some(ColorIdx { 0: c, 1: idx }) => {
900 if c != Colors::None {
901 self.color[c as usize][idx]
902 } else {
903 Color::default()
904 }
905 }
906 None => {
907 if cfg!(debug_assertions) {
908 panic!("unknown aliased color {:?} in palette {:?}", id, self.name);
909 } else {
910 Color::default()
911 }
912 }
913 }
914 }
915
916 pub fn style_alias(&self, bg: &str) -> Style {
920 let color = self.color_alias(bg);
921 self.normal_contrast(color)
922 }
923
924 pub fn high_style_alias(&self, bg: &str) -> Style {
928 let color = self.color_alias(bg);
929 self.high_contrast(color)
930 }
931
932 pub fn fg_bg_style_alias(&self, fg: &str, bg: &str) -> Style {
935 let color = self.color_alias(fg);
936 let color_bg = self.color_alias(bg);
937 let mut style = Style::new();
938 if color != Color::Reset {
939 style = style.fg(color);
940 }
941 if color_bg != Color::Reset {
942 style = style.bg(color_bg);
943 }
944 style
945 }
946
947 pub fn fg_style_alias(&self, fg: &str) -> Style {
950 let color = self.color_alias(fg);
951 let mut style = Style::new();
952 if color != Color::Reset {
953 style = style.fg(color);
954 }
955 style
956 }
957
958 pub fn bg_style_alias(&self, bg: &str) -> Style {
961 let color = self.color_alias(bg);
962 let mut style = Style::new();
963 if color != Color::Reset {
964 style = style.bg(color);
965 }
966 style
967 }
968}
969
970impl Palette {
971 pub fn high_contrast(&self, color: Color) -> Style {
975 match Self::rate_text_color(color) {
976 None => Style::new(),
977 Some(Rating::Light) => Style::new().bg(color).fg(self.color(Colors::TextLight, 3)),
978 Some(Rating::Dark) => Style::new().bg(color).fg(self.color(Colors::TextDark, 3)),
979 }
980 }
981
982 pub fn normal_contrast(&self, color: Color) -> Style {
986 match Self::rate_text_color(color) {
987 None => Style::new(),
988 Some(Rating::Light) => Style::new().bg(color).fg(self.color(Colors::TextLight, 0)),
989 Some(Rating::Dark) => Style::new().bg(color).fg(self.color(Colors::TextDark, 0)),
990 }
991 }
992
993 pub fn normal_contrast_color(&self, bg: Color, text: &[Color]) -> Style {
996 if bg == Color::Reset {
997 return Style::new();
998 }
999 let mut color0 = text[0];
1000 let mut color1 = text[0];
1001 let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
1002
1003 for text_color in text {
1004 let test = Self::contrast_bt_srgb(*text_color, bg);
1005 if test > contrast1 {
1006 color0 = color1;
1007 color1 = *text_color;
1008 contrast1 = test;
1009 }
1010 }
1011
1012 Style::new().bg(bg).fg(color0)
1013 }
1014
1015 pub fn high_contrast_color(&self, bg: Color, text: &[Color]) -> Style {
1018 if bg == Color::Reset {
1019 return Style::new();
1020 }
1021 let mut color0 = text[0];
1022 let mut color1 = text[0];
1023 let mut contrast1 = Self::contrast_bt_srgb(color1, bg);
1024
1025 for text_color in text {
1026 let test = Self::contrast_bt_srgb(*text_color, bg);
1027 if test > contrast1 {
1028 color0 = color1;
1029 color1 = *text_color;
1030 contrast1 = test;
1031 }
1032 }
1033 _ = color0;
1035
1036 Style::new().bg(bg).fg(color1)
1037 }
1038
1039 pub(crate) const fn luminance_bt(color: Color) -> f32 {
1064 let (r, g, b) = Self::color_to_rgb(color);
1065 0.2126f32 * ((r as f32) / 255f32)
1066 + 0.7152f32 * ((g as f32) / 255f32)
1067 + 0.0722f32 * ((b as f32) / 255f32)
1068 }
1069
1070 pub(crate) fn luminance_bt_srgb(color: Color) -> f32 {
1072 let (r, g, b) = Self::color_to_rgb(color);
1073 0.2126f32 * ((r as f32) / 255f32).powf(2.2f32)
1074 + 0.7152f32 * ((g as f32) / 255f32).powf(2.2f32)
1075 + 0.0722f32 * ((b as f32) / 255f32).powf(2.2f32)
1076 }
1077
1078 pub(crate) fn contrast_bt_srgb(color: Color, color2: Color) -> f32 {
1080 let lum1 = Self::luminance_bt_srgb(color);
1081 let lum2 = Self::luminance_bt_srgb(color2);
1082 (lum1 - lum2).abs()
1083 }
1087
1088 pub(crate) fn rate_text_color(color: Color) -> Option<Rating> {
1099 match color {
1100 Color::Reset => None,
1101 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 => {
1118 let lum = Self::luminance_bt(c);
1119 if lum >= 0.4117f32 {
1120 Some(Rating::Dark)
1121 } else {
1122 Some(Rating::Light)
1123 }
1124 }
1125 }
1126 }
1127
1128 pub const fn grayscale(color: Color) -> Color {
1130 let lum = Self::luminance_bt(color);
1131 let gray = lum * 255f32;
1132 Color::Rgb(gray as u8, gray as u8, gray as u8)
1133 }
1134
1135 pub const fn color_from_u32(c: u32) -> Color {
1137 let r0 = (c >> 16) as u8;
1138 let g0 = (c >> 8) as u8;
1139 let b0 = c as u8;
1140 Color::Rgb(r0, g0, b0)
1141 }
1142
1143 pub const fn color_to_u32(color: Color) -> u32 {
1145 let (r, g, b) = Self::color_to_rgb(color);
1146 ((r as u32) << 16) + ((g as u32) << 8) + (b as u32)
1147 }
1148
1149 pub const fn interpolatec(c0: Color, c3: Color, dark_scale_to: u8) -> [Color; 8] {
1153 Self::interpolate(
1154 Self::color_to_u32(c0),
1155 Self::color_to_u32(c3),
1156 dark_scale_to,
1157 )
1158 }
1159
1160 pub const fn interpolate(c0: u32, c3: u32, dark_scale_to: u8) -> [Color; 8] {
1164 let mut c4 = Self::color_to_rgb(Self::color_from_u32(c0));
1166 c4.0 = Self::scale_to(c4.0, dark_scale_to);
1167 c4.1 = Self::scale_to(c4.1, dark_scale_to);
1168 c4.2 = Self::scale_to(c4.2, dark_scale_to);
1169 let c4 = ((c4.0 as u32) << 16) + ((c4.1 as u32) << 8) + (c4.2 as u32);
1170
1171 let mut c7 = Self::color_to_rgb(Self::color_from_u32(c3));
1172 c7.0 = Self::scale_to(c7.0, dark_scale_to);
1173 c7.1 = Self::scale_to(c7.1, dark_scale_to);
1174 c7.2 = Self::scale_to(c7.2, dark_scale_to);
1175 let c7 = ((c7.0 as u32) << 16) + ((c7.1 as u32) << 8) + (c7.2 as u32);
1176
1177 Self::interpolate2(c0, c3, c4, c7)
1178 }
1179
1180 pub const fn interpolatec2(c0: Color, c3: Color, c4: Color, c7: Color) -> [Color; 8] {
1184 Self::interpolate2(
1185 Self::color_to_u32(c0),
1186 Self::color_to_u32(c3),
1187 Self::color_to_u32(c4),
1188 Self::color_to_u32(c7),
1189 )
1190 }
1191
1192 pub const fn interpolate2(c0: u32, c3: u32, c4: u32, c7: u32) -> [Color; 8] {
1196 const fn i1(a: u8, b: u8) -> u8 {
1198 if a < b {
1199 a + (b - a) / 3
1200 } else {
1201 a - (a - b) / 3
1202 }
1203 }
1204 const fn i2(a: u8, b: u8) -> u8 {
1206 if a < b {
1207 b - (b - a) / 3
1208 } else {
1209 b + (a - b) / 3
1210 }
1211 }
1212
1213 let r0 = (c0 >> 16) as u8;
1214 let g0 = (c0 >> 8) as u8;
1215 let b0 = c0 as u8;
1216
1217 let r3 = (c3 >> 16) as u8;
1218 let g3 = (c3 >> 8) as u8;
1219 let b3 = c3 as u8;
1220
1221 let r1 = i1(r0, r3);
1222 let g1 = i1(g0, g3);
1223 let b1 = i1(b0, b3);
1224
1225 let r2 = i2(r0, r3);
1226 let g2 = i2(g0, g3);
1227 let b2 = i2(b0, b3);
1228
1229 let r4 = (c4 >> 16) as u8;
1231 let g4 = (c4 >> 8) as u8;
1232 let b4 = c4 as u8;
1233
1234 let r7 = (c7 >> 16) as u8;
1235 let g7 = (c7 >> 8) as u8;
1236 let b7 = c7 as u8;
1237
1238 let r5 = i1(r4, r7);
1239 let g5 = i1(g4, g7);
1240 let b5 = i1(b4, b7);
1241
1242 let r6 = i2(r4, r7);
1243 let g6 = i2(g4, g7);
1244 let b6 = i2(b4, b7);
1245
1246 [
1247 Color::Rgb(r0, g0, b0),
1248 Color::Rgb(r1, g1, b1),
1249 Color::Rgb(r2, g2, b2),
1250 Color::Rgb(r3, g3, b3),
1251 Color::Rgb(r4, g4, b4),
1252 Color::Rgb(r5, g5, b5),
1253 Color::Rgb(r6, g6, b6),
1254 Color::Rgb(r7, g7, b7),
1255 ]
1256 }
1257
1258 pub const fn scale_to(v: u8, scale_to: u8) -> u8 {
1260 (((v as u16) * scale_to as u16) / 255u16) as u8
1261 }
1262
1263 pub const fn scale_color_to(c: Color, scale: u8) -> Color {
1265 let (r, g, b) = Palette::color_to_rgb(c);
1266 let r = Palette::scale_to(r, scale);
1267 let g = Palette::scale_to(g, scale);
1268 let b = Palette::scale_to(b, scale);
1269 Color::Rgb(r, g, b)
1270 }
1271
1272 pub const fn color_to_rgb(color: Color) -> (u8, u8, u8) {
1275 match color {
1276 Color::Black => (0x00, 0x00, 0x00),
1277 Color::Red => (0xaa, 0x00, 0x00),
1278 Color::Green => (0x00, 0xaa, 0x00),
1279 Color::Yellow => (0xaa, 0x55, 0x00),
1280 Color::Blue => (0x00, 0x00, 0xaa),
1281 Color::Magenta => (0xaa, 0x00, 0xaa),
1282 Color::Cyan => (0x00, 0xaa, 0xaa),
1283 Color::Gray => (0xaa, 0xaa, 0xaa),
1284 Color::DarkGray => (0x55, 0x55, 0x55),
1285 Color::LightRed => (0xff, 0x55, 0x55),
1286 Color::LightGreen => (0x55, 0xff, 0x55),
1287 Color::LightYellow => (0xff, 0xff, 0x55),
1288 Color::LightBlue => (0x55, 0x55, 0xff),
1289 Color::LightMagenta => (0xff, 0x55, 0xff),
1290 Color::LightCyan => (0x55, 0xff, 0xff),
1291 Color::White => (0xff, 0xff, 0xff),
1292 Color::Rgb(r, g, b) => (r, g, b),
1293 Color::Indexed(i) => {
1294 const VGA256: [(u8, u8, u8); 256] = [
1295 (0x00, 0x00, 0x00),
1296 (0x80, 0x00, 0x00),
1297 (0x00, 0x80, 0x00),
1298 (0x80, 0x80, 0x00),
1299 (0x00, 0x00, 0x80),
1300 (0x80, 0x00, 0x80),
1301 (0x00, 0x80, 0x80),
1302 (0xc0, 0xc0, 0xc0),
1303 (0x80, 0x80, 0x80),
1304 (0xff, 0x00, 0x00),
1305 (0x00, 0xff, 0x00),
1306 (0xff, 0xff, 0x00),
1307 (0x00, 0x00, 0xff),
1308 (0xff, 0x00, 0xff),
1309 (0x00, 0xff, 0xff),
1310 (0xff, 0xff, 0xff),
1311 (0x00, 0x00, 0x00),
1312 (0x00, 0x00, 0x5f),
1313 (0x00, 0x00, 0x87),
1314 (0x00, 0x00, 0xaf),
1315 (0x00, 0x00, 0xd7),
1316 (0x00, 0x00, 0xff),
1317 (0x00, 0x5f, 0x00),
1318 (0x00, 0x5f, 0x5f),
1319 (0x00, 0x5f, 0x87),
1320 (0x00, 0x5f, 0xaf),
1321 (0x00, 0x5f, 0xd7),
1322 (0x00, 0x5f, 0xff),
1323 (0x00, 0x87, 0x00),
1324 (0x00, 0x87, 0x5f),
1325 (0x00, 0x87, 0x87),
1326 (0x00, 0x87, 0xaf),
1327 (0x00, 0x87, 0xd7),
1328 (0x00, 0x87, 0xff),
1329 (0x00, 0xaf, 0x00),
1330 (0x00, 0xaf, 0x5f),
1331 (0x00, 0xaf, 0x87),
1332 (0x00, 0xaf, 0xaf),
1333 (0x00, 0xaf, 0xd7),
1334 (0x00, 0xaf, 0xff),
1335 (0x00, 0xd7, 0x00),
1336 (0x00, 0xd7, 0x5f),
1337 (0x00, 0xd7, 0x87),
1338 (0x00, 0xd7, 0xaf),
1339 (0x00, 0xd7, 0xd7),
1340 (0x00, 0xd7, 0xff),
1341 (0x00, 0xff, 0x00),
1342 (0x00, 0xff, 0x5f),
1343 (0x00, 0xff, 0x87),
1344 (0x00, 0xff, 0xaf),
1345 (0x00, 0xff, 0xd7),
1346 (0x00, 0xff, 0xff),
1347 (0x5f, 0x00, 0x00),
1348 (0x5f, 0x00, 0x5f),
1349 (0x5f, 0x00, 0x87),
1350 (0x5f, 0x00, 0xaf),
1351 (0x5f, 0x00, 0xd7),
1352 (0x5f, 0x00, 0xff),
1353 (0x5f, 0x5f, 0x00),
1354 (0x5f, 0x5f, 0x5f),
1355 (0x5f, 0x5f, 0x87),
1356 (0x5f, 0x5f, 0xaf),
1357 (0x5f, 0x5f, 0xd7),
1358 (0x5f, 0x5f, 0xff),
1359 (0x5f, 0x87, 0x00),
1360 (0x5f, 0x87, 0x5f),
1361 (0x5f, 0x87, 0x87),
1362 (0x5f, 0x87, 0xaf),
1363 (0x5f, 0x87, 0xd7),
1364 (0x5f, 0x87, 0xff),
1365 (0x5f, 0xaf, 0x00),
1366 (0x5f, 0xaf, 0x5f),
1367 (0x5f, 0xaf, 0x87),
1368 (0x5f, 0xaf, 0xaf),
1369 (0x5f, 0xaf, 0xd7),
1370 (0x5f, 0xaf, 0xff),
1371 (0x5f, 0xd7, 0x00),
1372 (0x5f, 0xd7, 0x5f),
1373 (0x5f, 0xd7, 0x87),
1374 (0x5f, 0xd7, 0xaf),
1375 (0x5f, 0xd7, 0xd7),
1376 (0x5f, 0xd7, 0xff),
1377 (0x5f, 0xff, 0x00),
1378 (0x5f, 0xff, 0x5f),
1379 (0x5f, 0xff, 0x87),
1380 (0x5f, 0xff, 0xaf),
1381 (0x5f, 0xff, 0xd7),
1382 (0x5f, 0xff, 0xff),
1383 (0x87, 0x00, 0x00),
1384 (0x87, 0x00, 0x5f),
1385 (0x87, 0x00, 0x87),
1386 (0x87, 0x00, 0xaf),
1387 (0x87, 0x00, 0xd7),
1388 (0x87, 0x00, 0xff),
1389 (0x87, 0x5f, 0x00),
1390 (0x87, 0x5f, 0x5f),
1391 (0x87, 0x5f, 0x87),
1392 (0x87, 0x5f, 0xaf),
1393 (0x87, 0x5f, 0xd7),
1394 (0x87, 0x5f, 0xff),
1395 (0x87, 0x87, 0x00),
1396 (0x87, 0x87, 0x5f),
1397 (0x87, 0x87, 0x87),
1398 (0x87, 0x87, 0xaf),
1399 (0x87, 0x87, 0xd7),
1400 (0x87, 0x87, 0xff),
1401 (0x87, 0xaf, 0x00),
1402 (0x87, 0xaf, 0x5f),
1403 (0x87, 0xaf, 0x87),
1404 (0x87, 0xaf, 0xaf),
1405 (0x87, 0xaf, 0xd7),
1406 (0x87, 0xaf, 0xff),
1407 (0x87, 0xd7, 0x00),
1408 (0x87, 0xd7, 0x5f),
1409 (0x87, 0xd7, 0x87),
1410 (0x87, 0xd7, 0xaf),
1411 (0x87, 0xd7, 0xd7),
1412 (0x87, 0xd7, 0xff),
1413 (0x87, 0xff, 0x00),
1414 (0x87, 0xff, 0x5f),
1415 (0x87, 0xff, 0x87),
1416 (0x87, 0xff, 0xaf),
1417 (0x87, 0xff, 0xd7),
1418 (0x87, 0xff, 0xff),
1419 (0xaf, 0x00, 0x00),
1420 (0xaf, 0x00, 0x5f),
1421 (0xaf, 0x00, 0x87),
1422 (0xaf, 0x00, 0xaf),
1423 (0xaf, 0x00, 0xd7),
1424 (0xaf, 0x00, 0xff),
1425 (0xaf, 0x5f, 0x00),
1426 (0xaf, 0x5f, 0x5f),
1427 (0xaf, 0x5f, 0x87),
1428 (0xaf, 0x5f, 0xaf),
1429 (0xaf, 0x5f, 0xd7),
1430 (0xaf, 0x5f, 0xff),
1431 (0xaf, 0x87, 0x00),
1432 (0xaf, 0x87, 0x5f),
1433 (0xaf, 0x87, 0x87),
1434 (0xaf, 0x87, 0xaf),
1435 (0xaf, 0x87, 0xd7),
1436 (0xaf, 0x87, 0xff),
1437 (0xaf, 0xaf, 0x00),
1438 (0xaf, 0xaf, 0x5f),
1439 (0xaf, 0xaf, 0x87),
1440 (0xaf, 0xaf, 0xaf),
1441 (0xaf, 0xaf, 0xd7),
1442 (0xaf, 0xaf, 0xff),
1443 (0xaf, 0xd7, 0x00),
1444 (0xaf, 0xd7, 0x5f),
1445 (0xaf, 0xd7, 0x87),
1446 (0xaf, 0xd7, 0xaf),
1447 (0xaf, 0xd7, 0xd7),
1448 (0xaf, 0xd7, 0xff),
1449 (0xaf, 0xff, 0x00),
1450 (0xaf, 0xff, 0x5f),
1451 (0xaf, 0xff, 0x87),
1452 (0xaf, 0xff, 0xaf),
1453 (0xaf, 0xff, 0xd7),
1454 (0xaf, 0xff, 0xff),
1455 (0xd7, 0x00, 0x00),
1456 (0xd7, 0x00, 0x5f),
1457 (0xd7, 0x00, 0x87),
1458 (0xd7, 0x00, 0xaf),
1459 (0xd7, 0x00, 0xd7),
1460 (0xd7, 0x00, 0xff),
1461 (0xd7, 0x5f, 0x00),
1462 (0xd7, 0x5f, 0x5f),
1463 (0xd7, 0x5f, 0x87),
1464 (0xd7, 0x5f, 0xaf),
1465 (0xd7, 0x5f, 0xd7),
1466 (0xd7, 0x5f, 0xff),
1467 (0xd7, 0x87, 0x00),
1468 (0xd7, 0x87, 0x5f),
1469 (0xd7, 0x87, 0x87),
1470 (0xd7, 0x87, 0xaf),
1471 (0xd7, 0x87, 0xd7),
1472 (0xd7, 0x87, 0xff),
1473 (0xd7, 0xaf, 0x00),
1474 (0xd7, 0xaf, 0x5f),
1475 (0xd7, 0xaf, 0x87),
1476 (0xd7, 0xaf, 0xaf),
1477 (0xd7, 0xaf, 0xd7),
1478 (0xd7, 0xaf, 0xff),
1479 (0xd7, 0xd7, 0x00),
1480 (0xd7, 0xd7, 0x5f),
1481 (0xd7, 0xd7, 0x87),
1482 (0xd7, 0xd7, 0xaf),
1483 (0xd7, 0xd7, 0xd7),
1484 (0xd7, 0xd7, 0xff),
1485 (0xd7, 0xff, 0x00),
1486 (0xd7, 0xff, 0x5f),
1487 (0xd7, 0xff, 0x87),
1488 (0xd7, 0xff, 0xaf),
1489 (0xd7, 0xff, 0xd7),
1490 (0xd7, 0xff, 0xff),
1491 (0xff, 0x00, 0x00),
1492 (0xff, 0x00, 0x5f),
1493 (0xff, 0x00, 0x87),
1494 (0xff, 0x00, 0xaf),
1495 (0xff, 0x00, 0xd7),
1496 (0xff, 0x00, 0xff),
1497 (0xff, 0x5f, 0x00),
1498 (0xff, 0x5f, 0x5f),
1499 (0xff, 0x5f, 0x87),
1500 (0xff, 0x5f, 0xaf),
1501 (0xff, 0x5f, 0xd7),
1502 (0xff, 0x5f, 0xff),
1503 (0xff, 0x87, 0x00),
1504 (0xff, 0x87, 0x5f),
1505 (0xff, 0x87, 0x87),
1506 (0xff, 0x87, 0xaf),
1507 (0xff, 0x87, 0xd7),
1508 (0xff, 0x87, 0xff),
1509 (0xff, 0xaf, 0x00),
1510 (0xff, 0xaf, 0x5f),
1511 (0xff, 0xaf, 0x87),
1512 (0xff, 0xaf, 0xaf),
1513 (0xff, 0xaf, 0xd7),
1514 (0xff, 0xaf, 0xff),
1515 (0xff, 0xd7, 0x00),
1516 (0xff, 0xd7, 0x5f),
1517 (0xff, 0xd7, 0x87),
1518 (0xff, 0xd7, 0xaf),
1519 (0xff, 0xd7, 0xd7),
1520 (0xff, 0xd7, 0xff),
1521 (0xff, 0xff, 0x00),
1522 (0xff, 0xff, 0x5f),
1523 (0xff, 0xff, 0x87),
1524 (0xff, 0xff, 0xaf),
1525 (0xff, 0xff, 0xd7),
1526 (0xff, 0xff, 0xff),
1527 (0x08, 0x08, 0x08),
1528 (0x12, 0x12, 0x12),
1529 (0x1c, 0x1c, 0x1c),
1530 (0x26, 0x26, 0x26),
1531 (0x30, 0x30, 0x30),
1532 (0x3a, 0x3a, 0x3a),
1533 (0x44, 0x44, 0x44),
1534 (0x4e, 0x4e, 0x4e),
1535 (0x58, 0x58, 0x58),
1536 (0x62, 0x62, 0x62),
1537 (0x6c, 0x6c, 0x6c),
1538 (0x76, 0x76, 0x76),
1539 (0x80, 0x80, 0x80),
1540 (0x8a, 0x8a, 0x8a),
1541 (0x94, 0x94, 0x94),
1542 (0x9e, 0x9e, 0x9e),
1543 (0xa8, 0xa8, 0xa8),
1544 (0xb2, 0xb2, 0xb2),
1545 (0xbc, 0xbc, 0xbc),
1546 (0xc6, 0xc6, 0xc6),
1547 (0xd0, 0xd0, 0xd0),
1548 (0xda, 0xda, 0xda),
1549 (0xe4, 0xe4, 0xe4),
1550 (0xee, 0xee, 0xee),
1551 ];
1552 VGA256[i as usize]
1553 }
1554 Color::Reset => (0, 0, 0),
1555 }
1556 }
1557}