1 /*
2  * Copyright (C) 2007 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 import android.annotation.NonNull;
21 
22 /** A subclass of shader that returns the composition of two other shaders, combined by
23     an {@link android.graphics.Xfermode} subclass.
24 */
25 public class ComposeShader extends Shader {
26 
27     Shader mShaderA;
28     private long mNativeInstanceShaderA;
29     Shader mShaderB;
30     private long mNativeInstanceShaderB;
31     private int mPorterDuffMode;
32 
33     /**
34      * Create a new compose shader, given shaders A, B, and a combining mode.
35      * When the mode is applied, it will be given the result from shader A as its
36      * "dst", and the result from shader B as its "src".
37      *
38      * @param shaderA  The colors from this shader are seen as the "dst" by the mode
39      * @param shaderB  The colors from this shader are seen as the "src" by the mode
40      * @param mode     The mode that combines the colors from the two shaders. If mode
41      *                 is null, then SRC_OVER is assumed.
42      */
43     @Deprecated
ComposeShader(@onNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode)44     public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
45         this(shaderA, shaderB, mode.porterDuffMode);
46     }
47 
48     /**
49      * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
50      * When the mode is applied, it will be given the result from shader A as its
51      * "dst", and the result from shader B as its "src".
52      *
53      * @param shaderA  The colors from this shader are seen as the "dst" by the mode
54      * @param shaderB  The colors from this shader are seen as the "src" by the mode
55      * @param mode     The PorterDuff mode that combines the colors from the two shaders.
56      *
57      */
ComposeShader(@onNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode)58     public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB,
59             @NonNull PorterDuff.Mode mode) {
60         this(shaderA, shaderB, mode.nativeInt);
61     }
62 
63     /**
64      * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
65      * When the mode is applied, it will be given the result from shader A as its
66      * "dst", and the result from shader B as its "src".
67      *
68      * @param shaderA  The colors from this shader are seen as the "dst" by the mode
69      * @param shaderB  The colors from this shader are seen as the "src" by the mode
70      * @param blendMode The blend mode that combines the colors from the two shaders.
71     */
ComposeShader(@onNull Shader shaderA, @NonNull Shader shaderB, @NonNull BlendMode blendMode)72     public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB,
73             @NonNull BlendMode blendMode) {
74         this(shaderA, shaderB, blendMode.getXfermode().porterDuffMode);
75     }
76 
ComposeShader(Shader shaderA, Shader shaderB, int nativeMode)77     private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) {
78         if (shaderA == null || shaderB == null) {
79             throw new IllegalArgumentException("Shader parameters must not be null");
80         }
81 
82         mShaderA = shaderA;
83         mShaderB = shaderB;
84         mPorterDuffMode = nativeMode;
85     }
86 
87     @Override
createNativeInstance(long nativeMatrix)88     long createNativeInstance(long nativeMatrix) {
89         mNativeInstanceShaderA = mShaderA.getNativeInstance();
90         mNativeInstanceShaderB = mShaderB.getNativeInstance();
91         return nativeCreate(nativeMatrix,
92                 mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
93     }
94 
95     /** @hide */
96     @Override
verifyNativeInstance()97     protected void verifyNativeInstance() {
98         if (mShaderA.getNativeInstance() != mNativeInstanceShaderA
99                 || mShaderB.getNativeInstance() != mNativeInstanceShaderB) {
100             // Child shader native instance has been updated,
101             // so our cached native instance is no longer valid - discard it
102             discardNativeInstance();
103         }
104     }
105 
nativeCreate(long nativeMatrix, long nativeShaderA, long nativeShaderB, int porterDuffMode)106     private static native long nativeCreate(long nativeMatrix,
107             long nativeShaderA, long nativeShaderB, int porterDuffMode);
108 }
109