use bitflags::bitflags;
use std::fmt;
use std::fmt::Formatter;
bitflags! {
#[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
pub struct EmphasisFlags: u16 {
const EMPHASIZE_RED = 0b00000000_01000000;
const EMPHASIZE_GREEN = 0b00000000_10000000;
const EMPHASIZE_BLUE = 0b00000001_00000000;
}
}
const EMPHASIS_MASK: u16 = 0b00000001_11000000; const HUE_MASK: u8 = 0b00001111; const LUMA_MASK: u8 = 0b00110000; const COLOR_INDEX_MASK: u8 = 0b00111111;
#[derive(Default, PartialEq, Eq, Clone, Copy)]
pub struct Color {
value: u16,
}
impl From<Color> for (u8, EmphasisFlags) {
fn from(value: Color) -> Self {
(value.color_index(), value.emphasis())
}
}
impl From<(u8, EmphasisFlags)> for Color {
fn from(value: (u8, EmphasisFlags)) -> Self {
let color_index = (value.0 & COLOR_INDEX_MASK) as u16;
let emphasis = value.1.bits() & EMPHASIS_MASK;
let value = color_index | emphasis;
Self { value }
}
}
impl fmt::Debug for Color {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"Color({}), hue:{} luma:{}",
self.value,
self.hue(),
self.luma()
)?;
if self.emphasis() != EmphasisFlags::empty() {
write!(
f,
" Emphasis: r:{}, g:{}, b:{}",
self.emphasis().contains(EmphasisFlags::EMPHASIZE_RED),
self.emphasis().contains(EmphasisFlags::EMPHASIZE_GREEN),
self.emphasis().contains(EmphasisFlags::EMPHASIZE_BLUE)
)?;
}
Ok(())
}
}
impl Color {
pub fn new(value: u8, emphasis: EmphasisFlags) -> Self {
(value, emphasis).into()
}
pub fn hue(&self) -> u8 {
self.value as u8 & HUE_MASK
}
pub fn luma(&self) -> u8 {
(self.value as u8 & LUMA_MASK) >> 4
}
pub fn color_index(&self) -> u8 {
self.value as u8 & COLOR_INDEX_MASK
}
pub fn emphasis(&self) -> EmphasisFlags {
EmphasisFlags::from_bits_truncate(self.value & EMPHASIS_MASK)
}
pub fn value(&self) -> u16 {
self.value
}
pub fn set_hue(&mut self, hue: u8) {
debug_assert!(hue < 16);
let not_hue_bits = self.value & !(HUE_MASK as u16);
let hue_bits = (hue & HUE_MASK) as u16;
self.value = not_hue_bits | hue_bits;
}
pub fn set_luma(&mut self, luma: u8) {
debug_assert!(luma < 4);
let not_luma_bits = self.value & !(LUMA_MASK as u16);
let luma_bits = (luma as u16) << 4;
self.value = not_luma_bits | luma_bits;
}
}