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