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