variants Updated various framework Views to have equivalent BlendMode APIs to replace the deprecated PorterDuff equivalents. Updated InspectableProperty annotations to refer to the same xml attributes as the original tintmode APIs Bug: 126726419 Test: Added CTS tests to verify new BlendMode APIs Change-Id: Id9ab36d3d4d29f351250723e9d13d49bc6062c83 Merged-In: Id9ab36d3d4d29f351250723e9d13d49bc6062c83
409 lines
18 KiB
Java
409 lines
18 KiB
Java
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.graphics;
|
|
|
|
import android.annotation.UnsupportedAppUsage;
|
|
|
|
/**
|
|
* <p>This class contains the list of alpha compositing and blending modes
|
|
* that can be passed to {@link PorterDuffXfermode}, a specialized implementation
|
|
* of {@link Paint}'s {@link Paint#setXfermode(Xfermode) transfer mode}.
|
|
* All the available modes can be found in the {@link Mode} enum.</p>
|
|
*
|
|
* Consider using {@link BlendMode} instead as it provides a wider variety of tinting options
|
|
*/
|
|
public class PorterDuff {
|
|
/**
|
|
* {@usesMathJax}
|
|
*
|
|
* <h3>Porter-Duff</h3>
|
|
*
|
|
* <p>The name of the parent class is an homage to the work of Thomas Porter and
|
|
* Tom Duff, presented in their seminal 1984 paper titled "Compositing Digital Images".
|
|
* In this paper, the authors describe 12 compositing operators that govern how to
|
|
* compute the color resulting of the composition of a source (the graphics object
|
|
* to render) with a destination (the content of the render target).</p>
|
|
*
|
|
* <p>"Compositing Digital Images" was published in <em>Computer Graphics</em>
|
|
* Volume 18, Number 3 dated July 1984.</p>
|
|
*
|
|
* <p>Because the work of Porter and Duff focuses solely on the effects of the alpha
|
|
* channel of the source and destination, the 12 operators described in the original
|
|
* paper are called alpha compositing modes here.</p>
|
|
*
|
|
* <p>For convenience, this class also provides several blending modes, which similarly
|
|
* define the result of compositing a source and a destination but without being
|
|
* constrained to the alpha channel. These blending modes are not defined by Porter
|
|
* and Duff but have been included in this class for convenience purposes.</p>
|
|
*
|
|
* <h3>Diagrams</h3>
|
|
*
|
|
* <p>All the example diagrams presented below use the same source and destination
|
|
* images:</p>
|
|
*
|
|
* <table summary="Source and Destination" style="background-color: transparent;">
|
|
* <tr>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
|
|
* <figcaption>Source image</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
|
|
* <figcaption>Destination image</figcaption>
|
|
* </td>
|
|
* </tr>
|
|
* </table>
|
|
*
|
|
* <p>The order of drawing operations used to generate each diagram is shown in the
|
|
* following code snippet:</p>
|
|
*
|
|
* <pre class="prettyprint">
|
|
* Paint paint = new Paint();
|
|
* canvas.drawBitmap(destinationImage, 0, 0, paint);
|
|
*
|
|
* PorterDuff.Mode mode = // choose a mode
|
|
* paint.setXfermode(new PorterDuffXfermode(mode));
|
|
*
|
|
* canvas.drawBitmap(sourceImage, 0, 0, paint);
|
|
* </pre>
|
|
|
|
*
|
|
* <h3>Alpha compositing modes</h3>
|
|
*
|
|
* <table summary="Alpha compositing modes" style="background-color: transparent;">
|
|
* <tr>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
|
|
* <figcaption>{@link #SRC Source}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
|
|
* <figcaption>{@link #SRC_OVER Source Over}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
|
|
* <figcaption>{@link #SRC_IN Source In}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
|
|
* <figcaption>{@link #SRC_ATOP Source Atop}</figcaption>
|
|
* </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
|
|
* <figcaption>{@link #DST Destination}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
|
|
* <figcaption>{@link #DST_OVER Destination Over}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
|
|
* <figcaption>{@link #DST_IN Destination In}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
|
|
* <figcaption>{@link #DST_ATOP Destination Atop}</figcaption>
|
|
* </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
|
|
* <figcaption>{@link #CLEAR Clear}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
|
|
* <figcaption>{@link #SRC_OUT Source Out}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
|
|
* <figcaption>{@link #DST_OUT Destination Out}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
|
|
* <figcaption>{@link #XOR Exclusive Or}</figcaption>
|
|
* </td>
|
|
* </tr>
|
|
* </table>
|
|
*
|
|
* <h3>Blending modes</h3>
|
|
*
|
|
* <table summary="Blending modes" style="background-color: transparent;">
|
|
* <tr>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
|
|
* <figcaption>{@link #DARKEN Darken}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
|
|
* <figcaption>{@link #LIGHTEN Lighten}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
|
|
* <figcaption>{@link #MULTIPLY Multiply}</figcaption>
|
|
* </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
|
|
* <figcaption>{@link #SCREEN Screen}</figcaption>
|
|
* </td>
|
|
* <td style="border: none; text-align: center;">
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
|
|
* <figcaption>{@link #OVERLAY Overlay}</figcaption>
|
|
* </td>
|
|
* </tr>
|
|
* </table>
|
|
*
|
|
* <h3>Compositing equations</h3>
|
|
*
|
|
* <p>The documentation of each individual alpha compositing or blending mode below
|
|
* provides the exact equation used to compute alpha and color value of the result
|
|
* of the composition of a source and destination.</p>
|
|
*
|
|
* <p>The result (or output) alpha value is noted \(\alpha_{out}\). The result (or output)
|
|
* color value is noted \(C_{out}\).</p>
|
|
*/
|
|
public enum Mode {
|
|
// these value must match their native equivalents. See SkXfermode.h
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_CLEAR.png" />
|
|
* <figcaption>Destination pixels covered by the source are cleared to 0.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = 0\)</p>
|
|
* <p>\(C_{out} = 0\)</p>
|
|
*/
|
|
CLEAR (0),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC.png" />
|
|
* <figcaption>The source pixels replace the destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src}\)</p>
|
|
* <p>\(C_{out} = C_{src}\)</p>
|
|
*/
|
|
SRC (1),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST.png" />
|
|
* <figcaption>The source pixels are discarded, leaving the destination intact.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = C_{dst}\)</p>
|
|
*/
|
|
DST (2),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OVER.png" />
|
|
* <figcaption>The source pixels are drawn over the destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
|
|
*/
|
|
SRC_OVER (3),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_OVER.png" />
|
|
* <figcaption>The source pixels are drawn behind the destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{dst} + (1 - \alpha_{dst}) * \alpha_{src}\)</p>
|
|
* <p>\(C_{out} = C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
|
|
*/
|
|
DST_OVER (4),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_IN.png" />
|
|
* <figcaption>Keeps the source pixels that cover the destination pixels,
|
|
* discards the remaining source and destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = C_{src} * \alpha_{dst}\)</p>
|
|
*/
|
|
SRC_IN (5),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_IN.png" />
|
|
* <figcaption>Keeps the destination pixels that cover source pixels,
|
|
* discards the remaining source and destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = C_{dst} * \alpha_{src}\)</p>
|
|
*/
|
|
DST_IN (6),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_OUT.png" />
|
|
* <figcaption>Keeps the source pixels that do not cover destination pixels.
|
|
* Discards source pixels that cover destination pixels. Discards all
|
|
* destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src}\)</p>
|
|
* <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src}\)</p>
|
|
*/
|
|
SRC_OUT (7),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_OUT.png" />
|
|
* <figcaption>Keeps the destination pixels that are not covered by source pixels.
|
|
* Discards destination pixels that are covered by source pixels. Discards all
|
|
* source pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = (1 - \alpha_{src}) * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = (1 - \alpha_{src}) * C_{dst}\)</p>
|
|
*/
|
|
DST_OUT (8),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SRC_ATOP.png" />
|
|
* <figcaption>Discards the source pixels that do not cover destination pixels.
|
|
* Draws remaining source pixels over destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = \alpha_{dst} * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
|
|
*/
|
|
SRC_ATOP (9),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DST_ATOP.png" />
|
|
* <figcaption>Discards the destination pixels that are not covered by source pixels.
|
|
* Draws remaining destination pixels over source pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src}\)</p>
|
|
* <p>\(C_{out} = \alpha_{src} * C_{dst} + (1 - \alpha_{dst}) * C_{src}\)</p>
|
|
*/
|
|
DST_ATOP (10),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_XOR.png" />
|
|
* <figcaption>Discards the source and destination pixels where source pixels
|
|
* cover destination pixels. Draws remaining source pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = (1 - \alpha_{dst}) * \alpha_{src} + (1 - \alpha_{src}) * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst}\)</p>
|
|
*/
|
|
XOR (11),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_DARKEN.png" />
|
|
* <figcaption>Retains the smallest component of the source and
|
|
* destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + min(C_{src}, C_{dst})\)</p>
|
|
*/
|
|
DARKEN (16),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_LIGHTEN.png" />
|
|
* <figcaption>Retains the largest component of the source and
|
|
* destination pixel.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = (1 - \alpha_{dst}) * C_{src} + (1 - \alpha_{src}) * C_{dst} + max(C_{src}, C_{dst})\)</p>
|
|
*/
|
|
LIGHTEN (17),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_MULTIPLY.png" />
|
|
* <figcaption>Multiplies the source and destination pixels.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = C_{src} * C_{dst}\)</p>
|
|
*/
|
|
MULTIPLY (13),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_SCREEN.png" />
|
|
* <figcaption>Adds the source and destination pixels, then subtracts the
|
|
* source pixels multiplied by the destination.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(C_{out} = C_{src} + C_{dst} - C_{src} * C_{dst}\)</p>
|
|
*/
|
|
SCREEN (14),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_ADD.png" />
|
|
* <figcaption>Adds the source pixels to the destination pixels and saturates
|
|
* the result.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = max(0, min(\alpha_{src} + \alpha_{dst}, 1))\)</p>
|
|
* <p>\(C_{out} = max(0, min(C_{src} + C_{dst}, 1))\)</p>
|
|
*/
|
|
ADD (12),
|
|
/**
|
|
* <p>
|
|
* <img src="{@docRoot}reference/android/images/graphics/composite_OVERLAY.png" />
|
|
* <figcaption>Multiplies or screens the source and destination depending on the
|
|
* destination color.</figcaption>
|
|
* </p>
|
|
* <p>\(\alpha_{out} = \alpha_{src} + \alpha_{dst} - \alpha_{src} * \alpha_{dst}\)</p>
|
|
* <p>\(\begin{equation}
|
|
* C_{out} = \begin{cases} 2 * C_{src} * C_{dst} & 2 * C_{dst} \lt \alpha_{dst} \\
|
|
* \alpha_{src} * \alpha_{dst} - 2 (\alpha_{dst} - C_{src}) (\alpha_{src} - C_{dst}) & otherwise \end{cases}
|
|
* \end{equation}\)</p>
|
|
*/
|
|
OVERLAY (15);
|
|
|
|
Mode(int nativeInt) {
|
|
this.nativeInt = nativeInt;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public final int nativeInt;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static int modeToInt(Mode mode) {
|
|
return mode.nativeInt;
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static Mode intToMode(int val) {
|
|
switch (val) {
|
|
default:
|
|
case 0: return Mode.CLEAR;
|
|
case 1: return Mode.SRC;
|
|
case 2: return Mode.DST;
|
|
case 3: return Mode.SRC_OVER;
|
|
case 4: return Mode.DST_OVER;
|
|
case 5: return Mode.SRC_IN;
|
|
case 6: return Mode.DST_IN;
|
|
case 7: return Mode.SRC_OUT;
|
|
case 8: return Mode.DST_OUT;
|
|
case 9: return Mode.SRC_ATOP;
|
|
case 10: return Mode.DST_ATOP;
|
|
case 11: return Mode.XOR;
|
|
case 16: return Mode.DARKEN;
|
|
case 17: return Mode.LIGHTEN;
|
|
case 13: return Mode.MULTIPLY;
|
|
case 14: return Mode.SCREEN;
|
|
case 12: return Mode.ADD;
|
|
case 15: return Mode.OVERLAY;
|
|
}
|
|
}
|
|
}
|