1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! Color blending and blending equations.
//!
//! Palette offers both OpenGL style blending equations, as well as most of the
//! SVG composition operators (also common in photo manipulation software). The
//! composition operators are all implemented in the
//! [`Blend`](crate::Blend) trait, and ready to use with any appropriate
//! color type:
//!
//! ```
//! use palette::{LinSrgba, Blend};
//!
//! let a = LinSrgba::new(0.2, 0.5, 0.1, 0.8);
//! let b = LinSrgba::new(0.6, 0.3, 0.5, 0.1);
//! let c = a.overlay(b);
//! ```
//!
//! Blending equations can be defined using the
//! [`Equations`](crate::blend::Equations) type, which is then passed to the
//! `blend` function, from the `Blend` trait:
//!
//! ```
//! use palette::{LinSrgba, Blend};
//! use palette::blend::{Equations, Parameter};
//!
//! let blend_mode = Equations::from_parameters(
//!    Parameter::SourceAlpha,
//!    Parameter::OneMinusSourceAlpha
//! );
//!
//! let a = LinSrgba::new(0.2, 0.5, 0.1, 0.8);
//! let b = LinSrgba::new(0.6, 0.3, 0.5, 0.1);
//! let c = a.blend(b, blend_mode);
//! ```
//!
//! Note that blending will use [premultiplied alpha](crate::blend::PreAlpha),
//! which may result in loss of some color information in some cases. One such
//! case is that a completely transparent resultant color will become black.

use crate::float::Float;
use crate::ComponentWise;

pub use self::blend::Blend;
pub use self::equations::{Equation, Equations, Parameter, Parameters};
pub use self::pre_alpha::PreAlpha;

mod blend;
mod equations;
mod pre_alpha;

#[cfg(test)]
mod test;

/// A trait for custom blend functions.
pub trait BlendFunction<C: Blend<Color = C> + ComponentWise>
where
    C::Scalar: Float,
{
    /// Apply this blend function to a pair of colors.
    fn apply_to(
        self,
        source: PreAlpha<C, C::Scalar>,
        destination: PreAlpha<C, C::Scalar>,
    ) -> PreAlpha<C, C::Scalar>;
}

impl<C, F> BlendFunction<C> for F
where
    C: Blend<Color = C> + ComponentWise,
    C::Scalar: Float,
    F: FnOnce(PreAlpha<C, C::Scalar>, PreAlpha<C, C::Scalar>) -> PreAlpha<C, C::Scalar>,
{
    fn apply_to(
        self,
        source: PreAlpha<C, C::Scalar>,
        destination: PreAlpha<C, C::Scalar>,
    ) -> PreAlpha<C, C::Scalar> {
        (self)(source, destination)
    }
}