1 /*
2  * Copyright (C) 2006 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 android.graphics;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 
21 /**
22  * <p>This class contains the list of alpha compositing and blending modes
23  * that can be passed to {@link PorterDuffXfermode}, a specialized implementation
24  * of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}.
25  * All the available modes can be found in the {@link Mode} enum.</p>
26  *
27  * Consider using {@link BlendMode} instead as it provides a wider variety of tinting options
28  */
29 public class PorterDuff {
30     /**
31      * {@usesMathJax}
32      *
33      * <h3>Porter-Duff</h3>
34      *
35      * <p>The name of the parent class is an homage to the work of Thomas Porter and
36      * Tom Duff, presented in their seminal 1984 paper titled "Compositing Digital Images".
37      * In this paper, the authors describe 12 compositing operators that govern how to
38      * compute the color resulting of the composition of a source (the graphics object
39      * to render) with a destination (the content of the render target).</p>
40      *
41      * <p>"Compositing Digital Images" was published in <em>Computer Graphics</em>
42      * Volume 18, Number 3 dated July 1984.</p>
43      *
44      * <p>Because the work of Porter and Duff focuses solely on the effects of the alpha
45      * channel of the source and destination, the 12 operators described in the original
46      * paper are called alpha compositing modes here.</p>
47      *
48      * <p>For convenience, this class also provides several blending modes, which similarly
49      * define the result of compositing a source and a destination but without being
50      * constrained to the alpha channel. These blending modes are not defined by Porter
51      * and Duff but have been included in this class for convenience purposes.</p>
52      *
53      * <h3>Diagrams</h3>
54      *
55      * <p>All the example diagrams presented below use the same source and destination
56      * images:</p>
57      *
58      * <table summary="Source and Destination" style="background-color: transparent;">
59      *     <tr>
60      *         <td style="border: none; text-align: center;">
61      *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
62      *             <figcaption>Source image</figcaption>
63      *         </td>
64      *         <td style="border: none; text-align: center;">
65      *             <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
66      *             <figcaption>Destination image</figcaption>
67      *         </td>
68      *     </tr>
69      * </table>
70      *
71      * <p>The order of drawing operations used to generate each diagram is shown in the
72      * following code snippet:</p>
73      *
74      * <pre class="prettyprint">
75      * Paint paint = new Paint();
76      * canvas.drawBitmap(destinationImage, 0, 0, paint);
77      *
78      * PorterDuff.Mode mode = // choose a mode
79      * paint.setXfermode(new PorterDuffXfermode(mode));
80      *
81      * canvas.drawBitmap(sourceImage, 0, 0, paint);
82      * </pre>
83 
84      *
85      * <h3>Alpha compositing modes</h3>
86      *
87      * <table summary="Alpha compositing modes" style="background-color: transparent;">
88      *     <tr>
89      *         <td style="border: none; text-align: center;">
90      *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
91      *             <figcaption>{@link #SRC Source}</figcaption>
92      *         </td>
93      *         <td style="border: none; text-align: center;">
94      *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
95      *             <figcaption>{@link #SRC_OVER Source Over}</figcaption>
96      *         </td>
97      *         <td style="border: none; text-align: center;">
98      *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
99      *             <figcaption>{@link #SRC_IN Source In}</figcaption>
100      *         </td>
101      *         <td style="border: none; text-align: center;">
102      *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
103      *             <figcaption>{@link #SRC_ATOP Source Atop}</figcaption>
104      *         </td>
105      *     </tr>
106      *     <tr>
107      *         <td style="border: none; text-align: center;">
108      *             <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
109      *             <figcaption>{@link #DST Destination}</figcaption>
110      *         </td>
111      *         <td style="border: none; text-align: center;">
112      *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
113      *             <figcaption>{@link #DST_OVER Destination Over}</figcaption>
114      *         </td>
115      *         <td style="border: none; text-align: center;">
116      *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
117      *             <figcaption>{@link #DST_IN Destination In}</figcaption>
118      *         </td>
119      *         <td style="border: none; text-align: center;">
120      *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
121      *             <figcaption>{@link #DST_ATOP Destination Atop}</figcaption>
122      *         </td>
123      *     </tr>
124      *     <tr>
125      *         <td style="border: none; text-align: center;">
126      *             <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
127      *             <figcaption>{@link #CLEAR Clear}</figcaption>
128      *         </td>
129      *         <td style="border: none; text-align: center;">
130      *             <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
131      *             <figcaption>{@link #SRC_OUT Source Out}</figcaption>
132      *         </td>
133      *         <td style="border: none; text-align: center;">
134      *             <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
135      *             <figcaption>{@link #DST_OUT Destination Out}</figcaption>
136      *         </td>
137      *         <td style="border: none; text-align: center;">
138      *             <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
139      *             <figcaption>{@link #XOR Exclusive Or}</figcaption>
140      *         </td>
141      *     </tr>
142      * </table>
143      *
144      * <h3>Blending modes</h3>
145      *
146      * <table summary="Blending modes" style="background-color: transparent;">
147      *     <tr>
148      *         <td style="border: none; text-align: center;">
149      *             <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
150      *             <figcaption>{@link #DARKEN Darken}</figcaption>
151      *         </td>
152      *         <td style="border: none; text-align: center;">
153      *             <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
154      *             <figcaption>{@link #LIGHTEN Lighten}</figcaption>
155      *         </td>
156      *         <td style="border: none; text-align: center;">
157      *             <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
158      *             <figcaption>{@link #MULTIPLY Multiply}</figcaption>
159      *         </td>
160      *     </tr>
161      *     <tr>
162      *         <td style="border: none; text-align: center;">
163      *             <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
164      *             <figcaption>{@link #SCREEN Screen}</figcaption>
165      *         </td>
166      *         <td style="border: none; text-align: center;">
167      *             <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
168      *             <figcaption>{@link #OVERLAY Overlay}</figcaption>
169      *         </td>
170      *     </tr>
171      * </table>
172      *
173      * <h3>Compositing equations</h3>
174      *
175      * <p>The documentation of each individual alpha compositing or blending mode below
176      * provides the exact equation used to compute alpha and color value of the result
177      * of the composition of a source and destination.</p>
178      *
179      * <p>The result (or output) alpha value is noted \(\alpha_{out}\). The result (or output)
180      * color value is noted \(C_{out}\).</p>
181      */
182     public enum Mode {
183         // these value must match their native equivalents. See SkXfermode.h
184         /**
185          * <p>
186          *     <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
187          *     <figcaption>Destination pixels covered by the source are cleared to 0.</figcaption>
188          * </p>
189          * <p>\(\alpha_{out} = 0\)</p>
190          * <p>\(C_{out} = 0\)</p>
191          */
192         CLEAR       (0),
193         /**
194          * <p>
195          *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
196          *     <figcaption>The source pixels replace the destination pixels.</figcaption>
197          * </p>
198          * <p>\(\alpha_{out} = \alpha_{src}\)</p>
199          * <p>\(C_{out} = C_{src}\)</p>
200          */
201         SRC         (1),
202         /**
203          * <p>
204          *     <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
205          *     <figcaption>The source pixels are discarded, leaving the destination intact.</figcaption>
206          * </p>
207          * <p>\(\alpha_{out} = \alpha_{dst}\)</p>
208          * <p>\(C_{out} = C_{dst}\)</p>
209          */
210         DST         (2),
211         /**
212          * <p>
213          *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
214          *     <figcaption>The source pixels are drawn over the destination pixels.</figcaption>
215          * </p>
216          * <p>\(\alpha_{out} = \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
217          * <p>\(C_{out} = C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
218          */
219         SRC_OVER    (3),
220         /**
221          * <p>
222          *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
223          *     <figcaption>The source pixels are drawn behind the destination pixels.</figcaption>
224          * </p>
225          * <p>\(\alpha_{out} = \alpha_{dst} + (1 - \alpha_{dst}) * \alpha_{src}\)</p>
226          * <p>\(C_{out} = C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
227          */
228         DST_OVER    (4),
229         /**
230          * <p>
231          *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
232          *     <figcaption>Keeps the source pixels that cover the destination pixels,
233          *     discards the remaining source and destination pixels.</figcaption>
234          * </p>
235          * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
236          * <p>\(C_{out} = C_{src} * \alpha_{dst}\)</p>
237          */
238         SRC_IN      (5),
239         /**
240          * <p>
241          *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
242          *     <figcaption>Keeps the destination pixels that cover source pixels,
243          *     discards the remaining source and destination pixels.</figcaption>
244          * </p>
245          * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
246          * <p>\(C_{out} = C_{dst} * \alpha_{src}\)</p>
247          */
248         DST_IN      (6),
249         /**
250          * <p>
251          *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
252          *     <figcaption>Keeps the source pixels that do not cover destination pixels.
253          *     Discards source pixels that cover destination pixels. Discards all
254          *     destination pixels.</figcaption>
255          * </p>
256          * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src}\)</p>
257          * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src}\)</p>
258          */
259         SRC_OUT     (7),
260         /**
261          * <p>
262          *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
263          *     <figcaption>Keeps the destination pixels that are not covered by source pixels.
264          *     Discards destination pixels that are covered by source pixels. Discards all
265          *     source pixels.</figcaption>
266          * </p>
267          * <p>\(\alpha_{out} = (1 - \alpha_{src}) * \alpha_{dst}\)</p>
268          * <p>\(C_{out} = (1 - \alpha_{src}) * C_{dst}\)</p>
269          */
270         DST_OUT     (8),
271         /**
272          * <p>
273          *     <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
274          *     <figcaption>Discards the source pixels that do not cover destination pixels.
275          *     Draws remaining source pixels over destination pixels.</figcaption>
276          * </p>
277          * <p>\(\alpha_{out} = \alpha_{dst}\)</p>
278          * <p>\(C_{out} = \alpha_{dst} * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
279          */
280         SRC_ATOP    (9),
281         /**
282          * <p>
283          *     <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
284          *     <figcaption>Discards the destination pixels that are not covered by source pixels.
285          *     Draws remaining destination pixels over source pixels.</figcaption>
286          * </p>
287          * <p>\(\alpha_{out} = \alpha_{src}\)</p>
288          * <p>\(C_{out} = \alpha_{src} * C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
289          */
290         DST_ATOP    (10),
291         /**
292          * <p>
293          *     <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
294          *     <figcaption>Discards the source and destination pixels where source pixels
295          *     cover destination pixels. Draws remaining source pixels.</figcaption>
296          * </p>
297          * <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
298          * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
299          */
300         XOR         (11),
301         /**
302          * <p>
303          *     <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
304          *     <figcaption>Retains the smallest component of the source and
305          *     destination pixels.</figcaption>
306          * </p>
307          * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
308          * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + min(C_{src}, C_{dst})\)</p>
309          */
310         DARKEN      (16),
311         /**
312          * <p>
313          *     <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
314          *     <figcaption>Retains the largest component of the source and
315          *     destination pixel.</figcaption>
316          * </p>
317          * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
318          * <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + max(C_{src}, C_{dst})\)</p>
319          */
320         LIGHTEN     (17),
321         /**
322          * <p>
323          *     <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
324          *     <figcaption>Multiplies the source and destination pixels.</figcaption>
325          * </p>
326          * <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
327          * <p>\(C_{out} = C_{src} * C_{dst}\)</p>
328          */
329         MULTIPLY    (13),
330         /**
331          * <p>
332          *     <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
333          *     <figcaption>Adds the source and destination pixels, then subtracts the
334          *     source pixels multiplied by the destination.</figcaption>
335          * </p>
336          * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
337          * <p>\(C_{out} = C_{src} + C_{dst} - C_{src} * C_{dst}\)</p>
338          */
339         SCREEN      (14),
340         /**
341          * <p>
342          *     <img src="{@docRoot}reference/android/images/graphics/composite_ADD.png" />
343          *     <figcaption>Adds the source pixels to the destination pixels and saturates
344          *     the result.</figcaption>
345          * </p>
346          * <p>\(\alpha_{out} = max(0, min(\alpha_{src} + \alpha_{dst}, 1))\)</p>
347          * <p>\(C_{out} = max(0, min(C_{src} + C_{dst}, 1))\)</p>
348          */
349         ADD         (12),
350         /**
351          * <p>
352          *     <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
353          *     <figcaption>Multiplies or screens the source and destination depending on the
354          *     destination color.</figcaption>
355          * </p>
356          * <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
357          * <p>\(\begin{equation}
358          * C_{out} = \begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} \lt \alpha_{dst} \\
359          * \alpha_{src} * \alpha_{dst} - 2 (\alpha_{dst} - C_{src}) (\alpha_{src} - C_{dst}) & otherwise \end{cases}
360          * \end{equation}\)</p>
361          */
362         OVERLAY     (15);
363 
Mode(int nativeInt)364         Mode(int nativeInt) {
365             this.nativeInt = nativeInt;
366         }
367 
368         /**
369          * @hide
370          */
371         @UnsupportedAppUsage
372         public final int nativeInt;
373     }
374 
375     /**
376      * @hide
377      */
modeToInt(Mode mode)378     public static int modeToInt(Mode mode) {
379         return mode.nativeInt;
380     }
381 
382     /**
383      * @hide
384      */
intToMode(int val)385     public static Mode intToMode(int val) {
386         switch (val) {
387             default:
388             case  0: return Mode.CLEAR;
389             case  1: return Mode.SRC;
390             case  2: return Mode.DST;
391             case  3: return Mode.SRC_OVER;
392             case  4: return Mode.DST_OVER;
393             case  5: return Mode.SRC_IN;
394             case  6: return Mode.DST_IN;
395             case  7: return Mode.SRC_OUT;
396             case  8: return Mode.DST_OUT;
397             case  9: return Mode.SRC_ATOP;
398             case 10: return Mode.DST_ATOP;
399             case 11: return Mode.XOR;
400             case 16: return Mode.DARKEN;
401             case 17: return Mode.LIGHTEN;
402             case 13: return Mode.MULTIPLY;
403             case 14: return Mode.SCREEN;
404             case 12: return Mode.ADD;
405             case 15: return Mode.OVERLAY;
406         }
407     }
408 }
409