1use crate::pipeline;
2
3/// A blending mode.
4#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
5pub enum BlendMode {
6 /// Replaces destination with zero: fully transparent.
7 Clear,
8 /// Replaces destination.
9 Source,
10 /// Preserves destination.
11 Destination,
12 /// Source over destination.
13 SourceOver,
14 /// Destination over source.
15 DestinationOver,
16 /// Source trimmed inside destination.
17 SourceIn,
18 /// Destination trimmed by source.
19 DestinationIn,
20 /// Source trimmed outside destination.
21 SourceOut,
22 /// Destination trimmed outside source.
23 DestinationOut,
24 /// Source inside destination blended with destination.
25 SourceAtop,
26 /// Destination inside source blended with source.
27 DestinationAtop,
28 /// Each of source and destination trimmed outside the other.
29 Xor,
30 /// Sum of colors.
31 Plus,
32 /// Product of premultiplied colors; darkens destination.
33 Modulate,
34 /// Multiply inverse of pixels, inverting result; brightens destination.
35 Screen,
36 /// Multiply or screen, depending on destination.
37 Overlay,
38 /// Darker of source and destination.
39 Darken,
40 /// Lighter of source and destination.
41 Lighten,
42 /// Brighten destination to reflect source.
43 ColorDodge,
44 /// Darken destination to reflect source.
45 ColorBurn,
46 /// Multiply or screen, depending on source.
47 HardLight,
48 /// Lighten or darken, depending on source.
49 SoftLight,
50 /// Subtract darker from lighter with higher contrast.
51 Difference,
52 /// Subtract darker from lighter with lower contrast.
53 Exclusion,
54 /// Multiply source with destination, darkening image.
55 Multiply,
56 /// Hue of source with saturation and luminosity of destination.
57 Hue,
58 /// Saturation of source with hue and luminosity of destination.
59 Saturation,
60 /// Hue and saturation of source with luminosity of destination.
61 Color,
62 /// Luminosity of source with hue and saturation of destination.
63 Luminosity,
64}
65
66impl Default for BlendMode {
67 fn default() -> Self {
68 BlendMode::SourceOver
69 }
70}
71
72impl BlendMode {
73 pub(crate) fn should_pre_scale_coverage(self) -> bool {
74 // The most important things we do here are:
75 // 1) never pre-scale with rgb coverage if the blend mode involves a source-alpha term;
76 // 2) always pre-scale Plus.
77 //
78 // When we pre-scale with rgb coverage, we scale each of source r,g,b, with a distinct value,
79 // and source alpha with one of those three values. This process destructively updates the
80 // source-alpha term, so we can't evaluate blend modes that need its original value.
81 //
82 // Plus always requires pre-scaling as a specific quirk of its implementation in
83 // RasterPipeline. This lets us put the clamp inside the blend mode itself rather
84 // than as a separate stage that'd come after the lerp.
85 //
86 // This function is a finer-grained breakdown of SkBlendMode_SupportsCoverageAsAlpha().
87 matches!(
88 self,
89 BlendMode::Destination | // d --> no sa term, ok!
90 BlendMode::DestinationOver | // d + s*inv(da) --> no sa term, ok!
91 BlendMode::Plus | // clamp(s+d) --> no sa term, ok!
92 BlendMode::DestinationOut | // d * inv(sa)
93 BlendMode::SourceAtop | // s*da + d*inv(sa)
94 BlendMode::SourceOver | // s + d*inv(sa)
95 BlendMode::Xor // s*inv(da) + d*inv(sa)
96 )
97 }
98
99 pub(crate) fn to_stage(self) -> Option<pipeline::Stage> {
100 match self {
101 BlendMode::Clear => Some(pipeline::Stage::Clear),
102 BlendMode::Source => None, // This stage is a no-op.
103 BlendMode::Destination => Some(pipeline::Stage::MoveDestinationToSource),
104 BlendMode::SourceOver => Some(pipeline::Stage::SourceOver),
105 BlendMode::DestinationOver => Some(pipeline::Stage::DestinationOver),
106 BlendMode::SourceIn => Some(pipeline::Stage::SourceIn),
107 BlendMode::DestinationIn => Some(pipeline::Stage::DestinationIn),
108 BlendMode::SourceOut => Some(pipeline::Stage::SourceOut),
109 BlendMode::DestinationOut => Some(pipeline::Stage::DestinationOut),
110 BlendMode::SourceAtop => Some(pipeline::Stage::SourceAtop),
111 BlendMode::DestinationAtop => Some(pipeline::Stage::DestinationAtop),
112 BlendMode::Xor => Some(pipeline::Stage::Xor),
113 BlendMode::Plus => Some(pipeline::Stage::Plus),
114 BlendMode::Modulate => Some(pipeline::Stage::Modulate),
115 BlendMode::Screen => Some(pipeline::Stage::Screen),
116 BlendMode::Overlay => Some(pipeline::Stage::Overlay),
117 BlendMode::Darken => Some(pipeline::Stage::Darken),
118 BlendMode::Lighten => Some(pipeline::Stage::Lighten),
119 BlendMode::ColorDodge => Some(pipeline::Stage::ColorDodge),
120 BlendMode::ColorBurn => Some(pipeline::Stage::ColorBurn),
121 BlendMode::HardLight => Some(pipeline::Stage::HardLight),
122 BlendMode::SoftLight => Some(pipeline::Stage::SoftLight),
123 BlendMode::Difference => Some(pipeline::Stage::Difference),
124 BlendMode::Exclusion => Some(pipeline::Stage::Exclusion),
125 BlendMode::Multiply => Some(pipeline::Stage::Multiply),
126 BlendMode::Hue => Some(pipeline::Stage::Hue),
127 BlendMode::Saturation => Some(pipeline::Stage::Saturation),
128 BlendMode::Color => Some(pipeline::Stage::Color),
129 BlendMode::Luminosity => Some(pipeline::Stage::Luminosity),
130 }
131 }
132}
133