• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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