use crate::{
Color, ColorAlpha, ColorResult, DynamicAlphaState, DynamicColor, DynamicColorAlpha,
DynamicColorSpace, DynamicState, Premultiplied, Separate,
};
use glam::{Vec3, Vec4};
use core::fmt;
pub trait ColorSpace: Default + fmt::Display {
const SPACE: DynamicColorSpace;
type LinearSpace: LinearColorSpace + ConvertFromRaw<Self>;
type ComponentStruct: Clone + Copy + fmt::Display;
}
pub trait LinearColorSpace: ColorSpace {}
pub trait NonlinearColorSpace: ColorSpace {}
pub trait EncodedColorSpace: ColorSpace {
type DecodedSpace: WorkingColorSpace + ConvertFromRaw<Self>;
}
pub trait WorkingColorSpace: ColorSpace {}
pub trait ConvertFromRaw<SrcSpace: ColorSpace>: ColorSpace {
fn src_transform_raw(color: Vec3) -> Vec3;
fn linear_part_raw(color: Vec3) -> Vec3;
fn dst_transform_raw(color: Vec3) -> Vec3;
}
pub trait ConvertToRaw<DstSpace: ColorSpace>: ColorSpace {
fn src_transform_raw(color: Vec3) -> Vec3;
fn linear_part_raw(color: Vec3) -> Vec3;
fn dst_transform_raw(color: Vec3) -> Vec3;
}
impl<SrcSpace: ColorSpace, DstSpace: ConvertFromRaw<SrcSpace>> ConvertToRaw<DstSpace> for SrcSpace {
#[inline]
fn src_transform_raw(color: Vec3) -> Vec3 {
<DstSpace as ConvertFromRaw<SrcSpace>>::src_transform_raw(color)
}
#[inline]
fn linear_part_raw(color: Vec3) -> Vec3 {
<DstSpace as ConvertFromRaw<SrcSpace>>::linear_part_raw(color)
}
#[inline]
fn dst_transform_raw(color: Vec3) -> Vec3 {
<DstSpace as ConvertFromRaw<SrcSpace>>::dst_transform_raw(color)
}
}
pub trait ColorInto<T> {
fn into(self) -> T;
}
pub trait AsU8Array {}
pub trait State: Default + fmt::Display {
const STATE: DynamicState;
}
pub trait AlphaState
where
Self: Default
+ fmt::Display
+ ConvertToAlphaRaw<Separate>
+ ConvertToAlphaRaw<Premultiplied>
+ ConvertFromAlphaRaw<Separate>
+ ConvertFromAlphaRaw<Premultiplied>,
{
const STATE: DynamicAlphaState;
}
pub trait ConvertFromAlphaRaw<SrcAlphaState> {
fn convert_raw(raw: Vec3, alpha: f32) -> Vec3;
}
impl<T> ConvertFromAlphaRaw<T> for T {
#[inline]
fn convert_raw(raw: Vec3, _alpha: f32) -> Vec3 {
raw
}
}
pub trait ConvertToAlphaRaw<DstAlphaState> {
fn convert_raw(raw: Vec3, alpha: f32) -> Vec3;
}
impl<SrcAlpha, DstAlpha: ConvertFromAlphaRaw<SrcAlpha>> ConvertToAlphaRaw<DstAlpha> for SrcAlpha {
fn convert_raw(raw: Vec3, alpha: f32) -> Vec3 {
<DstAlpha as ConvertFromAlphaRaw<SrcAlpha>>::convert_raw(raw, alpha)
}
}
pub trait ColorConversionQuery<SrcSpace: ColorSpace, St: State> {
type DstSpace: ConvertFromRaw<SrcSpace>;
}
impl<SrcSpace, DstSpace, St> ColorConversionQuery<SrcSpace, St> for Color<DstSpace, St>
where
SrcSpace: ColorSpace,
DstSpace: ConvertFromRaw<SrcSpace>,
St: State,
{
type DstSpace = DstSpace;
}
pub trait ColorAlphaConversionQuery<SrcSpace: ColorSpace, SrcAlpha: AlphaState> {
type DstSpace: ConvertFromRaw<SrcSpace>;
type DstAlpha: ConvertFromAlphaRaw<SrcAlpha> + AlphaState;
}
impl<SrcSpace, DstSpc, SrcAlpha, DstAlpha> ColorAlphaConversionQuery<SrcSpace, SrcAlpha>
for ColorAlpha<DstSpc, DstAlpha>
where
SrcSpace: ColorSpace,
DstSpc: ConvertFromRaw<SrcSpace>,
SrcAlpha: AlphaState,
DstAlpha: ConvertFromAlphaRaw<SrcAlpha> + AlphaState,
{
type DstSpace = DstSpc;
type DstAlpha = DstAlpha;
}
pub trait AnyColor {
fn raw(&self) -> Vec3;
fn space(&self) -> DynamicColorSpace;
fn state(&self) -> DynamicState;
fn dynamic(&self) -> DynamicColor {
DynamicColor::new(self.raw(), self.space(), self.state())
}
}
impl<'a> From<&'a dyn AnyColor> for DynamicColor {
fn from(color: &'a dyn AnyColor) -> DynamicColor {
color.dynamic()
}
}
pub trait DynColor {
fn downcast<Spc: ColorSpace, St: State>(&self) -> ColorResult<Color<Spc, St>>;
fn downcast_unchecked<Spc: ColorSpace, St: State>(&self) -> Color<Spc, St>;
}
pub trait AnyColorAlpha {
fn raw(&self) -> Vec4;
fn space(&self) -> DynamicColorSpace;
fn alpha_state(&self) -> DynamicAlphaState;
fn dynamic(&self) -> DynamicColorAlpha {
DynamicColorAlpha::new(self.raw(), self.space(), self.alpha_state())
}
}
pub trait DynColorAlpha {
fn downcast<Spc: ColorSpace, A: AlphaState>(&self) -> ColorResult<ColorAlpha<Spc, A>>;
fn downcast_unchecked<Spc: ColorSpace, A: AlphaState>(&self) -> ColorAlpha<Spc, A>;
}