diff options
author | 2024-02-01 17:38:31 +0000 | |
---|---|---|
committer | 2024-02-14 20:07:41 +0000 | |
commit | 3700b100d79434079f87763e64b38c419b09ac2e (patch) | |
tree | 2b6928dd3b64831361eb06dc01492e50830aa59f | |
parent | 70331c8b8a33c00e3cede72f67bb4a6850d434d3 (diff) |
add clipShader API to android.graphics.Canvas
Test: atest CtsUiRenderingTestCases:android.uirendering.cts.testclasses.ShaderClippingTests
Bug: 280116960
Change-Id: Ic78c4b2ca01e6af9e5af757aa64e15e248cadcf8
-rw-r--r-- | core/api/current.txt | 2 | ||||
-rw-r--r-- | graphics/java/android/graphics/Canvas.java | 26 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 11 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.h | 1 | ||||
-rw-r--r-- | libs/hwui/hwui/Canvas.h | 1 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_Canvas.cpp | 18 |
6 files changed, 59 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 7052fd1c08e9..5edfe99570f9 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -15667,6 +15667,7 @@ package android.graphics { method public boolean clipOutRect(@NonNull android.graphics.Rect); method public boolean clipOutRect(float, float, float, float); method public boolean clipOutRect(int, int, int, int); + method @FlaggedApi("com.android.graphics.hwui.flags.clip_shader") public void clipOutShader(@NonNull android.graphics.Shader); method @Deprecated public boolean clipPath(@NonNull android.graphics.Path, @NonNull android.graphics.Region.Op); method public boolean clipPath(@NonNull android.graphics.Path); method @Deprecated public boolean clipRect(@NonNull android.graphics.RectF, @NonNull android.graphics.Region.Op); @@ -15676,6 +15677,7 @@ package android.graphics { method @Deprecated public boolean clipRect(float, float, float, float, @NonNull android.graphics.Region.Op); method public boolean clipRect(float, float, float, float); method public boolean clipRect(int, int, int, int); + method @FlaggedApi("com.android.graphics.hwui.flags.clip_shader") public void clipShader(@NonNull android.graphics.Shader); method public void concat(@Nullable android.graphics.Matrix); method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void concat44(@Nullable android.graphics.Matrix44); method public void disableZ(); diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index b33a5d2dcef8..f3bb21719890 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1128,6 +1128,30 @@ public class Canvas extends BaseCanvas { return false; } + /** + * Intersect the current clip with the specified shader. + * The shader will be treated as an alpha mask, taking the intersection of the two. + * + * @param shader The shader to intersect with the current clip + */ + @FlaggedApi(Flags.FLAG_CLIP_SHADER) + public void clipShader(@NonNull Shader shader) { + nClipShader(mNativeCanvasWrapper, shader.getNativeInstance(), + Region.Op.INTERSECT.nativeInt); + } + + /** + * Set the clip to the difference of the current clip and the shader. + * The shader will be treated as an alpha mask, taking the difference of the two. + * + * @param shader The shader to intersect with the current clip + */ + @FlaggedApi(Flags.FLAG_CLIP_SHADER) + public void clipOutShader(@NonNull Shader shader) { + nClipShader(mNativeCanvasWrapper, shader.getNativeInstance(), + Region.Op.DIFFERENCE.nativeInt); + } + public @Nullable DrawFilter getDrawFilter() { return mDrawFilter; } @@ -1472,6 +1496,8 @@ public class Canvas extends BaseCanvas { @CriticalNative private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp); @CriticalNative + private static native void nClipShader(long nativeCanvas, long nativeShader, int regionOp); + @CriticalNative private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter); @CriticalNative private static native void nGetMatrix(long nativeCanvas, long nativeMatrix); diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 14b8d8d0aa12..0b739c361d64 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -70,6 +70,8 @@ public: : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {} Clip(const SkPath& path, SkClipOp op, const SkMatrix& m) : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {} + Clip(const sk_sp<SkShader> shader, SkClipOp op, const SkMatrix& m) + : mType(Type::Shader), mOp(op), mMatrix(m), mShader(shader) {} void apply(SkCanvas* canvas) const { canvas->setMatrix(mMatrix); @@ -86,6 +88,8 @@ public: // Ensure path clips are anti-aliased canvas->clipPath(mPath.value(), mOp, true); break; + case Type::Shader: + canvas->clipShader(mShader, mOp); } } @@ -94,6 +98,7 @@ private: Rect, RRect, Path, + Shader, }; Type mType; @@ -103,6 +108,7 @@ private: // These are logically a union (tracked separately due to non-POD path). std::optional<SkPath> mPath; SkRRect mRRect; + sk_sp<SkShader> mShader; }; Canvas* Canvas::create_canvas(const SkBitmap& bitmap) { @@ -413,6 +419,11 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) { return !mCanvas->isClipEmpty(); } +void SkiaCanvas::clipShader(sk_sp<SkShader> shader, SkClipOp op) { + this->recordClip(shader, op); + mCanvas->clipShader(shader, op); +} + bool SkiaCanvas::replaceClipRect_deprecated(float left, float top, float right, float bottom) { SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 5e3553bbbbb4..4a012bc601c9 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -97,6 +97,7 @@ public: virtual bool quickRejectPath(const SkPath& path) const override; virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; + virtual void clipShader(sk_sp<SkShader> shader, SkClipOp op) override; virtual bool replaceClipRect_deprecated(float left, float top, float right, float bottom) override; virtual bool replaceClipPath_deprecated(const SkPath* path) override; diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 20e3ad2c8202..14b4f584f0f3 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -188,6 +188,7 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) = 0; virtual bool clipPath(const SkPath* path, SkClipOp op) = 0; + virtual void clipShader(sk_sp<SkShader> shader, SkClipOp op) = 0; // Resets clip to wide open, used to emulate the now-removed SkClipOp::kReplace on // apps with compatibility < P. Canvases for version P and later are restricted to // intersect and difference at the Java level, matching SkClipOp's definition. diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp index e5bdeeea75be..1fc34d633370 100644 --- a/libs/hwui/jni/android_graphics_Canvas.cpp +++ b/libs/hwui/jni/android_graphics_Canvas.cpp @@ -261,6 +261,23 @@ static jboolean clipPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong pat return nonEmptyClip ? JNI_TRUE : JNI_FALSE; } +static void clipShader(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong shaderHandle, + jint opHandle) { + SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle); + sk_sp<SkShader> shader = sk_ref_sp(reinterpret_cast<SkShader*>(shaderHandle)); + switch (rgnOp) { + case SkRegion::Op::kIntersect_Op: + case SkRegion::Op::kDifference_Op: + get_canvas(canvasHandle)->clipShader(shader, static_cast<SkClipOp>(rgnOp)); + break; + default: + ALOGW("Ignoring unsupported clip operation %d", opHandle); + SkRect clipBounds; // ignored + get_canvas(canvasHandle)->getClipBounds(&clipBounds); + break; + } +} + static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) { SkBlendMode mode = static_cast<SkBlendMode>(modeHandle); get_canvas(canvasHandle)->drawColor(color, mode); @@ -797,6 +814,7 @@ static const JNINativeMethod gMethods[] = { {"nQuickReject", "(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, {"nClipRect", "(JFFFFI)Z", (void*)CanvasJNI::clipRect}, {"nClipPath", "(JJI)Z", (void*)CanvasJNI::clipPath}, + {"nClipShader", "(JJI)V", (void*)CanvasJNI::clipShader}, {"nSetDrawFilter", "(JJ)V", (void*)CanvasJNI::setPaintFilter}, }; |