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 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 22 import java.lang.annotation.Retention; 23 import java.lang.annotation.RetentionPolicy; 24 25 /** 26 * Shader used to draw a bitmap as a texture. The bitmap can be repeated or 27 * mirrored by setting the tiling mode. 28 */ 29 public class BitmapShader extends Shader { 30 /** 31 * Prevent garbage collection. 32 */ 33 /*package*/ Bitmap mBitmap; 34 35 private int mTileX; 36 private int mTileY; 37 38 /** @hide */ 39 @IntDef(prefix = {"FILTER_MODE"}, value = { 40 FILTER_MODE_DEFAULT, 41 FILTER_MODE_NEAREST, 42 FILTER_MODE_LINEAR 43 }) 44 @Retention(RetentionPolicy.SOURCE) 45 public @interface FilterMode {} 46 47 /** 48 * This FilterMode value will respect the value of the Paint#isFilterBitmap flag while the 49 * shader is attached to the Paint. 50 * 51 * <p>The exception to this rule is when a Shader is attached as input to a RuntimeShader. In 52 * that case this mode will default to FILTER_MODE_NEAREST.</p> 53 * 54 * @see #setFilterMode(int) 55 */ 56 public static final int FILTER_MODE_DEFAULT = 0; 57 /** 58 * This FilterMode value will cause the shader to sample from the nearest pixel to the requested 59 * sample point. 60 * 61 * <p>This value will override the effect of Paint#isFilterBitmap.</p> 62 * 63 * @see #setFilterMode(int) 64 */ 65 public static final int FILTER_MODE_NEAREST = 1; 66 /** 67 * This FilterMode value will cause the shader to interpolate the output of the shader from a 68 * 2x2 grid of pixels nearest to the sample point (i.e. bilinear interpolation). 69 * 70 * <p>This value will override the effect of Paint#isFilterBitmap.</p> 71 * 72 * @see #setFilterMode(int) 73 */ 74 public static final int FILTER_MODE_LINEAR = 2; 75 76 @FilterMode 77 private int mFilterMode; 78 79 /* 80 * This is cache of the last value from the Paint of bitmap-filtering. 81 * In the future, BitmapShaders will carry their own (expanded) data for this 82 * (e.g. including mipmap options, or bicubic weights) 83 * 84 * When that happens, this bool will become those extended values, and we will 85 * need to track whether this Shader was created with those new constructors, 86 * or from the current "legacy" constructor, which (for compatibility) will 87 * still need to know the Paint's setting. 88 * 89 * When the filter Paint setting is finally gone, we will be able to remove 90 * the filterFromPaint parameter currently being passed to createNativeInstance() 91 * and shouldDiscardNativeInstance(), as shaders will always know their filter 92 * settings. 93 */ 94 private boolean mFilterFromPaint; 95 96 /** 97 * Stores whether or not the contents of this shader's bitmap will be sampled 98 * without modification or if the bitmap's properties, like colorspace and 99 * premultiplied alpha, will be respected when sampling from the bitmap's buffer. 100 */ 101 private boolean mIsDirectSampled; 102 103 private boolean mRequestDirectSampling; 104 105 /** 106 * Call this to create a new shader that will draw with a bitmap. 107 * 108 * @param bitmap The bitmap to use inside the shader 109 * @param tileX The tiling mode for x to draw the bitmap in. 110 * @param tileY The tiling mode for y to draw the bitmap in. 111 */ BitmapShader(@onNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)112 public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) { 113 this(bitmap, tileX.nativeInt, tileY.nativeInt); 114 } 115 BitmapShader(Bitmap bitmap, int tileX, int tileY)116 private BitmapShader(Bitmap bitmap, int tileX, int tileY) { 117 if (bitmap == null) { 118 throw new IllegalArgumentException("Bitmap must be non-null"); 119 } 120 mBitmap = bitmap; 121 mTileX = tileX; 122 mTileY = tileY; 123 mFilterMode = FILTER_MODE_DEFAULT; 124 mFilterFromPaint = false; 125 mIsDirectSampled = false; 126 mRequestDirectSampling = false; 127 } 128 129 /** 130 * Returns the filter mode used when sampling from this shader 131 */ 132 @FilterMode getFilterMode()133 public int getFilterMode() { 134 return mFilterMode; 135 } 136 137 /** 138 * Set the filter mode to be used when sampling from this shader 139 */ setFilterMode(@ilterMode int mode)140 public void setFilterMode(@FilterMode int mode) { 141 if (mode != mFilterMode) { 142 mFilterMode = mode; 143 discardNativeInstance(); 144 } 145 } 146 147 /** @hide */ getNativeInstanceWithDirectSampling()148 /* package */ synchronized long getNativeInstanceWithDirectSampling() { 149 mRequestDirectSampling = true; 150 return getNativeInstance(); 151 } 152 153 /** @hide */ 154 @Override createNativeInstance(long nativeMatrix, boolean filterFromPaint)155 protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) { 156 boolean enableLinearFilter = mFilterMode == FILTER_MODE_LINEAR; 157 if (mFilterMode == FILTER_MODE_DEFAULT) { 158 mFilterFromPaint = filterFromPaint; 159 enableLinearFilter = mFilterFromPaint; 160 } 161 162 mIsDirectSampled = mRequestDirectSampling; 163 mRequestDirectSampling = false; 164 165 return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY, 166 enableLinearFilter, mIsDirectSampled); 167 } 168 169 /** @hide */ 170 @Override shouldDiscardNativeInstance(boolean filterFromPaint)171 protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) { 172 return mIsDirectSampled != mRequestDirectSampling 173 || (mFilterMode == FILTER_MODE_DEFAULT && mFilterFromPaint != filterFromPaint); 174 } 175 nativeCreate(long nativeMatrix, long bitmapHandle, int shaderTileModeX, int shaderTileModeY, boolean filter, boolean isDirectSampled)176 private static native long nativeCreate(long nativeMatrix, long bitmapHandle, 177 int shaderTileModeX, int shaderTileModeY, boolean filter, boolean isDirectSampled); 178 } 179 180