Use SkSamplingOptions when creating image-shader
Test: make Change-Id: Ie979cdb10263a08ea3d8c817234b94c9b61abb76
This commit is contained in:
@@ -31,6 +31,23 @@ public class BitmapShader extends Shader {
|
||||
private int mTileX;
|
||||
private int mTileY;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Call this to create a new shader that will draw with a bitmap.
|
||||
*
|
||||
@@ -49,14 +66,24 @@ public class BitmapShader extends Shader {
|
||||
mBitmap = bitmap;
|
||||
mTileX = tileX;
|
||||
mTileY = tileY;
|
||||
mFilterFromPaint = false;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY);
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
mFilterFromPaint = filterFromPaint;
|
||||
return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY,
|
||||
mFilterFromPaint);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
|
||||
return mFilterFromPaint != filterFromPaint;
|
||||
}
|
||||
|
||||
private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
|
||||
int shaderTileModeX, int shaderTileModeY);
|
||||
int shaderTileModeX, int shaderTileModeY, boolean filter);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,16 +69,18 @@ public final class BlurShader extends Shader {
|
||||
|
||||
/** @hide **/
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
mNativeInputShader = mInputShader != null ? mInputShader.getNativeInstance() : 0;
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
mNativeInputShader = mInputShader != null
|
||||
? mInputShader.getNativeInstance(filterFromPaint) : 0;
|
||||
return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader,
|
||||
mEdgeTreatment.nativeInt);
|
||||
}
|
||||
|
||||
/** @hide **/
|
||||
@Override
|
||||
protected boolean shouldDiscardNativeInstance() {
|
||||
long currentNativeInstance = mInputShader != null ? mInputShader.getNativeInstance() : 0;
|
||||
protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
|
||||
long currentNativeInstance = mInputShader != null
|
||||
? mInputShader.getNativeInstance(filterFromPaint) : 0;
|
||||
return mNativeInputShader != currentNativeInstance;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,18 +86,18 @@ public class ComposeShader extends Shader {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
mNativeInstanceShaderA = mShaderA.getNativeInstance();
|
||||
mNativeInstanceShaderB = mShaderB.getNativeInstance();
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
mNativeInstanceShaderA = mShaderA.getNativeInstance(filterFromPaint);
|
||||
mNativeInstanceShaderB = mShaderB.getNativeInstance(filterFromPaint);
|
||||
return nativeCreate(nativeMatrix,
|
||||
mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected boolean shouldDiscardNativeInstance() {
|
||||
return mShaderA.getNativeInstance() != mNativeInstanceShaderA
|
||||
|| mShaderB.getNativeInstance() != mNativeInstanceShaderB;
|
||||
protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
|
||||
return mShaderA.getNativeInstance(filterFromPaint) != mNativeInstanceShaderA
|
||||
|| mShaderB.getNativeInstance(filterFromPaint) != mNativeInstanceShaderB;
|
||||
}
|
||||
|
||||
private static native long nativeCreate(long nativeMatrix,
|
||||
|
||||
@@ -154,7 +154,7 @@ public class LinearGradient extends Shader {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1,
|
||||
mColorLongs, mPositions, mTileMode.nativeInt,
|
||||
colorSpace().getNativeInstance());
|
||||
|
||||
@@ -698,7 +698,8 @@ public class Paint {
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public synchronized long getNativeInstance() {
|
||||
long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
|
||||
boolean filter = isFilterBitmap();
|
||||
long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance(filter);
|
||||
if (newNativeShader != mNativeShader) {
|
||||
mNativeShader = newNativeShader;
|
||||
nSetShader(mNativePaint, mNativeShader);
|
||||
|
||||
@@ -207,7 +207,7 @@ public class RadialGradient extends Shader {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius,
|
||||
mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance());
|
||||
}
|
||||
|
||||
@@ -105,10 +105,10 @@ public class RuntimeShader extends Shader {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
|
||||
for (int i = 0; i < mInputShaders.length; i++) {
|
||||
nativeShaders[i] = mInputShaders[i].getNativeInstance();
|
||||
nativeShaders[i] = mInputShaders[i].getNativeInstance(filterFromPaint);
|
||||
}
|
||||
|
||||
return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
|
||||
|
||||
@@ -148,7 +148,7 @@ public class Shader {
|
||||
/**
|
||||
* @hide Only to be used by subclasses in the graphics package.
|
||||
*/
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ public class Shader {
|
||||
* constructed native instance is still valid.
|
||||
* @hide Only to be used by subclasses in the graphics package.
|
||||
*/
|
||||
protected boolean shouldDiscardNativeInstance() {
|
||||
protected boolean shouldDiscardNativeInstance(boolean filterBitmap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -182,14 +182,14 @@ public class Shader {
|
||||
* @hide so it can be called by android.graphics.drawable but must not be called from outside
|
||||
* the module.
|
||||
*/
|
||||
public synchronized final long getNativeInstance() {
|
||||
if (shouldDiscardNativeInstance()) {
|
||||
public final synchronized long getNativeInstance(boolean filterFromPaint) {
|
||||
if (shouldDiscardNativeInstance(filterFromPaint)) {
|
||||
discardNativeInstanceLocked();
|
||||
}
|
||||
|
||||
if (mNativeInstance == 0) {
|
||||
mNativeInstance = createNativeInstance(mLocalMatrix == null
|
||||
? 0 : mLocalMatrix.ni());
|
||||
? 0 : mLocalMatrix.ni(), filterFromPaint);
|
||||
if (mNativeInstance != 0) {
|
||||
mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
|
||||
this, mNativeInstance);
|
||||
@@ -198,6 +198,15 @@ public class Shader {
|
||||
return mNativeInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide so it can be called by android.graphics.drawable but must not be called from outside
|
||||
* the module.
|
||||
*/
|
||||
public final long getNativeInstance() {
|
||||
// If the caller has no paint flag for filtering bitmaps, we just pass false
|
||||
return getNativeInstance(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide Only to be called by subclasses in the android.graphics package.
|
||||
*/
|
||||
|
||||
@@ -133,7 +133,7 @@ public class SweepGradient extends Shader {
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected long createNativeInstance(long nativeMatrix) {
|
||||
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
|
||||
return nativeCreate(nativeMatrix, mCx, mCy, mColorLongs, mPositions,
|
||||
colorSpace().getNativeInstance());
|
||||
}
|
||||
|
||||
@@ -669,7 +669,10 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
|
||||
if (paint) {
|
||||
pnt = *paint;
|
||||
}
|
||||
pnt.setShader(bitmap.makeImage()->makeShader());
|
||||
SkSamplingOptions sampling(pnt.isFilterBitmap() ? SkFilterMode::kLinear
|
||||
: SkFilterMode::kNearest,
|
||||
SkMipmapMode::kNone);
|
||||
pnt.setShader(bitmap.makeImage()->makeShader(sampling));
|
||||
auto v = builder.detach();
|
||||
apply_looper(&pnt, [&](const SkPaint& p) {
|
||||
mCanvas->drawVertices(v, SkBlendMode::kModulate, p);
|
||||
|
||||
@@ -137,6 +137,9 @@ public:
|
||||
bool isDevKern() const { return mDevKern; }
|
||||
void setDevKern(bool d) { mDevKern = d; }
|
||||
|
||||
// Deprecated -- bitmapshaders will be taking this flag explicitly
|
||||
bool isFilterBitmap() const { return this->getFilterQuality() != kNone_SkFilterQuality; }
|
||||
|
||||
// The Java flags (Paint.java) no longer fit into the native apis directly.
|
||||
// These methods handle converting to and from them and the native representations
|
||||
// in android::Paint.
|
||||
@@ -149,7 +152,7 @@ public:
|
||||
// The only respected flags are : [ antialias, dither, filterBitmap ]
|
||||
static uint32_t GetSkPaintJavaFlags(const SkPaint&);
|
||||
static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
|
||||
|
||||
|
||||
private:
|
||||
SkFont mFont;
|
||||
sk_sp<SkDrawLooper> mLooper;
|
||||
|
||||
@@ -61,7 +61,7 @@ static jlong Shader_getNativeFinalizer(JNIEnv*, jobject) {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
|
||||
jint tileModeX, jint tileModeY) {
|
||||
jint tileModeX, jint tileModeY, bool filter) {
|
||||
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
|
||||
sk_sp<SkImage> image;
|
||||
if (bitmapHandle) {
|
||||
@@ -74,8 +74,10 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j
|
||||
SkBitmap bitmap;
|
||||
image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
|
||||
}
|
||||
SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,
|
||||
SkMipmapMode::kNone);
|
||||
sk_sp<SkShader> shader = image->makeShader(
|
||||
(SkTileMode)tileModeX, (SkTileMode)tileModeY);
|
||||
(SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
|
||||
ThrowIAE_IfNull(env, shader.get());
|
||||
|
||||
if (matrix) {
|
||||
@@ -291,7 +293,7 @@ static const JNINativeMethod gShaderMethods[] = {
|
||||
};
|
||||
|
||||
static const JNINativeMethod gBitmapShaderMethods[] = {
|
||||
{ "nativeCreate", "(JJII)J", (void*)BitmapShader_constructor },
|
||||
{ "nativeCreate", "(JJIIZ)J", (void*)BitmapShader_constructor },
|
||||
};
|
||||
|
||||
static const JNINativeMethod gLinearGradientMethods[] = {
|
||||
|
||||
@@ -44,15 +44,16 @@ public:
|
||||
skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
|
||||
});
|
||||
|
||||
SkSamplingOptions sampling;
|
||||
Paint paint;
|
||||
sk_sp<SkImage> image = hwuiBitmap->makeImage();
|
||||
sk_sp<SkShader> repeatShader =
|
||||
image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
|
||||
image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, sampling);
|
||||
paint.setShader(std::move(repeatShader));
|
||||
canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
|
||||
|
||||
sk_sp<SkShader> mirrorShader =
|
||||
image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror);
|
||||
image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror, sampling);
|
||||
paint.setShader(std::move(mirrorShader));
|
||||
canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,6 @@ public:
|
||||
|
||||
sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
|
||||
sk_sp<SkImage> image = bitmap.makeImage();
|
||||
return image->makeShader();
|
||||
return image->makeShader(SkSamplingOptions());
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user