1 | use crate::pipeline; |
2 | |
3 | /// A blending mode. |
4 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] |
5 | pub 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 | |
66 | impl Default for BlendMode { |
67 | fn default() -> Self { |
68 | BlendMode::SourceOver |
69 | } |
70 | } |
71 | |
72 | impl 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 | |