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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use cssparser::Parser;
use crate::layout::style::tw::TailwindPropertyParser;
use crate::layout::style::{
Animatable, CssToken, FromCss, ListInterpolationStrategy, ParseResult, declare_enum_from_css_impl,
};
/// A list of blend modes.
pub type BlendModes = Box<[BlendMode]>;
impl<'i> FromCss<'i> for BlendModes {
fn from_css(input: &mut Parser<'i, '_>) -> ParseResult<'i, Self> {
let mut values = Vec::new();
values.push(BlendMode::from_css(input)?);
while input.expect_comma().is_ok() {
values.push(BlendMode::from_css(input)?);
}
Ok(values.into_boxed_slice())
}
fn valid_tokens() -> &'static [CssToken] {
BlendMode::valid_tokens()
}
}
/// Defines the blending mode for an element.
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum BlendMode {
/// The final color is the top color, regardless of what the bottom color is.
#[default]
Normal,
/// The final color is the result of multiplying the top and bottom colors.
Multiply,
/// The final color is the result of inverting the colors, multiplying them, and inverting that value.
Screen,
/// The final color is the result of multiply if the bottom color is darker, or screen if the bottom color is lighter.
Overlay,
/// The final color is composed of the darkest values of each color channel.
Darken,
/// The final color is composed of the lightest values of each color channel.
Lighten,
/// The final color is the result of dividing the bottom color by the inverse of the top color.
ColorDodge,
/// The final color is the result of inverting the bottom color, dividing the value by the top color, and inverting that value.
ColorBurn,
/// The final color is the result of multiply if the top color is darker, or screen if the top color is lighter.
HardLight,
/// The final color is similar to hard-light, but softer.
SoftLight,
/// The final color is the result of subtracting the darker of the two colors from the lighter one.
Difference,
/// The final color is similar to difference, but with less contrast.
Exclusion,
/// The final color has the hue of the top color, while using the saturation and luminosity of the bottom color.
Hue,
/// The final color has the saturation of the top color, while using the hue and luminosity of the bottom color.
Saturation,
/// The final color has the hue and saturation of the top color, while using the luminosity of the bottom color.
Color,
/// The final color has the luminosity of the top color, while using the hue and saturation of the bottom color.
Luminosity,
/// The final color is the result of adding the source and backdrop colors, clamped to maximum.
PlusLighter,
/// The final color is the result of adding the source and backdrop colors, clamped to minimum.
PlusDarker,
}
declare_enum_from_css_impl!(
BlendMode,
"normal" => BlendMode::Normal,
"multiply" => BlendMode::Multiply,
"screen" => BlendMode::Screen,
"overlay" => BlendMode::Overlay,
"darken" => BlendMode::Darken,
"lighten" => BlendMode::Lighten,
"color-dodge" => BlendMode::ColorDodge,
"color-burn" => BlendMode::ColorBurn,
"hard-light" => BlendMode::HardLight,
"soft-light" => BlendMode::SoftLight,
"difference" => BlendMode::Difference,
"exclusion" => BlendMode::Exclusion,
"hue" => BlendMode::Hue,
"saturation" => BlendMode::Saturation,
"color" => BlendMode::Color,
"luminosity" => BlendMode::Luminosity,
"plus-lighter" => BlendMode::PlusLighter,
"plus-darker" => BlendMode::PlusDarker
);
impl TailwindPropertyParser for BlendMode {
fn parse_tw(token: &str) -> Option<Self> {
Self::from_str(token).ok()
}
}
impl Animatable for BlendMode {
fn list_interpolation_strategy() -> ListInterpolationStrategy {
ListInterpolationStrategy::RepeatToLcm
}
}