peniko/blend.rs
1// Copyright 2022 the Peniko Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4/// Defines the color mixing function for a [blend operation](BlendMode).
5///
6/// See [W3C's *Compositing and Blending Level 1* draft](https://www.w3.org/TR/compositing-1/) for more details.
7/// Illustrations fall under the [W3C open license](https://www.w3.org/copyright/software-license/).
8#[derive(Copy, Clone, PartialEq, Eq, Debug)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[repr(u8)]
11pub enum Mix {
12 /// Default attribute which specifies no blending. The blending formula simply selects the source color.
13 ///
14 /// 
15 Normal = 0,
16 /// Source color is multiplied by the destination color and replaces the destination.
17 ///
18 /// 
19 Multiply = 1,
20 /// Multiplies the complements of the backdrop and source color values, then complements the result.
21 ///
22 /// 
23 Screen = 2,
24 /// Multiplies or screens the colors, depending on the backdrop color value.
25 ///
26 /// 
27 Overlay = 3,
28 /// Selects the darker of the backdrop and source colors.
29 ///
30 /// 
31 Darken = 4,
32 /// Selects the lighter of the backdrop and source colors.
33 ///
34 /// 
35 Lighten = 5,
36 /// Brightens the backdrop color to reflect the source color. Painting with black produces no
37 /// change.
38 ///
39 /// 
40 ColorDodge = 6,
41 /// Darkens the backdrop color to reflect the source color. Painting with white produces no
42 /// change.
43 ///
44 /// 
45 ColorBurn = 7,
46 /// Multiplies or screens the colors, depending on the source color value. The effect is
47 /// similar to shining a harsh spotlight on the backdrop.
48 ///
49 /// 
50 HardLight = 8,
51 /// Darkens or lightens the colors, depending on the source color value. The effect is similar
52 /// to shining a diffused spotlight on the backdrop.
53 ///
54 /// 
55 SoftLight = 9,
56 /// Subtracts the darker of the two constituent colors from the lighter color.
57 ///
58 /// 
59 Difference = 10,
60 /// Produces an effect similar to that of the `Difference` mode but lower in contrast. Painting
61 /// with white inverts the backdrop color; painting with black produces no change.
62 ///
63 /// 
64 Exclusion = 11,
65 /// Creates a color with the hue of the source color and the saturation and luminosity of the
66 /// backdrop color.
67 ///
68 /// 
69 Hue = 12,
70 /// Creates a color with the saturation of the source color and the hue and luminosity of the
71 /// backdrop color. Painting with this mode in an area of the backdrop that is a pure gray
72 /// (no saturation) produces no change.
73 ///
74 /// 
75 Saturation = 13,
76 /// Creates a color with the hue and saturation of the source color and the luminosity of the
77 /// backdrop color. This preserves the gray levels of the backdrop and is useful for coloring
78 /// monochrome images or tinting color images.
79 ///
80 /// 
81 Color = 14,
82 /// Creates a color with the luminosity of the source color and the hue and saturation of the
83 /// backdrop color. This produces an inverse effect to that of the `Color` mode.
84 ///
85 /// 
86 Luminosity = 15,
87 // NOTICE: If a new value is added, be sure to modify `MAX_VALUE` in the `bytemuck::Contiguous` impl.
88}
89
90/// Defines the layer composition function for a [blend operation](BlendMode).
91///
92/// See [W3C's *Compositing and Blending Level 1* draft](https://www.w3.org/TR/compositing-1/) for more details.
93/// Illustrations fall under the [W3C open license](https://www.w3.org/copyright/software-license/).
94#[derive(Copy, Clone, PartialEq, Eq, Debug)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96#[repr(u8)]
97pub enum Compose {
98 /// No regions are enabled.
99 ///
100 /// 
101 Clear = 0,
102 /// Only the source will be present.
103 ///
104 /// 
105 Copy = 1,
106 /// Only the destination will be present.
107 ///
108 /// 
109 Dest = 2,
110 /// The source is placed over the destination.
111 ///
112 /// 
113 SrcOver = 3,
114 /// The destination is placed over the source.
115 ///
116 /// 
117 DestOver = 4,
118 /// The parts of the source that overlap with the destination are placed.
119 ///
120 /// 
121 SrcIn = 5,
122 /// The parts of the destination that overlap with the source are placed.
123 ///
124 /// 
125 DestIn = 6,
126 /// The parts of the source that fall outside of the destination are placed.
127 ///
128 /// 
129 SrcOut = 7,
130 /// The parts of the destination that fall outside of the source are placed.
131 ///
132 /// 
133 DestOut = 8,
134 /// The parts of the source which overlap the destination replace the destination. The
135 /// destination is placed everywhere else.
136 ///
137 /// 
138 SrcAtop = 9,
139 /// The parts of the destination which overlaps the source replace the source. The source is
140 /// placed everywhere else.
141 ///
142 /// 
143 DestAtop = 10,
144 /// The non-overlapping regions of source and destination are combined.
145 ///
146 /// 
147 Xor = 11,
148 /// The sum of the source image and destination image is displayed.
149 Plus = 12,
150 /// Allows two elements to cross fade by changing their opacities from 0 to 1 on one
151 /// element and 1 to 0 on the other element.
152 PlusLighter = 13,
153 // NOTICE: If a new value is added, be sure to modify `MAX_VALUE` in the `bytemuck::Contiguous` impl.
154}
155
156/// Blend mode consisting of [color mixing](Mix) and [composition functions](Compose).
157#[derive(Copy, Clone, PartialEq, Eq, Debug)]
158#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
159pub struct BlendMode {
160 /// The color mixing function.
161 pub mix: Mix,
162 /// The layer composition function.
163 pub compose: Compose,
164}
165
166impl BlendMode {
167 /// Creates a new blend mode from color mixing and layer composition
168 /// functions.
169 #[must_use]
170 pub const fn new(mix: Mix, compose: Compose) -> Self {
171 Self { mix, compose }
172 }
173}
174
175impl Default for BlendMode {
176 fn default() -> Self {
177 Self {
178 mix: Mix::Normal,
179 compose: Compose::SrcOver,
180 }
181 }
182}
183
184impl From<Mix> for BlendMode {
185 fn from(mix: Mix) -> Self {
186 Self {
187 mix,
188 compose: Compose::SrcOver,
189 }
190 }
191}
192
193impl From<Compose> for BlendMode {
194 fn from(compose: Compose) -> Self {
195 Self {
196 mix: Mix::Normal,
197 compose,
198 }
199 }
200}