Shader.java revision 6f085f60e929f4bb5ae7ccbc04cbc23c99ee8850
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 17package android.graphics; 18 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21 22/** 23 * Shader is the based class for objects that return horizontal spans of colors 24 * during drawing. A subclass of Shader is installed in a Paint calling 25 * paint.setShader(shader). After that any object (other than a bitmap) that is 26 * drawn with that paint will get its color(s) from the shader. 27 */ 28public class Shader { 29 /** 30 * @deprecated Use subclass constructors directly instead. 31 */ 32 @Deprecated 33 public Shader() {} 34 35 /** 36 * Current native shader instance. Created and updated lazily when {@link #getNativeInstance()} 37 * is called - otherwise may be out of date with java setters/properties. 38 */ 39 private long mNativeInstance; 40 41 /** 42 * Current matrix - always set to null if local matrix is identity. 43 */ 44 private Matrix mLocalMatrix; 45 46 public enum TileMode { 47 /** 48 * replicate the edge color if the shader draws outside of its 49 * original bounds 50 */ 51 CLAMP (0), 52 /** 53 * repeat the shader's image horizontally and vertically 54 */ 55 REPEAT (1), 56 /** 57 * repeat the shader's image horizontally and vertically, alternating 58 * mirror images so that adjacent images always seam 59 */ 60 MIRROR (2); 61 62 TileMode(int nativeInt) { 63 this.nativeInt = nativeInt; 64 } 65 final int nativeInt; 66 } 67 68 /** 69 * Return true if the shader has a non-identity local matrix. 70 * @param localM Set to the local matrix of the shader, if the shader's matrix is non-null. 71 * @return true if the shader has a non-identity local matrix 72 */ 73 public boolean getLocalMatrix(@NonNull Matrix localM) { 74 if (mLocalMatrix != null) { 75 localM.set(mLocalMatrix); 76 return true; // presence of mLocalMatrix means it's not identity 77 } 78 return false; 79 } 80 81 /** 82 * Set the shader's local matrix. Passing null will reset the shader's 83 * matrix to identity. If the matrix has scale value as 0, the drawing 84 * result is undefined. 85 * 86 * @param localM The shader's new local matrix, or null to specify identity 87 */ 88 public void setLocalMatrix(@Nullable Matrix localM) { 89 if (localM == null || localM.isIdentity()) { 90 if (mLocalMatrix != null) { 91 mLocalMatrix = null; 92 discardNativeInstance(); 93 } 94 } else { 95 if (mLocalMatrix == null) { 96 mLocalMatrix = new Matrix(localM); 97 discardNativeInstance(); 98 } else if (!mLocalMatrix.equals(localM)) { 99 mLocalMatrix.set(localM); 100 discardNativeInstance(); 101 } 102 } 103 } 104 105 long createNativeInstance(long nativeMatrix) { 106 return 0; 107 } 108 109 void discardNativeInstance() { 110 if (mNativeInstance != 0) { 111 nativeSafeUnref(mNativeInstance); 112 mNativeInstance = 0; 113 } 114 } 115 116 /** 117 * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently 118 * constructed native instance is no longer valid. 119 */ 120 void verifyNativeInstance() { 121 } 122 123 @Override 124 protected void finalize() throws Throwable { 125 try { 126 if (mNativeInstance != 0) { 127 nativeSafeUnref(mNativeInstance); 128 } 129 mNativeInstance = -1; 130 } finally { 131 super.finalize(); 132 } 133 } 134 135 /** 136 * @hide 137 */ 138 protected Shader copy() { 139 final Shader copy = new Shader(); 140 copyLocalMatrix(copy); 141 return copy; 142 } 143 144 /** 145 * @hide 146 */ 147 protected void copyLocalMatrix(Shader dest) { 148 dest.mLocalMatrix.set(mLocalMatrix); 149 } 150 151 /** 152 * @hide 153 */ 154 public long getNativeInstance() { 155 if (mNativeInstance == -1) { 156 throw new IllegalStateException("attempting to use a finalized Shader"); 157 } 158 159 // verify mNativeInstance is valid 160 verifyNativeInstance(); 161 162 if (mNativeInstance == 0) { 163 mNativeInstance = createNativeInstance(mLocalMatrix == null 164 ? 0 : mLocalMatrix.native_instance); 165 } 166 return mNativeInstance; 167 } 168 169 private static native void nativeSafeUnref(long nativeInstance); 170} 171