Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit bd92e72

Browse files
author
Chris Yang
committed
draft
fix rename unittest
1 parent 19fe86c commit bd92e72

7 files changed

Lines changed: 239 additions & 20 deletions

File tree

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,52 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
3232
}
3333
@end
3434

35-
// Determines if the final `clipBounds` from a clipRect/clipRRect/clipPath mutator contains the
35+
// Determines if the `clip_rect` from a clipRect mutator contains the
3636
// `platformview_boundingrect`.
3737
//
38-
// `clip_bounds` is the bounding rect of the rect/rrect/path in the clipRect/clipRRect/clipPath
39-
// mutator. This rect is in its own coordinate space. The rect needs to be transformed by
38+
// `clip_rect` is in its own coordinate space. The rect needs to be transformed by
4039
// `transform_matrix` to be in the coordinate space where the PlatformView is displayed.
4140
//
4241
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate
4342
// space where the PlatformView is displayed.
44-
static bool ClipBoundsContainsPlatformViewBoundingRect(const SkRect& clip_bounds,
45-
const SkRect& platformview_boundingrect,
46-
const SkMatrix& transform_matrix) {
47-
SkRect transforme_clip_bounds = transform_matrix.mapRect(clip_bounds);
48-
return transforme_clip_bounds.contains(platformview_boundingrect);
43+
static bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect,
44+
const SkRect& platformview_boundingrect,
45+
const SkMatrix& transform_matrix) {
46+
SkRect transformed_rect = transform_matrix.mapRect(clip_rect);
47+
return transformed_rect.contains(platformview_boundingrect);
48+
}
49+
50+
// Determines if the `clipRRect` from a clipRRect mutator contains the
51+
// `platformview_boundingrect`.
52+
//
53+
// `clip_rrect` is in its own coordinate space. The rrect needs to be transformed by
54+
// `transform_matrix` to be in the coordinate space where the PlatformView is displayed.
55+
//
56+
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate
57+
// space where the PlatformView is displayed.
58+
static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
59+
const SkRect& platformview_boundingrect,
60+
const SkMatrix& transform_matrix) {
61+
SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner);
62+
SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner);
63+
SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner);
64+
SkVector lower_left = clip_rrect.radii(SkRRect::Corner::kLowerLeft_Corner);
65+
SkScalar transformed_upper_left_x = transform_matrix.mapRadius(upper_left.x());
66+
SkScalar transformed_upper_left_y = transform_matrix.mapRadius(upper_left.y());
67+
SkScalar transformed_upper_right_x = transform_matrix.mapRadius(upper_right.x());
68+
SkScalar transformed_upper_right_y = transform_matrix.mapRadius(upper_right.y());
69+
SkScalar transformed_lower_right_x = transform_matrix.mapRadius(lower_right.x());
70+
SkScalar transformed_lower_right_y = transform_matrix.mapRadius(lower_right.y());
71+
SkScalar transformed_lower_left_x = transform_matrix.mapRadius(lower_left.x());
72+
SkScalar transformed_lower_left_y = transform_matrix.mapRadius(lower_left.y());
73+
SkRect transformed_clip_rect = transform_matrix.mapRect(clip_rrect.rect());
74+
SkRRect transformed_rrect;
75+
SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y},
76+
{transformed_upper_right_x, transformed_upper_right_y},
77+
{transformed_lower_right_x, transformed_lower_right_y},
78+
{transformed_lower_left_x, transformed_lower_left_y}};
79+
transformed_rrect.setRectRadii(transformed_clip_rect, corners);
80+
return transformed_rrect.contains(platformview_boundingrect);
4981
}
5082

5183
namespace flutter {
@@ -450,28 +482,27 @@ static bool ClipBoundsContainsPlatformViewBoundingRect(const SkRect& clip_bounds
450482
break;
451483
}
452484
case kClipRect: {
453-
if (ClipBoundsContainsPlatformViewBoundingRect((*iter)->GetRect(), bounding_rect,
454-
transformMatrix)) {
485+
if (ClipRectContainsPlatformViewBoundingRect((*iter)->GetRect(), bounding_rect,
486+
transformMatrix)) {
455487
break;
456488
}
457489
[maskView clipRect:(*iter)->GetRect() matrix:transformMatrix];
458490
clipView.maskView = maskView;
459491
break;
460492
}
461493
case kClipRRect: {
462-
if (ClipBoundsContainsPlatformViewBoundingRect((*iter)->GetRRect().getBounds(),
463-
bounding_rect, transformMatrix)) {
494+
if (ClipRRectContainsPlatformViewBoundingRect((*iter)->GetRRect(), bounding_rect,
495+
transformMatrix)) {
464496
break;
465497
}
466498
[maskView clipRRect:(*iter)->GetRRect() matrix:transformMatrix];
467499
clipView.maskView = maskView;
468500
break;
469501
}
470502
case kClipPath: {
471-
if (ClipBoundsContainsPlatformViewBoundingRect((*iter)->GetPath().getBounds(),
472-
bounding_rect, transformMatrix)) {
473-
break;
474-
}
503+
// TODO(cyanglaz): Find a way to pre-determine if path contains the PlatformView boudning
504+
// rect. See `ClipRRectContainsPlatformViewBoundingRect`.
505+
// https://github.com/flutter/flutter/issues/118650
475506
[maskView clipPath:(*iter)->GetPath() matrix:transformMatrix];
476507
clipView.maskView = maskView;
477508
break;

shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,7 @@ - (void)testChildClippingViewShouldBeTheBoundingRectOfPlatformView {
14781478
kFloatCompareEpsilon);
14791479
}
14801480

1481-
- (void)testClipsDoNotInterceptWithPlatformViewShouldNotAddMaskView {
1481+
- (void)testClipRectDoNotInterceptWithPlatformViewShouldNotAddMaskView {
14821482
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
14831483
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
14841484
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
@@ -1526,9 +1526,6 @@ - (void)testClipsDoNotInterceptWithPlatformViewShouldNotAddMaskView {
15261526
SkRect rect_for_rrect = SkRect::MakeXYWH(0, 0, 24, 24);
15271527
SkRRect rrect = SkRRect::MakeRectXY(rect_for_rrect, 1, 1);
15281528
stack.PushClipRRect(rrect);
1529-
// Push a clip path, big enough to contain the entire platform view bound
1530-
SkPath path = SkPath::RRect(SkRect::MakeXYWH(0, 0, 23, 23), 1, 1);
1531-
stack.PushClipPath(path);
15321529

15331530
auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
15341531
SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack);
@@ -1546,6 +1543,70 @@ - (void)testClipsDoNotInterceptWithPlatformViewShouldNotAddMaskView {
15461543
XCTAssertNil(childClippingView.maskView);
15471544
}
15481545

1546+
- (void)testClipRRectOnlyHasCornersInterceptWithPlatformViewShouldAddMaskView {
1547+
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1548+
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
1549+
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
1550+
/*platform=*/thread_task_runner,
1551+
/*raster=*/thread_task_runner,
1552+
/*ui=*/thread_task_runner,
1553+
/*io=*/thread_task_runner);
1554+
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
1555+
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1556+
/*delegate=*/mock_delegate,
1557+
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
1558+
/*platform_views_controller=*/flutterPlatformViewsController,
1559+
/*task_runners=*/runners);
1560+
1561+
FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
1562+
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
1563+
flutterPlatformViewsController->RegisterViewFactory(
1564+
factory, @"MockFlutterPlatformView",
1565+
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
1566+
FlutterResult result = ^(id result) {
1567+
};
1568+
flutterPlatformViewsController->OnMethodCall(
1569+
[FlutterMethodCall
1570+
methodCallWithMethodName:@"create"
1571+
arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
1572+
result);
1573+
1574+
XCTAssertNotNil(gMockPlatformView);
1575+
1576+
UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)] autorelease];
1577+
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
1578+
// Create embedded view params
1579+
flutter::MutatorsStack stack;
1580+
// Layer tree always pushes a screen scale factor to the stack
1581+
SkMatrix screenScaleMatrix =
1582+
SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
1583+
stack.PushTransform(screenScaleMatrix);
1584+
SkMatrix translateMatrix = SkMatrix::Translate(5, 5);
1585+
// The platform view's rect for this test will be (5, 5, 10, 10)
1586+
stack.PushTransform(translateMatrix);
1587+
1588+
// Push a clip rrect, the rect of the rrect is the same as the PlatformView of the corner should
1589+
// clip the PlatformView.
1590+
SkRect rect_for_rrect = SkRect::MakeXYWH(0, 0, 10, 10);
1591+
SkRRect rrect = SkRRect::MakeRectXY(rect_for_rrect, 1, 1);
1592+
stack.PushClipRRect(rrect);
1593+
1594+
auto embeddedViewParams = std::make_unique<flutter::EmbeddedViewParams>(
1595+
SkMatrix::Concat(screenScaleMatrix, translateMatrix), SkSize::Make(5, 5), stack);
1596+
1597+
flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
1598+
flutterPlatformViewsController->CompositeEmbeddedView(2);
1599+
gMockPlatformView.backgroundColor = UIColor.redColor;
1600+
XCTAssertTrue([gMockPlatformView.superview.superview isKindOfClass:ChildClippingView.class]);
1601+
ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView.superview.superview;
1602+
[mockFlutterView addSubview:childClippingView];
1603+
1604+
[mockFlutterView setNeedsLayout];
1605+
[mockFlutterView layoutIfNeeded];
1606+
1607+
XCTAssertNotNil(childClippingView.maskView);
1608+
}
1609+
15491610
- (void)testClipRect {
15501611
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
15511612
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");

testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ - (BOOL)application:(UIApplication*)application
4343
@"platform_view_multiple_background_foreground",
4444
@"--platform-view-cliprect" : @"platform_view_cliprect",
4545
@"--platform-view-cliprrect" : @"platform_view_cliprrect",
46+
@"--platform-view-large-cliprrect" : @"platform_view_large_cliprrect",
4647
@"--platform-view-clippath" : @"platform_view_clippath",
4748
@"--platform-view-cliprrect-with-transform" : @"platform_view_cliprrect_with_transform",
49+
@"--platform-view-large-cliprrect-with-transform" :
50+
@"platform_view_large_cliprrect_with_transform",
4851
@"--platform-view-cliprect-with-transform" : @"platform_view_cliprect_with_transform",
4952
@"--platform-view-clippath-with-transform" : @"platform_view_clippath_with_transform",
5053
@"--platform-view-transform" : @"platform_view_transform",

testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenTestManager.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ - (instancetype)initWithLaunchArg:(NSString*)launchArg {
2929
@"platform_view_multiple_background_foreground",
3030
@"--platform-view-cliprect" : @"platform_view_cliprect",
3131
@"--platform-view-cliprrect" : @"platform_view_cliprrect",
32+
@"--platform-view-large-cliprrect" : @"platform_view_large_cliprrect",
3233
@"--platform-view-clippath" : @"platform_view_clippath",
3334
@"--platform-view-cliprrect-with-transform" : @"platform_view_cliprrect_with_transform",
35+
@"--platform-view-large-cliprrect-with-transform" :
36+
@"platform_view_large_cliprrect_with_transform",
3437
@"--platform-view-cliprect-with-transform" : @"platform_view_cliprect_with_transform",
3538
@"--platform-view-clippath-with-transform" : @"platform_view_clippath_with_transform",
3639
@"--platform-view-transform" : @"platform_view_transform",

testing/scenario_app/ios/Scenarios/ScenariosUITests/PlatformViewUITests.m

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,24 @@ - (void)testPlatformView {
116116

117117
@end
118118

119+
@interface PlatformViewMutationLargeClipRRectTests : GoldenPlatformViewTests
120+
121+
@end
122+
123+
@implementation PlatformViewMutationLargeClipRRectTests
124+
125+
- (instancetype)initWithInvocation:(NSInvocation*)invocation {
126+
GoldenTestManager* manager =
127+
[[GoldenTestManager alloc] initWithLaunchArg:@"--platform-view-large-cliprrect"];
128+
return [super initWithManager:manager invocation:invocation];
129+
}
130+
131+
- (void)testPlatformView {
132+
[self checkPlatformViewGolden];
133+
}
134+
135+
@end
136+
119137
@interface PlatformViewMutationClipPathTests : GoldenPlatformViewTests
120138

121139
@end
@@ -170,6 +188,24 @@ - (void)testPlatformView {
170188

171189
@end
172190

191+
@interface PlatformViewMutationLargeClipRRectWithTransformTests : GoldenPlatformViewTests
192+
193+
@end
194+
195+
@implementation PlatformViewMutationLargeClipRRectWithTransformTests
196+
197+
- (instancetype)initWithInvocation:(NSInvocation*)invocation {
198+
GoldenTestManager* manager = [[GoldenTestManager alloc]
199+
initWithLaunchArg:@"--platform-view-large-cliprrect-with-transform"];
200+
return [super initWithManager:manager invocation:invocation];
201+
}
202+
203+
- (void)testPlatformView {
204+
[self checkPlatformViewGolden];
205+
}
206+
207+
@end
208+
173209
@interface PlatformViewMutationClipPathWithTransformTests : GoldenPlatformViewTests
174210

175211
@end

testing/scenario_app/lib/src/platform_view.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,41 @@ class PlatformViewClipRRectScenario extends PlatformViewScenario {
618618
}
619619
}
620620

621+
622+
/// Platform view with clip rrect.
623+
/// The bounding rect of the rrect is the same as PlatformView and only the corner radii clips the PlatformView.
624+
class PlatformViewLargeClipRRectScenario extends PlatformViewScenario {
625+
/// Constructs a platform view with large clip rrect scenario.
626+
PlatformViewLargeClipRRectScenario(
627+
PlatformDispatcher dispatcher, {
628+
int id = 0,
629+
}) : super(dispatcher, id: id);
630+
631+
@override
632+
void onBeginFrame(Duration duration) {
633+
final SceneBuilder builder = SceneBuilder();
634+
builder.pushClipRRect(
635+
RRect.fromLTRBAndCorners(
636+
0,
637+
0,
638+
500,
639+
500,
640+
topLeft: const Radius.circular(15),
641+
topRight: const Radius.circular(50),
642+
bottomLeft: const Radius.circular(50),
643+
),
644+
);
645+
646+
addPlatformView(
647+
id,
648+
dispatcher: dispatcher,
649+
sceneBuilder: builder,
650+
);
651+
652+
finishBuilder(builder);
653+
}
654+
}
655+
621656
/// Platform view with clip path.
622657
class PlatformViewClipPathScenario extends PlatformViewScenario {
623658
/// Constructs a platform view with clip path scenario.
@@ -730,6 +765,54 @@ class PlatformViewClipRRectWithTransformScenario extends PlatformViewScenario {
730765
}
731766
}
732767

768+
/// Platform view with clip rrect after transformed.
769+
/// The bounding rect of the rrect is the same as PlatformView and only the corner radii clips the PlatformView.
770+
class PlatformViewLargeClipRRectWithTransformScenario extends PlatformViewScenario {
771+
/// Constructs a platform view with large clip rrect with transform scenario.
772+
PlatformViewLargeClipRRectWithTransformScenario(
773+
PlatformDispatcher dispatcher, {
774+
int id = 0,
775+
}) : super(dispatcher, id: id);
776+
777+
@override
778+
void onBeginFrame(Duration duration) {
779+
final Matrix4 matrix4 = Matrix4.identity()
780+
..rotateZ(1)
781+
..scale(0.5, 0.5, 1.0)
782+
..translate(1000.0, 100.0);
783+
784+
final SceneBuilder builder = SceneBuilder()..pushTransform(matrix4.storage);
785+
builder.pushClipRRect(
786+
RRect.fromLTRBAndCorners(
787+
0,
788+
0,
789+
500,
790+
500,
791+
topLeft: const Radius.circular(15),
792+
topRight: const Radius.circular(50),
793+
bottomLeft: const Radius.circular(50),
794+
),
795+
);
796+
addPlatformView(
797+
id,
798+
dispatcher: dispatcher,
799+
sceneBuilder: builder,
800+
);
801+
802+
// Add a translucent rect that has the same size of PlatformView.
803+
final PictureRecorder recorder = PictureRecorder();
804+
final Canvas canvas = Canvas(recorder);
805+
canvas.drawRect(
806+
const Rect.fromLTWH(0, 0, 500, 500),
807+
Paint()..color = const Color(0x22FF0000),
808+
);
809+
final Picture picture = recorder.endRecording();
810+
builder.addPicture(Offset.zero, picture);
811+
812+
finishBuilder(builder);
813+
}
814+
}
815+
733816
/// Platform view with clip path after transformed.
734817
class PlatformViewClipPathWithTransformScenario extends PlatformViewScenario {
735818
/// Constructs a platform view with clip path with transform scenario.

testing/scenario_app/lib/src/scenarios.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ Map<String, ScenarioFactory> _scenarios = <String, ScenarioFactory>{
3333
'platform_view_cliprect': () => PlatformViewClipRectScenario(PlatformDispatcher.instance, id: _viewId++),
3434
'platform_view_cliprect_with_transform': () => PlatformViewClipRectWithTransformScenario(PlatformDispatcher.instance, id: _viewId++),
3535
'platform_view_cliprrect': () => PlatformViewClipRRectScenario(PlatformDispatcher.instance, id: _viewId++),
36+
'platform_view_large_cliprrect': () => PlatformViewLargeClipRRectScenario(PlatformDispatcher.instance, id: _viewId++),
3637
'platform_view_cliprrect_with_transform': () => PlatformViewClipRRectWithTransformScenario(PlatformDispatcher.instance, id: _viewId++),
38+
'platform_view_large_cliprrect_with_transform': () => PlatformViewLargeClipRRectWithTransformScenario(PlatformDispatcher.instance, id: _viewId++),
3739
'platform_view_clippath': () => PlatformViewClipPathScenario(PlatformDispatcher.instance, id: _viewId++),
3840
'platform_view_clippath_with_transform': () => PlatformViewClipPathWithTransformScenario(PlatformDispatcher.instance, id: _viewId++),
3941
'platform_view_transform': () => PlatformViewTransformScenario(PlatformDispatcher.instance, id: _viewId++),

0 commit comments

Comments
 (0)