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