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