diff --git a/shell/platform/android/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorsStack.java b/shell/platform/android/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorsStack.java index 300d9ab5e2c9f..c8a7fb181e719 100644 --- a/shell/platform/android/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorsStack.java +++ b/shell/platform/android/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorsStack.java @@ -47,6 +47,7 @@ public class FlutterMutator { @Nullable private Matrix matrix; @Nullable private Rect rect; @Nullable private Path path; + @Nullable private float[] radiis; private FlutterMutatorType type; @@ -60,6 +61,19 @@ public FlutterMutator(Rect rect) { this.rect = rect; } + /** + * Initialize a clip rrect mutator. + * + * @param rect the rect of the rrect + * @param radiis the radiis of the rrect. Array of 8 values, 4 pairs of [X,Y]. This value cannot + * be null. + */ + public FlutterMutator(Rect rect, float[] radiis) { + this.type = FlutterMutatorType.CLIP_RRECT; + this.rect = rect; + this.radiis = radiis; + } + /** * Initialize a clip path mutator. * @@ -154,6 +168,26 @@ public void pushClipRect(int left, int top, int right, int bottom) { finalClippingPaths.add(path); } + /** + * Push a clipRRect {@link io.flutter.embedding.engine.mutatorsstack.Mutator} to the stack. + * + * @param left left offset of the rrect. + * @param top top offset of the rrect. + * @param right right position of the rrect. + * @param bottom bottom position of the rrect. + * @param radiis the radiis of the rrect. It must be size of 8, including an x and y for each + * corner. + */ + public void pushClipRRect(int left, int top, int right, int bottom, float[] radiis) { + Rect rect = new Rect(left, top, right, bottom); + FlutterMutator mutator = new FlutterMutator(rect, radiis); + mutators.add(mutator); + Path path = new Path(); + path.addRoundRect(new RectF(rect), radiis, Path.Direction.CCW); + path.transform(finalMatrix); + finalClippingPaths.add(path); + } + /** * Get a list of all the raw mutators. The 0 index of the returned list is the top of the stack. */ diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index ac3c50e83d75c..d83c615043332 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -122,6 +122,7 @@ static fml::jni::ScopedJavaGlobalRef* g_mutators_stack_class = nullptr; static jmethodID g_mutators_stack_init_method = nullptr; static jmethodID g_mutators_stack_push_transform_method = nullptr; static jmethodID g_mutators_stack_push_cliprect_method = nullptr; +static jmethodID g_mutators_stack_push_cliprrect_method = nullptr; // Called By Java static jlong AttachJNI(JNIEnv* env, @@ -918,7 +919,15 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { g_mutators_stack_class->obj(), "pushClipRect", "(IIII)V"); if (g_mutators_stack_push_cliprect_method == nullptr) { FML_LOG(ERROR) - << "Could not locate FlutterMutatorsStack.pushCilpRect method"; + << "Could not locate FlutterMutatorsStack.pushClipRect method"; + return false; + } + + g_mutators_stack_push_cliprrect_method = env->GetMethodID( + g_mutators_stack_class->obj(), "pushClipRRect", "(IIII[F)V"); + if (g_mutators_stack_push_cliprect_method == nullptr) { + FML_LOG(ERROR) + << "Could not locate FlutterMutatorsStack.pushClipRRect method"; return false; } @@ -1288,9 +1297,28 @@ void PlatformViewAndroidJNIImpl::FlutterViewOnDisplayPlatformView( static_cast(rect.right()), static_cast(rect.bottom())); break; } + case clip_rrect: { + const SkRRect& rrect = (*iter)->GetRRect(); + const SkRect& rect = rrect.rect(); + const SkVector& upper_left = rrect.radii(SkRRect::kUpperLeft_Corner); + const SkVector& upper_right = rrect.radii(SkRRect::kUpperRight_Corner); + const SkVector& lower_right = rrect.radii(SkRRect::kLowerRight_Corner); + const SkVector& lower_left = rrect.radii(SkRRect::kLowerLeft_Corner); + SkScalar radiis[8] = { + upper_left.x(), upper_left.y(), upper_right.x(), upper_right.y(), + lower_right.x(), lower_right.y(), lower_left.x(), lower_left.y(), + }; + fml::jni::ScopedJavaLocalRef radiisArray( + env, env->NewFloatArray(8)); + env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis); + env->CallVoidMethod( + mutatorsStack, g_mutators_stack_push_cliprrect_method, + (int)rect.left(), (int)rect.top(), (int)rect.right(), + (int)rect.bottom(), radiisArray.obj()); + break; + } // TODO(cyanglaz): Implement other mutators. // https://github.com/flutter/flutter/issues/58426 - case clip_rrect: case clip_path: case opacity: break; diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png index ab4c574c78b58..4b39abeb9b196 100644 Binary files a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png and b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png differ