7 #include "third_party/googletest/googletest/include/gtest/gtest.h"
13 @property(readonly, nonatomic, nonnull) NSMutableArray<NSView*>*
pathClipViews;
23 const std::vector<FlutterPlatformViewMutation>& mutations) {
25 layer.struct_size =
sizeof(FlutterLayer);
26 layer.type = kFlutterLayerContentTypePlatformView;
29 layer.offset = FlutterPoint{0, 0};
32 FlutterPlatformView flutterPlatformView;
33 flutterPlatformView.struct_size =
sizeof(FlutterPlatformView);
34 flutterPlatformView.identifier = 0;
36 std::vector<const FlutterPlatformViewMutation*> mutationPointers;
37 mutationPointers.reserve(mutations.size());
38 for (
auto& mutation : mutations) {
39 mutationPointers.push_back(&mutation);
41 flutterPlatformView.mutations = mutationPointers.data();
42 flutterPlatformView.mutations_count = mutationPointers.size();
43 layer.platform_view = &flutterPlatformView;
52 void ExpectTransform3DEqual(
const CATransform3D& t,
const CATransform3D& u) {
53 EXPECT_NEAR(t.m11, u.m11,
kMaxErr);
54 EXPECT_NEAR(t.m12, u.m12,
kMaxErr);
55 EXPECT_NEAR(t.m13, u.m13,
kMaxErr);
56 EXPECT_NEAR(t.m14, u.m14,
kMaxErr);
58 EXPECT_NEAR(t.m21, u.m21,
kMaxErr);
59 EXPECT_NEAR(t.m22, u.m22,
kMaxErr);
60 EXPECT_NEAR(t.m23, u.m23,
kMaxErr);
61 EXPECT_NEAR(t.m24, u.m24,
kMaxErr);
63 EXPECT_NEAR(t.m31, u.m31,
kMaxErr);
64 EXPECT_NEAR(t.m32, u.m32,
kMaxErr);
65 EXPECT_NEAR(t.m33, u.m33,
kMaxErr);
66 EXPECT_NEAR(t.m34, u.m34,
kMaxErr);
68 EXPECT_NEAR(t.m41, u.m41,
kMaxErr);
69 EXPECT_NEAR(t.m42, u.m42,
kMaxErr);
70 EXPECT_NEAR(t.m43, u.m43,
kMaxErr);
71 EXPECT_NEAR(t.m44, u.m44,
kMaxErr);
75 TEST(FlutterMutatorViewTest, BasicFrameIsCorrect) {
76 NSView* platformView = [[NSView alloc] init];
81 std::vector<FlutterPlatformViewMutation> mutations{
83 .type = kFlutterPlatformViewMutationTypeTransformation,
85 FlutterTransformation{
94 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
96 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
97 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
98 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
99 EXPECT_NE(mutatorView.platformViewContainer, nil);
102 TEST(FlutterMutatorViewTest, ClipsToBounds) {
103 NSView* platformView = [[NSView alloc] init];
105 EXPECT_TRUE(mutatorView.clipsToBounds);
108 TEST(FlutterMutatorViewTest, TransformedFrameIsCorrect) {
109 NSView* platformView = [[NSView alloc] init];
111 NSView* mutatorViewParent = [[NSView alloc] init];
112 mutatorViewParent.wantsLayer = YES;
113 mutatorViewParent.layer.contentsScale = 2.0;
114 [mutatorViewParent addSubview:mutatorView];
116 std::vector<FlutterPlatformViewMutation> mutations{
118 .type = kFlutterPlatformViewMutationTypeTransformation,
120 FlutterTransformation{
126 .type = kFlutterPlatformViewMutationTypeTransformation,
128 FlutterTransformation{
136 .type = kFlutterPlatformViewMutationTypeTransformation,
138 FlutterTransformation{
148 ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
149 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(92.5, 45, 45, 30)));
150 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
152 ExpectTransform3DEqual(mutatorView.platformViewContainer.layer.sublayerTransform,
153 CATransform3DMakeScale(1.5, 1.5, 1));
156 TEST(FlutterMutatorViewTest, FrameWithLooseClipIsCorrect) {
157 NSView* platformView = [[NSView alloc] init];
162 std::vector<FlutterPlatformViewMutation> mutations{
164 .type = kFlutterPlatformViewMutationTypeClipRect,
165 .clip_rect = FlutterRect{80, 40, 200, 100},
168 .type = kFlutterPlatformViewMutationTypeTransformation,
170 FlutterTransformation{
179 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
181 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
182 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
185 TEST(FlutterMutatorViewTest, FrameWithTightClipIsCorrect) {
186 NSView* platformView = [[NSView alloc] init];
191 std::vector<FlutterPlatformViewMutation> mutations{
193 .type = kFlutterPlatformViewMutationTypeClipRect,
194 .clip_rect = FlutterRect{80, 40, 200, 100},
197 .type = kFlutterPlatformViewMutationTypeClipRect,
198 .clip_rect = FlutterRect{110, 55, 120, 65},
201 .type = kFlutterPlatformViewMutationTypeTransformation,
203 FlutterTransformation{
212 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
214 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
216 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
217 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
220 TEST(FlutterMutatorViewTest, FrameWithTightClipAndTransformIsCorrect) {
221 NSView* platformView = [[NSView alloc] init];
223 NSView* mutatorViewParent = [[NSView alloc] init];
224 mutatorViewParent.wantsLayer = YES;
225 mutatorViewParent.layer.contentsScale = 2.0;
226 [mutatorViewParent addSubview:mutatorView];
228 std::vector<FlutterPlatformViewMutation> mutations{
230 .type = kFlutterPlatformViewMutationTypeTransformation,
232 FlutterTransformation{
238 .type = kFlutterPlatformViewMutationTypeClipRect,
239 .clip_rect = FlutterRect{80, 40, 200, 100},
242 .type = kFlutterPlatformViewMutationTypeClipRect,
243 .clip_rect = FlutterRect{110, 55, 120, 65},
246 .type = kFlutterPlatformViewMutationTypeTransformation,
248 FlutterTransformation{
256 .type = kFlutterPlatformViewMutationTypeTransformation,
258 FlutterTransformation{
267 ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
269 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
271 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-17.5, -10, 45, 30)));
272 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
276 TEST(FlutterMutatorViewTest, RoundRectClipsToSimpleRectangle) {
277 NSView* platformView = [[NSView alloc] init];
280 std::vector<FlutterPlatformViewMutation> mutations{
282 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
285 .rect = FlutterRect{110, 30, 120, 90},
286 .upper_left_corner_radius = FlutterSize{10, 10},
287 .upper_right_corner_radius = FlutterSize{10, 10},
288 .lower_right_corner_radius = FlutterSize{10, 10},
289 .lower_left_corner_radius = FlutterSize{10, 10},
293 .type = kFlutterPlatformViewMutationTypeTransformation,
295 FlutterTransformation{
304 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
306 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 50, 10, 20)));
308 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, 0, 30, 20)));
309 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
310 EXPECT_EQ(mutatorView.pathClipViews.count, 0ul);
316 TEST(FlutterMutatorViewTest, ViewsSetIsFlipped) {
317 NSView* platformView = [[NSView alloc] init];
320 std::vector<FlutterPlatformViewMutation> mutations{
322 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
325 .rect = FlutterRect{110, 60, 150, 150},
326 .upper_left_corner_radius = FlutterSize{10, 10},
327 .upper_right_corner_radius = FlutterSize{10, 10},
328 .lower_right_corner_radius = FlutterSize{10, 10},
329 .lower_left_corner_radius = FlutterSize{10, 10},
333 .type = kFlutterPlatformViewMutationTypeTransformation,
335 FlutterTransformation{
344 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
346 EXPECT_TRUE(mutatorView.isFlipped);
347 ASSERT_EQ(mutatorView.pathClipViews.count, 1ul);
348 EXPECT_TRUE(mutatorView.pathClipViews.firstObject.isFlipped);
349 EXPECT_TRUE(mutatorView.platformViewContainer.isFlipped);
352 TEST(FlutterMutatorViewTest, RectsClipsToPathWhenRotated) {
353 NSView* platformView = [[NSView alloc] init];
355 std::vector<FlutterPlatformViewMutation> mutations{
357 .type = kFlutterPlatformViewMutationTypeTransformation,
360 FlutterTransformation{
361 .scaleX = 0.9238795325112867,
362 .skewX = -0.3826834323650898,
363 .skewY = 0.3826834323650898,
364 .scaleY = 0.9238795325112867,
368 .type = kFlutterPlatformViewMutationTypeClipRect,
369 .clip_rect = FlutterRect{110, 60, 150, 150},
372 .type = kFlutterPlatformViewMutationTypeTransformation,
374 FlutterTransformation{
382 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
383 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
384 EXPECT_NEAR(mutatorView.platformViewContainer.frame.size.width, 35.370054622640396,
kMaxErr);
385 EXPECT_NEAR(mutatorView.platformViewContainer.frame.size.height, 29.958093621178421,
kMaxErr);
388 TEST(FlutterMutatorViewTest, RoundRectClipsToPath) {
389 NSView* platformView = [[NSView alloc] init];
392 std::vector<FlutterPlatformViewMutation> mutations{
394 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
397 .rect = FlutterRect{110, 60, 150, 150},
398 .upper_left_corner_radius = FlutterSize{10, 10},
399 .upper_right_corner_radius = FlutterSize{10, 10},
400 .lower_right_corner_radius = FlutterSize{10, 10},
401 .lower_left_corner_radius = FlutterSize{10, 10},
405 .type = kFlutterPlatformViewMutationTypeTransformation,
407 FlutterTransformation{
416 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
418 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
420 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
421 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
422 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
423 ExpectTransform3DEqual(mutatorView.pathClipViews.firstObject.layer.mask.transform,
424 CATransform3DMakeTranslation(-100, -50, 0));
427 TEST(FlutterMutatorViewTest, PathClipViewsAreAddedAndRemoved) {
428 NSView* platformView = [[NSView alloc] init];
431 std::vector<FlutterPlatformViewMutation> mutations{
433 .type = kFlutterPlatformViewMutationTypeTransformation,
435 FlutterTransformation{
444 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
446 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
447 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
449 std::vector<FlutterPlatformViewMutation> mutations2{
451 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
454 .rect = FlutterRect{110, 60, 150, 150},
455 .upper_left_corner_radius = FlutterSize{10, 10},
456 .upper_right_corner_radius = FlutterSize{10, 10},
457 .lower_right_corner_radius = FlutterSize{10, 10},
458 .lower_left_corner_radius = FlutterSize{10, 10},
462 .type = kFlutterPlatformViewMutationTypeTransformation,
464 FlutterTransformation{
473 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
475 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
477 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
478 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
479 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
481 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
482 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
483 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
485 std::vector<FlutterPlatformViewMutation> mutations3{
487 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
490 .rect = FlutterRect{110, 55, 150, 150},
491 .upper_left_corner_radius = FlutterSize{10, 10},
492 .upper_right_corner_radius = FlutterSize{10, 10},
493 .lower_right_corner_radius = FlutterSize{10, 10},
494 .lower_left_corner_radius = FlutterSize{10, 10},
498 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
501 .rect = FlutterRect{30, 30, 120, 65},
502 .upper_left_corner_radius = FlutterSize{10, 10},
503 .upper_right_corner_radius = FlutterSize{10, 10},
504 .lower_right_corner_radius = FlutterSize{10, 10},
505 .lower_left_corner_radius = FlutterSize{10, 10},
509 .type = kFlutterPlatformViewMutationTypeTransformation,
511 FlutterTransformation{
520 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations3);
522 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
524 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
525 EXPECT_EQ(mutatorView.pathClipViews.count, 2ul);
527 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
528 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[1]);
529 EXPECT_EQ(mutatorView.pathClipViews[1].superview, mutatorView.pathClipViews[0]);
530 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
532 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
534 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
536 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
537 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
538 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
540 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
541 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
542 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
544 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
546 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
547 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);