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