use core::ops;
use crate::c;
use crate::color::Color;
use crate::color::Color8;
use crate::color::ColorF;
use crate::color::Color16;
use crate::color::BlendMode;
impl Color<u8> for Color8 {
#[inline(always)]
fn r(&self) -> u8 {
return self.r;
}
#[inline(always)]
fn g(&self) -> u8 {
return self.g;
}
#[inline(always)]
fn b(&self) -> u8 {
return self.b;
}
#[inline(always)]
fn a(&self) -> u8 {
return self.a;
}
#[inline(always)]
fn gray(&self) -> u8 {
unsafe{c::lexlibColorGray(*self)}
}
#[inline(always)]
fn gray_alpha(&self) -> Self {
unsafe{c::lexlibColorGrayAlpha(*self)}
}
#[inline(always)]
fn premultiply(&self) -> Self {
unsafe{c::lexlibColorGrayAlpha(*self)}
}
#[inline(always)]
fn blend(&self, src: Self, mode: BlendMode) -> Self {
unsafe{c::lexlibColorBlend(*self, src, mode as u8)}
}
const MIN: u8 = 0x00;
const MAX: u8 = 0xFF;
const BLACK: Self = Self{r: Self::MIN, g: Self::MIN, b: Self::MIN, a: Self::MAX};
const WHITE: Self = Self{r: Self::MAX, g: Self::MAX, b: Self::MAX, a: Self::MAX};
const RED: Self = Self{r: Self::MAX, g: Self::MIN, b: Self::MIN, a: Self::MAX};
const GREEN: Self = Self{r: Self::MIN, g: Self::MAX, b: Self::MIN, a: Self::MAX};
const BLUE: Self = Self{r: Self::MIN, g: Self::MIN, b: Self::MAX, a: Self::MAX};
const YELLOW: Self = Self{r: Self::MAX, g: Self::MAX, b: Self::MIN, a: Self::MAX};
const MAGENTA: Self = Self{r: Self::MAX, g: Self::MIN, b: Self::MAX, a: Self::MAX};
const CYAN: Self = Self{r: Self::MIN, g: Self::MAX, b: Self::MAX, a: Self::MAX};
}
impl ops::Add for Color8 {
#[inline(always)]
fn add(self, src: Self) -> Self {
unsafe{ c::lexlibColorBlend(self, src, c::LEXLIB_ADD) }
}
type Output = Color8;
}
impl ops::Sub for Color8 {
#[inline(always)]
fn sub(self, src: Self) -> Self {
unsafe{ c::lexlibColorBlend(self, src, c::LEXLIB_SUB) }
}
type Output = Color8;
}
impl ops::Mul for Color8 {
#[inline(always)]
fn mul(self, src: Self) -> Self {
unsafe{ c::lexlibColorBlend(self, src, c::LEXLIB_MUL) }
}
type Output = Color8;
}
impl Color8 {
#[inline(always)]
pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
Self{r,g,b,a}
}
#[inline(always)]
pub const fn new_rgb(r: u8, g: u8, b: u8) -> Self {
Self{r,g,b, a: Self::MAX}
}
#[inline(always)]
pub const fn new_gray(g: u8) -> Self {
Self{r: g, g: g, b: g, a: Self::MAX}
}
#[inline(always)]
pub fn blend(self, src: Self) -> Self {
unsafe{ c::lexlibColorBlend(self, src, c::LEXLIB_BLEND) }
}
#[inline(always)]
pub fn modulate(self, src: Self) -> Self {
unsafe{ c::lexlibColorBlend(self, src, c::LEXLIB_MOD) }
}
}
impl From<Color16> for Color8 {
#[inline(always)]
fn from(color: Color16) -> Self {
Self {
r: (color.r / 257) as u8,
g: (color.g / 257) as u8,
b: (color.b / 257) as u8,
a: (color.a / 257) as u8,
}
}
}
impl From<ColorF> for Color8 {
#[inline(always)]
fn from(color: ColorF) -> Self {
Self {
r: (color.r * Self::MAX as f32).round() as u8,
g: (color.g * Self::MAX as f32).round() as u8,
b: (color.b * Self::MAX as f32).round() as u8,
a: (color.a * Self::MAX as f32).round() as u8,
}
}
}
impl From<[u8; 4]> for Color8 {
#[inline(always)]
fn from(val: [u8; 4]) -> Self {
Self{
r: val[0],
g: val[1],
b: val[2],
a: val[3],
}
}
}
impl From<(u8, u8, u8, u8)> for Color8 {
#[inline(always)]
fn from(val: (u8, u8, u8, u8)) -> Self {
Self{
r: val.0,
g: val.1,
b: val.2,
a: val.3,
}
}
}
#[test]
fn blending(){
let mut color = Color8::new(0x8C, 0x32, 0x95, 0xFF);
color = color + Color8::new(0xE0, 0x2F, 0xF0, 0xCC);
assert_eq!(color.r, 0xFF);
assert_eq!(color.g, 0x57);
assert_eq!(color.b, 0xFF);
assert_eq!(color.a, 0xFF);
let mut color = Color8::new(0x44, 0x20, 0x3A, 0xFF);
color = color * Color8::new(0x00, 0x08, 0x31, 0xCC);
assert_eq!(color.r, 0x0D);
assert_eq!(color.g, 0x07);
assert_eq!(color.b, 0x16);
assert_eq!(color.a, 0xFF);
let mut color = Color8::new(0x03, 0x38, 0x5E, 0xFF);
color = color.modulate(Color8::new(0x58, 0x1A, 0x40, 0xCC));
assert_eq!(color.r, 0x01);
assert_eq!(color.g, 0x05);
assert_eq!(color.b, 0x17);
assert_eq!(color.a, 0xFF);
let mut color = Color8::new(0x8D, 0xCC, 0x6A, 0xFF);
color = color.blend(Color8::new(0x16, 0xEB, 0xB8, 0xCC));
assert_eq!(color.r, 0x2E);
assert_eq!(color.g, 0xE5);
assert_eq!(color.b, 0xA8);
assert_eq!(color.a, 0xFF);
}
#[test]
fn gray(){
assert_eq!(Color8::new(0xFF, 0x00, 0x00, 0xFF).gray(), 0x4C);
assert_eq!(Color8::new(0x00, 0xFF, 0x00, 0xFF).gray(), 0x96);
assert_eq!(Color8::new(0x00, 0x00, 0xFF, 0xFF).gray(), 0x1D);
assert_eq!(Color8::new(0xFF, 0xFF, 0x00, 0xFF).gray(), 0xE2);
assert_eq!(Color8::new(0xFF, 0x00, 0xFF, 0xFF).gray(), 0x69);
assert_eq!(Color8::new(0x00, 0xFF, 0xFF, 0xFF).gray(), 0xB3);
assert_eq!(Color8::new(0xFF, 0xFF, 0xFF, 0xCC).gray(), 0xCC);
assert_eq!(Color8::new(0x36, 0x00, 0xB2, 0xFF).gray(), 0x24);
}