19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik 20b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craikimport android.annotation.NonNull; 21b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik 22e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio/** A subclass of shader that returns the composition of two other shaders, combined by 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project an {@link android.graphics.Xfermode} subclass. 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ComposeShader extends Shader { 26e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio 27b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik Shader mShaderA; 28b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik private long mNativeInstanceShaderA; 29b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik Shader mShaderB; 30b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik private long mNativeInstanceShaderB; 315d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck private int mPorterDuffMode; 32b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik 33b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik /** 34b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * Create a new compose shader, given shaders A, B, and a combining mode. 35b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * When the mode is applied, it will be given the result from shader A as its 36b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * "dst", and the result from shader B as its "src". 37b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * 38b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * @param shaderA The colors from this shader are seen as the "dst" by the mode 39b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * @param shaderB The colors from this shader are seen as the "src" by the mode 40b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * @param mode The mode that combines the colors from the two shaders. If mode 41b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * is null, then SRC_OVER is assumed. 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 43b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) { 445d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck this(shaderA, shaderB, mode.porterDuffMode); 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik /** 48b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * Create a new compose shader, given shaders A, B, and a combining PorterDuff mode. 49b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * When the mode is applied, it will be given the result from shader A as its 50b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * "dst", and the result from shader B as its "src". 51b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * 52b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * @param shaderA The colors from this shader are seen as the "dst" by the mode 53b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * @param shaderB The colors from this shader are seen as the "src" by the mode 54b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik * @param mode The PorterDuff mode that combines the colors from the two shaders. 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 56b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, 57b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik @NonNull PorterDuff.Mode mode) { 585d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck this(shaderA, shaderB, mode.nativeInt); 595d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck } 605d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck 615d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) { 62b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik if (shaderA == null || shaderB == null) { 63b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik throw new IllegalArgumentException("Shader parameters must not be null"); 64b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik } 65b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik 66de0547c07a65b59d5330588cdd8b1e410a613e9cRomain Guy mShaderA = shaderA; 67de0547c07a65b59d5330588cdd8b1e410a613e9cRomain Guy mShaderB = shaderB; 685d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck mPorterDuffMode = nativeMode; 69b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik } 70b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik 71b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik @Override 72b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik long createNativeInstance(long nativeMatrix) { 73b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik mNativeInstanceShaderA = mShaderA.getNativeInstance(); 74b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik mNativeInstanceShaderB = mShaderB.getNativeInstance(); 75b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik return nativeCreate(nativeMatrix, 76b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode); 77b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik } 78b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik 798bde0be1b4772787b98f1def6931877eb3f7991eJohn Reck /** @hide */ 80f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik @Override 818bde0be1b4772787b98f1def6931877eb3f7991eJohn Reck protected void verifyNativeInstance() { 82f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik if (mShaderA.getNativeInstance() != mNativeInstanceShaderA 83f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik || mShaderB.getNativeInstance() != mNativeInstanceShaderB) { 84f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik // Child shader native instance has been updated, 85f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik // so our cached native instance is no longer valid - discard it 86f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik discardNativeInstance(); 87f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik } 88f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik } 89f6b0e60bd07436edb033ffe975030b7c1ee91626Chris Craik 90e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio /** 91e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio * @hide 92e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio */ 93e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio @Override 94e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio protected Shader copy() { 955d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck final ComposeShader copy = new ComposeShader( 965d31a293ad0a832c7b8b445c1a67fb1800e5da32John Reck mShaderA.copy(), mShaderB.copy(), mPorterDuffMode); 97e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio copyLocalMatrix(copy); 98e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio return copy; 99e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio } 100e3c526f4f603e83c5fa8b9e399506b085f5648b7Fabrice Di Meglio 101b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik private static native long nativeCreate(long nativeMatrix, 102b581e6704fc1478bc1dda517502abd3eab2558d6Chris Craik long nativeShaderA, long nativeShaderB, int porterDuffMode); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 104