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