7 #include "third_party/googletest/googletest/include/gtest/gtest.h"
13 @property(readonly, nonatomic, nonnull) NSMutableArray<NSView*>*
pathClipViews;
23 const std::vector<FlutterPlatformViewMutation>& mutations) {
38 void ExpectTransform3DEqual(
const CATransform3D& t,
const CATransform3D& u) {
39 EXPECT_NEAR(t.m11, u.m11,
kMaxErr);
40 EXPECT_NEAR(t.m12, u.m12,
kMaxErr);
41 EXPECT_NEAR(t.m13, u.m13,
kMaxErr);
42 EXPECT_NEAR(t.m14, u.m14,
kMaxErr);
44 EXPECT_NEAR(t.m21, u.m21,
kMaxErr);
45 EXPECT_NEAR(t.m22, u.m22,
kMaxErr);
46 EXPECT_NEAR(t.m23, u.m23,
kMaxErr);
47 EXPECT_NEAR(t.m24, u.m24,
kMaxErr);
49 EXPECT_NEAR(t.m31, u.m31,
kMaxErr);
50 EXPECT_NEAR(t.m32, u.m32,
kMaxErr);
51 EXPECT_NEAR(t.m33, u.m33,
kMaxErr);
52 EXPECT_NEAR(t.m34, u.m34,
kMaxErr);
54 EXPECT_NEAR(t.m41, u.m41,
kMaxErr);
55 EXPECT_NEAR(t.m42, u.m42,
kMaxErr);
56 EXPECT_NEAR(t.m43, u.m43,
kMaxErr);
57 EXPECT_NEAR(t.m44, u.m44,
kMaxErr);
61 TEST(FlutterMutatorViewTest, BasicFrameIsCorrect) {
62 NSView* platformView = [[NSView alloc] init];
67 std::vector<FlutterPlatformViewMutation> mutations{
69 .type = kFlutterPlatformViewMutationTypeTransformation,
71 FlutterTransformation{
80 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
82 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
83 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
84 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
85 EXPECT_NE(mutatorView.platformViewContainer, nil);
88 TEST(FlutterMutatorViewTest, ClipsToBounds) {
89 NSView* platformView = [[NSView alloc] init];
91 EXPECT_TRUE(mutatorView.clipsToBounds);
94 TEST(FlutterMutatorViewTest, TransformedFrameIsCorrect) {
95 NSView* platformView = [[NSView alloc] init];
97 NSView* mutatorViewParent = [[NSView alloc] init];
98 mutatorViewParent.wantsLayer = YES;
99 mutatorViewParent.layer.contentsScale = 2.0;
100 [mutatorViewParent addSubview:mutatorView];
102 std::vector<FlutterPlatformViewMutation> mutations{
104 .type = kFlutterPlatformViewMutationTypeTransformation,
106 FlutterTransformation{
112 .type = kFlutterPlatformViewMutationTypeTransformation,
114 FlutterTransformation{
122 .type = kFlutterPlatformViewMutationTypeTransformation,
124 FlutterTransformation{
134 ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
135 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(92.5, 45, 45, 30)));
136 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
138 ExpectTransform3DEqual(mutatorView.platformViewContainer.layer.sublayerTransform,
139 CATransform3DMakeScale(1.5, 1.5, 1));
142 TEST(FlutterMutatorViewTest, FrameWithLooseClipIsCorrect) {
143 NSView* platformView = [[NSView alloc] init];
148 std::vector<FlutterPlatformViewMutation> mutations{
150 .type = kFlutterPlatformViewMutationTypeClipRect,
151 .clip_rect = FlutterRect{80, 40, 200, 100},
154 .type = kFlutterPlatformViewMutationTypeTransformation,
156 FlutterTransformation{
165 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
167 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
168 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
171 TEST(FlutterMutatorViewTest, FrameWithTightClipIsCorrect) {
172 NSView* platformView = [[NSView alloc] init];
177 std::vector<FlutterPlatformViewMutation> mutations{
179 .type = kFlutterPlatformViewMutationTypeClipRect,
180 .clip_rect = FlutterRect{80, 40, 200, 100},
183 .type = kFlutterPlatformViewMutationTypeClipRect,
184 .clip_rect = FlutterRect{110, 55, 120, 65},
187 .type = kFlutterPlatformViewMutationTypeTransformation,
189 FlutterTransformation{
198 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
200 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
202 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
203 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
206 TEST(FlutterMutatorViewTest, FrameWithTightClipAndTransformIsCorrect) {
207 NSView* platformView = [[NSView alloc] init];
209 NSView* mutatorViewParent = [[NSView alloc] init];
210 mutatorViewParent.wantsLayer = YES;
211 mutatorViewParent.layer.contentsScale = 2.0;
212 [mutatorViewParent addSubview:mutatorView];
214 std::vector<FlutterPlatformViewMutation> mutations{
216 .type = kFlutterPlatformViewMutationTypeTransformation,
218 FlutterTransformation{
224 .type = kFlutterPlatformViewMutationTypeClipRect,
225 .clip_rect = FlutterRect{80, 40, 200, 100},
228 .type = kFlutterPlatformViewMutationTypeClipRect,
229 .clip_rect = FlutterRect{110, 55, 120, 65},
232 .type = kFlutterPlatformViewMutationTypeTransformation,
234 FlutterTransformation{
242 .type = kFlutterPlatformViewMutationTypeTransformation,
244 FlutterTransformation{
253 ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
255 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
257 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-17.5, -10, 45, 30)));
258 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
262 TEST(FlutterMutatorViewTest, RoundRectClipsToSimpleRectangle) {
263 NSView* platformView = [[NSView alloc] init];
266 std::vector<FlutterPlatformViewMutation> mutations{
268 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
271 .rect = FlutterRect{110, 30, 120, 90},
272 .upper_left_corner_radius = FlutterSize{10, 10},
273 .upper_right_corner_radius = FlutterSize{10, 10},
274 .lower_right_corner_radius = FlutterSize{10, 10},
275 .lower_left_corner_radius = FlutterSize{10, 10},
279 .type = kFlutterPlatformViewMutationTypeTransformation,
281 FlutterTransformation{
290 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
292 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 50, 10, 20)));
294 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, 0, 30, 20)));
295 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
296 EXPECT_EQ(mutatorView.pathClipViews.count, 0ul);
302 TEST(FlutterMutatorViewTest, ViewsSetIsFlipped) {
303 NSView* platformView = [[NSView alloc] init];
306 std::vector<FlutterPlatformViewMutation> mutations{
308 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
311 .rect = FlutterRect{110, 60, 150, 150},
312 .upper_left_corner_radius = FlutterSize{10, 10},
313 .upper_right_corner_radius = FlutterSize{10, 10},
314 .lower_right_corner_radius = FlutterSize{10, 10},
315 .lower_left_corner_radius = FlutterSize{10, 10},
319 .type = kFlutterPlatformViewMutationTypeTransformation,
321 FlutterTransformation{
330 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
332 EXPECT_TRUE(mutatorView.isFlipped);
333 ASSERT_EQ(mutatorView.pathClipViews.count, 1ul);
334 EXPECT_TRUE(mutatorView.pathClipViews.firstObject.isFlipped);
335 EXPECT_TRUE(mutatorView.platformViewContainer.isFlipped);
338 TEST(FlutterMutatorViewTest, RectsClipsToPathWhenRotated) {
339 NSView* platformView = [[NSView alloc] init];
341 std::vector<FlutterPlatformViewMutation> mutations{
343 .type = kFlutterPlatformViewMutationTypeTransformation,
346 FlutterTransformation{
347 .scaleX = 0.9238795325112867,
348 .skewX = -0.3826834323650898,
349 .skewY = 0.3826834323650898,
350 .scaleY = 0.9238795325112867,
354 .type = kFlutterPlatformViewMutationTypeClipRect,
355 .clip_rect = FlutterRect{110, 60, 150, 150},
358 .type = kFlutterPlatformViewMutationTypeTransformation,
360 FlutterTransformation{
368 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
369 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
370 EXPECT_NEAR(mutatorView.platformViewContainer.frame.size.width, 35.370054622640396,
kMaxErr);
371 EXPECT_NEAR(mutatorView.platformViewContainer.frame.size.height, 29.958093621178421,
kMaxErr);
374 TEST(FlutterMutatorViewTest, RoundRectClipsToPath) {
375 NSView* platformView = [[NSView alloc] init];
378 std::vector<FlutterPlatformViewMutation> mutations{
380 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
383 .rect = FlutterRect{110, 60, 150, 150},
384 .upper_left_corner_radius = FlutterSize{10, 10},
385 .upper_right_corner_radius = FlutterSize{10, 10},
386 .lower_right_corner_radius = FlutterSize{10, 10},
387 .lower_left_corner_radius = FlutterSize{10, 10},
391 .type = kFlutterPlatformViewMutationTypeTransformation,
393 FlutterTransformation{
402 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
404 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
406 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
407 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
408 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
409 ExpectTransform3DEqual(mutatorView.pathClipViews.firstObject.layer.mask.transform,
410 CATransform3DMakeTranslation(-100, -50, 0));
413 TEST(FlutterMutatorViewTest, PathClipViewsAreAddedAndRemoved) {
414 NSView* platformView = [[NSView alloc] init];
417 std::vector<FlutterPlatformViewMutation> mutations{
419 .type = kFlutterPlatformViewMutationTypeTransformation,
421 FlutterTransformation{
430 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
432 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
433 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
435 std::vector<FlutterPlatformViewMutation> mutations2{
437 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
440 .rect = FlutterRect{110, 60, 150, 150},
441 .upper_left_corner_radius = FlutterSize{10, 10},
442 .upper_right_corner_radius = FlutterSize{10, 10},
443 .lower_right_corner_radius = FlutterSize{10, 10},
444 .lower_left_corner_radius = FlutterSize{10, 10},
448 .type = kFlutterPlatformViewMutationTypeTransformation,
450 FlutterTransformation{
459 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
461 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
463 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
464 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
465 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
467 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
468 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
469 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
471 std::vector<FlutterPlatformViewMutation> mutations3{
473 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
476 .rect = FlutterRect{110, 55, 150, 150},
477 .upper_left_corner_radius = FlutterSize{10, 10},
478 .upper_right_corner_radius = FlutterSize{10, 10},
479 .lower_right_corner_radius = FlutterSize{10, 10},
480 .lower_left_corner_radius = FlutterSize{10, 10},
484 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
487 .rect = FlutterRect{30, 30, 120, 65},
488 .upper_left_corner_radius = FlutterSize{10, 10},
489 .upper_right_corner_radius = FlutterSize{10, 10},
490 .lower_right_corner_radius = FlutterSize{10, 10},
491 .lower_left_corner_radius = FlutterSize{10, 10},
495 .type = kFlutterPlatformViewMutationTypeTransformation,
497 FlutterTransformation{
506 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations3);
508 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
510 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
511 EXPECT_EQ(mutatorView.pathClipViews.count, 2ul);
513 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
514 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[1]);
515 EXPECT_EQ(mutatorView.pathClipViews[1].superview, mutatorView.pathClipViews[0]);
516 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
518 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
520 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
522 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
523 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
524 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
526 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
527 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
528 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
530 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
532 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
533 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);