Shader.java revision 6097eca72134034fcc6086c110673b5df94913b0
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. 84 * 85 * @param localM The shader's new local matrix, or null to specify identity 86 */ 87 public void setLocalMatrix(@Nullable Matrix localM) { 88 if (localM == null || localM.isIdentity()) { 89 if (mLocalMatrix != null) { 90 mLocalMatrix = null; 91 discardNativeInstance(); 92 } 93 } else { 94 if (mLocalMatrix == null) { 95 mLocalMatrix = new Matrix(localM); 96 discardNativeInstance(); 97 } else if (!mLocalMatrix.equals(localM)) { 98 mLocalMatrix.set(localM); 99 discardNativeInstance(); 100 } 101 } 102 } 103 104 long createNativeInstance(long nativeMatrix) { 105 return 0; 106 } 107 108 void discardNativeInstance() { 109 if (mNativeInstance != 0) { 110 nativeSafeUnref(mNativeInstance); 111 mNativeInstance = 0; 112 } 113 } 114 115 /** 116 * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently 117 * constructed native instance is no longer valid. 118 */ 119 void verifyNativeInstance() { 120 } 121 122 @Override 123 protected void finalize() throws Throwable { 124 try { 125 if (mNativeInstance != 0) { 126 nativeSafeUnref(mNativeInstance); 127 } 128 mNativeInstance = -1; 129 } finally { 130 super.finalize(); 131 } 132 } 133 134 /** 135 * @hide 136 */ 137 protected Shader copy() { 138 final Shader copy = new Shader(); 139 copyLocalMatrix(copy); 140 return copy; 141 } 142 143 /** 144 * @hide 145 */ 146 protected void copyLocalMatrix(Shader dest) { 147 dest.mLocalMatrix.set(mLocalMatrix); 148 } 149 150 /** 151 * @hide 152 */ 153 public long getNativeInstance() { 154 if (mNativeInstance == -1) { 155 throw new IllegalStateException("attempting to use a finalized Shader"); 156 } 157 158 // verify mNativeInstance is valid 159 verifyNativeInstance(); 160 161 if (mNativeInstance == 0) { 162 mNativeInstance = createNativeInstance(mLocalMatrix == null 163 ? 0 : mLocalMatrix.native_instance); 164 } 165 return mNativeInstance; 166 } 167 168 private static native void nativeSafeUnref(long nativeInstance); 169} 170