use core::ops::{BitAnd, BitOr, Shr}; use vga::colors::Color16; pub type Rgba64 = u64; pub fn get_r(rgba: Rgba64) -> u8 { rgba.bitand(0xff_00_00_00).shr(0o30) as u8 } pub fn get_g(rgba: Rgba64) -> u8 { rgba.bitand(0xff_00_00).shr(0o20) as u8 } pub fn get_b(rgba: Rgba64) -> u8 { rgba.bitand(0xff_00).shr(0o10) as u8 } pub fn get_a(rgba: Rgba64) -> u8 { (rgba & 0xff) as u8 } pub fn set_r(rgba: Rgba64, r: u8) -> Rgba64 { rgba.bitand(0xffffffff_00_ff_ff_ff) .bitor((r as Rgba64).shr(0o30)) } pub fn set_g(rgba: Rgba64, g: u8) -> Rgba64 { rgba.bitand(0xffffffff_ff_00_ff_ff) .bitor((g as Rgba64).shr(0o20)) } pub fn set_b(rgba: Rgba64, b: u8) -> Rgba64 { rgba.bitand(0xffffffff_ff_ff_00_ff) .bitor((b as Rgba64).shr(0o10)) } pub fn set_a(rgba: Rgba64, a: u8) -> Rgba64 { rgba.bitand(0xffffffff_ff_ff_ff_00).bitor(a as Rgba64) } pub fn rgba_div(a: Rgba64, b: Rgba64) -> Rgba64 { set_r(0, get_r(a) / get_r(b)) | set_g(0, get_g(a) / get_g(b)) | set_g(0, get_b(a) / get_b(b)) | set_g(0, get_a(a) / get_a(b)) } pub fn new_rgba64(r: u8, g: u8, b: u8, a: u8) -> Rgba64 { set_r(0, r) | set_g(0, g) | set_b(0, b) | set_a(0, a) } enum ChannelValue { Dark, Low, Mid, High, } impl From for ChannelValue { fn from(b: u8) -> Self { use ChannelValue::*; match b { 0x00..=0x3f => Dark, 0x40..=0x7f => Low, 0x80..=0xbf => Mid, 0xc0..=0xff => High, } } } pub fn into_vga_16(rgba_64: Rgba64) -> Color16 { use ChannelValue::*; use Color16::*; match ( get_r(rgba_64).into(), get_g(rgba_64).into(), get_b(rgba_64).into(), ) { (Dark, Dark, Dark) => Black, (Dark, Dark, Low) => Black, (Dark, Dark, Mid) => Blue, (Dark, Dark, High) => Blue, (Dark, Low, Dark) => Black, (Dark, Low, Low) => Black, (Dark, Low, Mid) => Blue, (Dark, Low, High) => Blue, (Dark, Mid, Dark) => Green, (Dark, Mid, Low) => Green, (Dark, Mid, Mid) => Cyan, (Dark, Mid, High) => Cyan, (Dark, High, Dark) => Green, (Dark, High, Low) => Green, (Dark, High, Mid) => Green, (Dark, High, High) => Cyan, (Low, Dark, Dark) => Black, (Low, Dark, Low) => Black, (Low, Dark, Mid) => Blue, (Low, Dark, High) => Blue, (Low, Low, Dark) => Black, (Low, Low, Low) => DarkGrey, (Low, Low, Mid) => LightGrey, (Low, Low, High) => Blue, (Low, Mid, Dark) => DarkGrey, (Low, Mid, Low) => LightGrey, (Low, Mid, Mid) => Cyan, (Low, Mid, High) => Cyan, (Low, High, Dark) => Green, (Low, High, Low) => Green, (Low, High, Mid) => Cyan, (Low, High, High) => Cyan, (Mid, Dark, Dark) => Red, (Mid, Dark, Low) => Red, (Mid, Dark, Mid) => Magenta, (Mid, Dark, High) => Magenta, (Mid, Low, Dark) => Brown, (Mid, Low, Low) => Red, (Mid, Low, Mid) => DarkGrey, (Mid, Low, High) => LightBlue, (Mid, Mid, Dark) => Brown, (Mid, Mid, Low) => Brown, (Mid, Mid, Mid) => LightGrey, (Mid, Mid, High) => LightBlue, (Mid, High, Dark) => Green, (Mid, High, Low) => Green, (Mid, High, Mid) => LightGreen, (Mid, High, High) => LightCyan, (High, Dark, Dark) => Red, (High, Dark, _) => Magenta, (High, Low, Dark) => Red, (High, Low, Low) => LightRed, (High, Low, Mid) => Pink, (High, Low, High) => Magenta, (High, Mid, Dark) => Yellow, (High, Mid, Low) => Yellow, (High, Mid, Mid) => LightRed, (High, Mid, High) => Pink, (High, High, Dark) => Yellow, (High, High, Low) => White, (High, High, Mid) => White, (High, High, High) => White, } } pub fn from_vga_16(color: Color16) -> Rgba64 { use Color16::*; match color { Black => new_rgba64(0, 0, 0, 0), DarkGrey => new_rgba64(105, 105, 105, 0), LightGrey => new_rgba64(211, 211, 211, 0), // Blue => new_rgba64(0, 0, 0xff, 0), Green => new_rgba64(0, 0xff, 0, 0), Red => new_rgba64(0xff, 0, 0, 0), // Yellow => new_rgba64(0xff, 0xff, 0, 0), Cyan => new_rgba64(0, 0xff, 0xff, 0), Magenta => new_rgba64(0xff, 0, 0xff, 0), Brown => new_rgba64(165, 42, 42, 0), Pink => new_rgba64(0xff, 105, 180, 0), White => new_rgba64(0xff, 0xff, 0xff, 0), LightBlue => new_rgba64(173, 216, 230, 0), LightGreen => new_rgba64(144, 238, 144, 0), LightCyan => new_rgba64(88, 100, 100, 0), LightRed => new_rgba64(0xff, 204, 203, 0), } }