use crate::ImageBrushRef;
use super::{Gradient, ImageBrush};
use color::{AlphaColor, ColorSpace, DynamicColor, OpaqueColor, Srgb};
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Brush<I = ImageBrush, G = Gradient> {
Solid(AlphaColor<Srgb>),
Gradient(G),
Image(I),
}
impl<CS: ColorSpace, I, G> From<AlphaColor<CS>> for Brush<I, G> {
fn from(c: AlphaColor<CS>) -> Self {
Self::Solid(c.convert())
}
}
impl<I, G> From<DynamicColor> for Brush<I, G> {
fn from(c: DynamicColor) -> Self {
Self::Solid(c.to_alpha_color::<Srgb>())
}
}
impl<CS: ColorSpace, I, G> From<OpaqueColor<CS>> for Brush<I, G> {
fn from(c: OpaqueColor<CS>) -> Self {
Self::Solid(c.with_alpha(1.).convert())
}
}
impl<CS: ColorSpace, I, G> From<&AlphaColor<CS>> for Brush<I, G> {
fn from(c: &AlphaColor<CS>) -> Self {
Self::Solid((*c).convert())
}
}
impl<I, G> From<&DynamicColor> for Brush<I, G> {
fn from(c: &DynamicColor) -> Self {
Self::Solid((*c).to_alpha_color::<Srgb>())
}
}
impl<CS: ColorSpace, I, G> From<&OpaqueColor<CS>> for Brush<I, G> {
fn from(c: &OpaqueColor<CS>) -> Self {
Self::Solid((*c).with_alpha(1.).convert())
}
}
impl<I> From<Gradient> for Brush<I, Gradient> {
fn from(g: Gradient) -> Self {
Self::Gradient(g)
}
}
impl<G, D> From<ImageBrush<D>> for Brush<ImageBrush<D>, G> {
fn from(value: ImageBrush<D>) -> Self {
Self::Image(value)
}
}
impl<I, G> Default for Brush<I, G> {
fn default() -> Self {
Self::Solid(AlphaColor::<Srgb>::TRANSPARENT)
}
}
impl Brush {
#[must_use]
pub fn with_alpha(self, alpha: f32) -> Self {
match self {
Self::Solid(color) => color.with_alpha(alpha).into(),
Self::Gradient(gradient) => gradient.with_alpha(alpha).into(),
Self::Image(image) => image.with_alpha(alpha).into(),
}
}
#[must_use]
#[doc(alias = "with_alpha_factor")]
#[track_caller]
pub fn multiply_alpha(self, alpha: f32) -> Self {
debug_assert!(
alpha.is_finite() && alpha >= 0.0,
"A non-finite or negative alpha ({alpha}) is meaningless."
);
if alpha == 1.0 {
self
} else {
match self {
Self::Solid(color) => color.multiply_alpha(alpha).into(),
Self::Gradient(gradient) => gradient.multiply_alpha(alpha).into(),
Self::Image(image) => image.multiply_alpha(alpha).into(),
}
}
}
}
pub type BrushRef<'a> = Brush<ImageBrushRef<'a>, &'a Gradient>;
impl BrushRef<'_> {
#[must_use]
pub fn to_owned(&self) -> Brush {
match self {
Self::Solid(color) => Brush::Solid(*color),
Self::Gradient(gradient) => Brush::Gradient((*gradient).clone()),
Self::Image(image) => Brush::Image(image.to_owned()),
}
}
}
impl<'a> From<&'a Gradient> for BrushRef<'a> {
fn from(gradient: &'a Gradient) -> Self {
Self::Gradient(gradient)
}
}
impl<'a> From<&'a ImageBrush> for BrushRef<'a> {
fn from(image: &'a ImageBrush) -> Self {
Self::Image(image.as_ref())
}
}
impl<'a> From<&'a Brush> for BrushRef<'a> {
fn from(brush: &'a Brush) -> Self {
match brush {
Brush::Solid(color) => Self::Solid(*color),
Brush::Gradient(gradient) => Self::Gradient(gradient),
Brush::Image(image) => Self::Image(image.as_ref()),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub enum Extend {
#[default]
Pad = 0,
Repeat = 1,
Reflect = 2,
}