1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.ui.graphics
18 
19 import androidx.compose.runtime.Immutable
20 
21 /**
22  * Algorithms to use when painting on the canvas.
23  *
24  * When drawing a shape or image onto a canvas, different algorithms can be used to blend the
25  * pixels. The different values of [BlendMode] specify different such algorithms.
26  *
27  * Each algorithm has two inputs, the _source_, which is the image being drawn, and the
28  * _destination_, which is the image into which the source image is being composited. The
29  * destination is often thought of as the _background_. The source and destination both have four
30  * color channels, the red, green, blue, and alpha channels. These are typically represented as
31  * numbers in the range 0.0 to 1.0. The output of the algorithm also has these same four channels,
32  * with values computed from the source and destination.
33  *
34  * ## Application to the [Canvas] API
35  *
36  * When using [Canvas.saveLayer] and [Canvas.restore], the blend mode of the [Paint] given to the
37  * [Canvas.saveLayer] will be applied when [Canvas.restore] is called. Each call to
38  * [Canvas.saveLayer] introduces a new layer onto which shapes and images are painted; when
39  * [Canvas.restore] is called, that layer is then composited onto the parent layer, with the source
40  * being the most-recently-drawn shapes and images, and the destination being the parent layer. (For
41  * the first [Canvas.saveLayer] call, the parent layer is the canvas itself.)
42  *
43  * See also:
44  * * [Paint.blendMode], which uses [BlendMode] to define the compositing strategy.
45  */
46 @Immutable
47 @kotlin.jvm.JvmInline
48 value class BlendMode internal constructor(@Suppress("unused") private val value: Int) {
49 
50     companion object {
51 
52         /** Drop both the source and destination images, leaving nothing. */
53         val Clear = BlendMode(0)
54 
55         /**
56          * Drop the destination image, only paint the source image.
57          *
58          * Conceptually, the destination is first cleared, then the source image is painted.
59          */
60         val Src = BlendMode(1)
61 
62         /**
63          * Drop the source image, only paint the destination image.
64          *
65          * Conceptually, the source image is discarded, leaving the destination untouched.
66          */
67         val Dst = BlendMode(2)
68 
69         /**
70          * Composite the source image over the destination image.
71          *
72          * This is the default value. It represents the most intuitive case, where shapes are
73          * painted on top of what is below, with transparent areas showing the destination layer.
74          */
75         val SrcOver = BlendMode(3)
76 
77         /**
78          * Composite the source image under the destination image.
79          *
80          * This is the opposite of [SrcOver].
81          *
82          * This is useful when the source image should have been painted before the destination
83          * image, but could not be.
84          */
85         val DstOver = BlendMode(4)
86 
87         /**
88          * Show the source image, but only where the two images overlap. The destination image is
89          * not rendered, it is treated merely as a mask. The color channels of the destination are
90          * ignored, only the opacity has an effect.
91          *
92          * To show the destination image instead, consider [DstIn].
93          *
94          * To reverse the semantic of the mask (only showing the source where the destination is
95          * absent, rather than where it is present), consider [SrcOut].
96          */
97         val SrcIn = BlendMode(5)
98 
99         /**
100          * Show the destination image, but only where the two images overlap. The source image is
101          * not rendered, it is treated merely as a mask. The color channels of the source are
102          * ignored, only the opacity has an effect.
103          *
104          * To show the source image instead, consider [SrcIn].
105          *
106          * To reverse the semantic of the mask (only showing the source where the destination is
107          * present, rather than where it is absent), consider [DstOut].
108          */
109         val DstIn = BlendMode(6)
110 
111         /**
112          * Show the source image, but only where the two images do not overlap. The destination
113          * image is not rendered, it is treated merely as a mask. The color channels of the
114          * destination are ignored, only the opacity has an effect.
115          *
116          * To show the destination image instead, consider [DstOut].
117          *
118          * To reverse the semantic of the mask (only showing the source where the destination is
119          * present, rather than where it is absent), consider [SrcIn].
120          *
121          * This corresponds to the "Source out Destination" Porter-Duff operator.
122          */
123         val SrcOut = BlendMode(7)
124 
125         /**
126          * Show the destination image, but only where the two images do not overlap. The source
127          * image is not rendered, it is treated merely as a mask. The color channels of the source
128          * are ignored, only the opacity has an effect.
129          *
130          * To show the source image instead, consider [SrcOut].
131          *
132          * To reverse the semantic of the mask (only showing the destination where the source is
133          * present, rather than where it is absent), consider [DstIn].
134          *
135          * This corresponds to the "Destination out Source" Porter-Duff operator.
136          */
137         val DstOut = BlendMode(8)
138 
139         /**
140          * Composite the source image over the destination image, but only where it overlaps the
141          * destination.
142          *
143          * This is essentially the [SrcOver] operator, but with the output's opacity channel being
144          * set to that of the destination image instead of being a combination of both image's
145          * opacity channels.
146          *
147          * For a variant with the destination on top instead of the source, see [DstAtop].
148          */
149         val SrcAtop = BlendMode(9)
150 
151         /**
152          * Composite the destination image over the source image, but only where it overlaps the
153          * source.
154          *
155          * This is essentially the [DstOver] operator, but with the output's opacity channel being
156          * set to that of the source image instead of being a combination of both image's opacity
157          * channels.
158          *
159          * For a variant with the source on top instead of the destination, see [SrcAtop].
160          */
161         val DstAtop = BlendMode(10)
162 
163         /**
164          * Apply a bitwise `xor` operator to the source and destination images. This leaves
165          * transparency where they would overlap.
166          */
167         val Xor = BlendMode(11)
168 
169         /**
170          * Sum the components of the source and destination images.
171          *
172          * Transparency in a pixel of one of the images reduces the contribution of that image to
173          * the corresponding output pixel, as if the color of that pixel in that image was darker.
174          */
175         val Plus = BlendMode(12)
176 
177         /**
178          * Multiply the color components of the source and destination images.
179          *
180          * This can only result in the same or darker colors (multiplying by white, 1.0, results in
181          * no change; multiplying by black, 0.0, results in black).
182          *
183          * When compositing two opaque images, this has similar effect to overlapping two
184          * transparencies on a projector.
185          *
186          * For a variant that also multiplies the alpha channel, consider [Multiply].
187          *
188          * See also:
189          * * [Screen], which does a similar computation but inverted.
190          * * [Overlay], which combines [Modulate] and [Screen] to favor the destination image.
191          * * [Hardlight], which combines [Modulate] and [Screen] to favor the source image.
192          */
193         val Modulate = BlendMode(13)
194 
195         /**
196          * Multiply the inverse of the components of the source and destination images, and inverse
197          * the result.
198          *
199          * Inverting the components means that a fully saturated channel (opaque white) is treated
200          * as the value 0.0, and values normally treated as 0.0 (black, transparent) are treated as
201          * 1.0.
202          *
203          * This is essentially the same as [Modulate] blend mode, but with the values of the colors
204          * inverted before the multiplication and the result being inverted back before rendering.
205          *
206          * This can only result in the same or lighter colors (multiplying by black, 1.0, results in
207          * no change; multiplying by white, 0.0, results in white). Similarly, in the alpha channel,
208          * it can only result in more opaque colors.
209          *
210          * This has similar effect to two projectors displaying their images on the same screen
211          * simultaneously.
212          *
213          * See also:
214          * * [Modulate], which does a similar computation but without inverting the values.
215          * * [Overlay], which combines [Modulate] and [Screen] to favor the destination image.
216          * * [Hardlight], which combines [Modulate] and [Screen] to favor the source image.
217          */
218         val Screen = BlendMode(14) // The last coeff mode.
219 
220         /**
221          * Multiply the components of the source and destination images after adjusting them to
222          * favor the destination.
223          *
224          * Specifically, if the destination value is smaller, this multiplies it with the source
225          * value, whereas is the source value is smaller, it multiplies the inverse of the source
226          * value with the inverse of the destination value, then inverts the result.
227          *
228          * Inverting the components means that a fully saturated channel (opaque white) is treated
229          * as the value 0.0, and values normally treated as 0.0 (black, transparent) are treated as
230          * 1.0.
231          *
232          * See also:
233          * * [Modulate], which always multiplies the values.
234          * * [Screen], which always multiplies the inverses of the values.
235          * * [Hardlight], which is similar to [Overlay] but favors the source image instead of the
236          *   destination image.
237          */
238         val Overlay = BlendMode(15)
239 
240         /**
241          * Composite the source and destination image by choosing the lowest value from each color
242          * channel.
243          *
244          * The opacity of the output image is computed in the same way as for [SrcOver].
245          */
246         val Darken = BlendMode(16)
247 
248         /**
249          * Composite the source and destination image by choosing the highest value from each color
250          * channel.
251          *
252          * The opacity of the output image is computed in the same way as for [SrcOver].
253          */
254         val Lighten = BlendMode(17)
255 
256         /**
257          * Divide the destination by the inverse of the source.
258          *
259          * Inverting the components means that a fully saturated channel (opaque white) is treated
260          * as the value 0.0, and values normally treated as 0.0 (black, transparent) are treated as
261          * 1.0.
262          *
263          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
264          */
265         val ColorDodge = BlendMode(18)
266 
267         /**
268          * Divide the inverse of the destination by the source, and inverse the result.
269          *
270          * Inverting the components means that a fully saturated channel (opaque white) is treated
271          * as the value 0.0, and values normally treated as 0.0 (black, transparent) are treated as
272          * 1.0.
273          *
274          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
275          */
276         val ColorBurn = BlendMode(19)
277 
278         /**
279          * Multiply the components of the source and destination images after adjusting them to
280          * favor the source.
281          *
282          * Specifically, if the source value is smaller, this multiplies it with the destination
283          * value, whereas is the destination value is smaller, it multiplies the inverse of the
284          * destination value with the inverse of the source value, then inverts the result.
285          *
286          * Inverting the components means that a fully saturated channel (opaque white) is treated
287          * as the value 0.0, and values normally treated as 0.0 (black, transparent) are treated as
288          * 1.0.
289          *
290          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
291          *
292          * See also:
293          * * [Modulate], which always multiplies the values.
294          * * [Screen], which always multiplies the inverses of the values.
295          * * [Overlay], which is similar to [Hardlight] but favors the destination image instead of
296          *   the source image.
297          */
298         val Hardlight = BlendMode(20)
299 
300         /**
301          * Use [ColorDodge] for source values below 0.5 and [ColorBurn] for source values above 0.5.
302          *
303          * This results in a similar but softer effect than [Overlay].
304          *
305          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
306          *
307          * See also:
308          * * [BlendMode.Color], which is a more subtle tinting effect.
309          */
310         val Softlight = BlendMode(21)
311 
312         /**
313          * Subtract the smaller value from the bigger value for each channel.
314          *
315          * Compositing black has no effect; compositing white inverts the colors of the other image.
316          *
317          * The opacity of the output image is computed in the same way as for [SrcOver].
318          *
319          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
320          *
321          * The effect is similar to [Exclusion] but harsher.
322          */
323         val Difference = BlendMode(22)
324 
325         /**
326          * Subtract double the product of the two images from the sum of the two images.
327          *
328          * Compositing black has no effect; compositing white inverts the colors of the other image.
329          *
330          * The opacity of the output image is computed in the same way as for [SrcOver].
331          *
332          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
333          *
334          * The effect is similar to [Difference] but softer.
335          */
336         val Exclusion = BlendMode(23)
337 
338         /**
339          * Multiply the components of the source and destination images, including the alpha
340          * channel.
341          *
342          * This can only result in the same or darker colors (multiplying by white, 1.0, results in
343          * no change; multiplying by black, 0.0, results in black).
344          *
345          * Since the alpha channel is also multiplied, a fully-transparent pixel (opacity 0.0) in
346          * one image results in a fully transparent pixel in the output. This is similar to [DstIn],
347          * but with the colors combined.
348          *
349          * For a variant that multiplies the colors but does not multiply the alpha channel,
350          * consider [Modulate].
351          *
352          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
353          */
354         val Multiply = BlendMode(24) // The last separable mode.
355 
356         /**
357          * Take the hue of the source image, and the saturation and luminosity of the destination
358          * image.
359          *
360          * The effect is to tint the destination image with the source image.
361          *
362          * The opacity of the output image is computed in the same way as for [SrcOver]. Regions
363          * that are entirely transparent in the source image take their hue from the destination.
364          *
365          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
366          */
367         val Hue = BlendMode(25)
368 
369         /**
370          * Take the saturation of the source image, and the hue and luminosity of the destination
371          * image.
372          *
373          * The opacity of the output image is computed in the same way as for [SrcOver]. Regions
374          * that are entirely transparent in the source image take their saturation from the
375          * destination.
376          *
377          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
378          *
379          * See also:
380          * * [BlendMode.Color], which also applies the hue of the source image.
381          * * [Luminosity], which applies the luminosity of the source image to the destination.
382          */
383         val Saturation = BlendMode(26)
384 
385         /**
386          * Take the hue and saturation of the source image, and the luminosity of the destination
387          * image.
388          *
389          * The effect is to tint the destination image with the source image.
390          *
391          * The opacity of the output image is computed in the same way as for [SrcOver]. Regions
392          * that are entirely transparent in the source image take their hue and saturation from the
393          * destination.
394          *
395          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
396          *
397          * See also:
398          * * [Hue], which is a similar but weaker effect.
399          * * [Softlight], which is a similar tinting effect but also tints white.
400          * * [Saturation], which only applies the saturation of the source image.
401          */
402         val Color = BlendMode(27)
403 
404         /**
405          * Take the luminosity of the source image, and the hue and saturation of the destination
406          * image.
407          *
408          * The opacity of the output image is computed in the same way as for [SrcOver]. Regions
409          * that are entirely transparent in the source image take their luminosity from the
410          * destination.
411          *
412          * **NOTE** This [BlendMode] can only be used on Android API level 29 and above
413          *
414          * See also:
415          * * [Saturation], which applies the saturation of the source image to the destination.
416          */
417         val Luminosity = BlendMode(28)
418     }
419 
toStringnull420     override fun toString() =
421         when (this) {
422             Clear -> "Clear"
423             Src -> "Src"
424             Dst -> "Dst"
425             SrcOver -> "SrcOver"
426             DstOver -> "DstOver"
427             SrcIn -> "SrcIn"
428             DstIn -> "DstIn"
429             SrcOut -> "SrcOut"
430             DstOut -> "DstOut"
431             SrcAtop -> "SrcAtop"
432             DstAtop -> "DstAtop"
433             Xor -> "Xor"
434             Plus -> "Plus"
435             Modulate -> "Modulate"
436             Screen -> "Screen"
437             Overlay -> "Overlay"
438             Darken -> "Darken"
439             Lighten -> "Lighten"
440             ColorDodge -> "ColorDodge"
441             ColorBurn -> "ColorBurn"
442             Hardlight -> "HardLight"
443             Softlight -> "Softlight"
444             Difference -> "Difference"
445             Exclusion -> "Exclusion"
446             Multiply -> "Multiply"
447             Hue -> "Hue"
448             Saturation -> "Saturation"
449             Color -> "Color"
450             Luminosity -> "Luminosity"
451             else -> "Unknown" // Should not get here since we have an internal constructor
452         }
453 }
454 
455 /**
456  * Capability query to determine if the particular platform supports the [BlendMode]. Not all
457  * platforms support all blend mode algorithms, however, [BlendMode.SrcOver] is guaranteed to be
458  * supported as it is the default drawing algorithm. If a [BlendMode] that is not supported is used,
459  * the default of SrcOver is consumed instead.
460  */
isSupportednull461 expect fun BlendMode.isSupported(): Boolean
462