script-astra/Android/Sdk/sources/android-35/android/graphics/BitmapShader.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

242 lines
8.8 KiB
Java

/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.graphics;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.graphics.hwui.flags.Flags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Shader used to draw a bitmap as a texture. The bitmap can be repeated or
* mirrored by setting the tiling mode.
*/
public class BitmapShader extends Shader {
/**
* Prevent garbage collection.
*/
/*package*/ Bitmap mBitmap;
private Gainmap mOverrideGainmap;
private int mTileX;
private int mTileY;
/** @hide */
@IntDef(prefix = {"FILTER_MODE"}, value = {
FILTER_MODE_DEFAULT,
FILTER_MODE_NEAREST,
FILTER_MODE_LINEAR
})
@Retention(RetentionPolicy.SOURCE)
public @interface FilterMode {}
/**
* This FilterMode value will respect the value of the Paint#isFilterBitmap flag while the
* shader is attached to the Paint.
*
* <p>The exception to this rule is when a Shader is attached as input to a RuntimeShader. In
* that case this mode will default to FILTER_MODE_NEAREST.</p>
*
* @see #setFilterMode(int)
*/
public static final int FILTER_MODE_DEFAULT = 0;
/**
* This FilterMode value will cause the shader to sample from the nearest pixel to the requested
* sample point.
*
* <p>This value will override the effect of Paint#isFilterBitmap.</p>
*
* @see #setFilterMode(int)
*/
public static final int FILTER_MODE_NEAREST = 1;
/**
* This FilterMode value will cause the shader to interpolate the output of the shader from a
* 2x2 grid of pixels nearest to the sample point (i.e. bilinear interpolation).
*
* <p>This value will override the effect of Paint#isFilterBitmap.</p>
*
* @see #setFilterMode(int)
*/
public static final int FILTER_MODE_LINEAR = 2;
@FilterMode
private int mFilterMode;
/*
* This is cache of the last value from the Paint of bitmap-filtering.
* In the future, BitmapShaders will carry their own (expanded) data for this
* (e.g. including mipmap options, or bicubic weights)
*
* When that happens, this bool will become those extended values, and we will
* need to track whether this Shader was created with those new constructors,
* or from the current "legacy" constructor, which (for compatibility) will
* still need to know the Paint's setting.
*
* When the filter Paint setting is finally gone, we will be able to remove
* the filterFromPaint parameter currently being passed to createNativeInstance()
* and shouldDiscardNativeInstance(), as shaders will always know their filter
* settings.
*/
private boolean mFilterFromPaint;
/**
* Stores whether or not the contents of this shader's bitmap will be sampled
* without modification or if the bitmap's properties, like colorspace and
* premultiplied alpha, will be respected when sampling from the bitmap's buffer.
*/
private boolean mIsDirectSampled;
private boolean mRequestDirectSampling;
private int mMaxAniso = 0;
/**
* Call this to create a new shader that will draw with a bitmap.
*
* @param bitmap The bitmap to use inside the shader
* @param tileX The tiling mode for x to draw the bitmap in.
* @param tileY The tiling mode for y to draw the bitmap in.
*/
public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
this(bitmap, tileX.nativeInt, tileY.nativeInt);
}
private BitmapShader(Bitmap bitmap, int tileX, int tileY) {
if (bitmap == null) {
throw new IllegalArgumentException("Bitmap must be non-null");
}
bitmap.checkRecycled("Cannot create BitmapShader for recycled bitmap");
mBitmap = bitmap;
mTileX = tileX;
mTileY = tileY;
mFilterMode = FILTER_MODE_DEFAULT;
mFilterFromPaint = false;
mIsDirectSampled = false;
mRequestDirectSampling = false;
}
/**
* Returns the filter mode used when sampling from this shader
*/
@FilterMode
public int getFilterMode() {
return mFilterMode;
}
/**
* Set the filter mode to be used when sampling from this shader. If this is configured
* then the anisotropic filtering value specified in any previous call to
* {@link #setMaxAnisotropy(int)} is ignored.
*/
public void setFilterMode(@FilterMode int mode) {
if (mode != mFilterMode) {
mFilterMode = mode;
mMaxAniso = 0;
discardNativeInstance();
}
}
/**
* Enables and configures the max anisotropy sampling value. If this value is configured,
* {@link #setFilterMode(int)} is ignored.
*
* Anisotropic filtering can enhance visual quality by removing aliasing effects of images
* that are at oblique viewing angles. This value is typically consumed as a power of 2 and
* anisotropic values of the next power of 2 typically provide twice the quality improvement
* as the previous value. For example, a sampling value of 4 would provide twice the improvement
* of a sampling value of 2. It is important to note that higher sampling values reach
* diminishing returns as the improvements between 8 and 16 can be slight.
*
* @param maxAnisotropy The Anisotropy value to use for filtering. Must be greater than 0.
*/
public void setMaxAnisotropy(@IntRange(from = 1) int maxAnisotropy) {
if (mMaxAniso != maxAnisotropy && maxAnisotropy > 0) {
mMaxAniso = maxAnisotropy;
mFilterMode = FILTER_MODE_DEFAULT;
discardNativeInstance();
}
}
/**
* Draws the BitmapShader with a copy of the given gainmap instead of the gainmap on the Bitmap
* the shader was constructed from
*
* @param overrideGainmap The gainmap to draw instead, null to use any gainmap on the Bitmap
*/
@FlaggedApi(Flags.FLAG_GAINMAP_ANIMATIONS)
public void setOverrideGainmap(@Nullable Gainmap overrideGainmap) {
if (!Flags.gainmapAnimations()) throw new IllegalStateException("API not available");
if (overrideGainmap == null) {
mOverrideGainmap = null;
} else {
mOverrideGainmap = new Gainmap(overrideGainmap, overrideGainmap.getGainmapContents());
}
discardNativeInstance();
}
/**
* Returns the current max anisotropic filtering value configured by
* {@link #setFilterMode(int)}. If {@link #setFilterMode(int)} is invoked this returns zero.
*/
public int getMaxAnisotropy() {
return mMaxAniso;
}
/** @hide */
/* package */ synchronized long getNativeInstanceWithDirectSampling() {
mRequestDirectSampling = true;
return getNativeInstance();
}
/** @hide */
@Override
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
mBitmap.checkRecycled("BitmapShader's bitmap has been recycled");
boolean enableLinearFilter = mFilterMode == FILTER_MODE_LINEAR;
if (mFilterMode == FILTER_MODE_DEFAULT) {
mFilterFromPaint = filterFromPaint;
enableLinearFilter = mFilterFromPaint;
}
mIsDirectSampled = mRequestDirectSampling;
mRequestDirectSampling = false;
return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX,
mTileY, mMaxAniso, enableLinearFilter, mIsDirectSampled,
mOverrideGainmap != null ? mOverrideGainmap.mNativePtr : 0);
}
/** @hide */
@Override
protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
return mIsDirectSampled != mRequestDirectSampling
|| (mFilterMode == FILTER_MODE_DEFAULT && mFilterFromPaint != filterFromPaint);
}
private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
int shaderTileModeX, int shaderTileModeY, int maxAniso, boolean filter,
boolean isDirectSampled, long overrideGainmapHandle);
}