7 #include "third_party/googletest/googletest/include/gtest/gtest.h"
11 @property(readonly, nonatomic, nonnull) NSMutableArray<NSView*>*
pathClipViews;
21 const std::vector<FlutterPlatformViewMutation>& mutations) {
23 layer.struct_size =
sizeof(FlutterLayer);
24 layer.type = kFlutterLayerContentTypePlatformView;
27 layer.offset = FlutterPoint{0, 0};
30 FlutterPlatformView flutterPlatformView;
31 flutterPlatformView.struct_size =
sizeof(FlutterPlatformView);
32 flutterPlatformView.identifier = 0;
34 std::vector<const FlutterPlatformViewMutation*> mutationPointers;
35 for (
auto& mutation : mutations) {
36 mutationPointers.push_back(&mutation);
38 flutterPlatformView.mutations = mutationPointers.data();
39 flutterPlatformView.mutations_count = mutationPointers.size();
40 layer.platform_view = &flutterPlatformView;
49 void ExpectTransform3DEqual(
const CATransform3D& t,
const CATransform3D& u) {
50 EXPECT_NEAR(t.m11, u.m11,
kMaxErr);
51 EXPECT_NEAR(t.m12, u.m12,
kMaxErr);
52 EXPECT_NEAR(t.m13, u.m13,
kMaxErr);
53 EXPECT_NEAR(t.m14, u.m14,
kMaxErr);
55 EXPECT_NEAR(t.m21, u.m21,
kMaxErr);
56 EXPECT_NEAR(t.m22, u.m22,
kMaxErr);
57 EXPECT_NEAR(t.m23, u.m23,
kMaxErr);
58 EXPECT_NEAR(t.m24, u.m24,
kMaxErr);
60 EXPECT_NEAR(t.m31, u.m31,
kMaxErr);
61 EXPECT_NEAR(t.m32, u.m32,
kMaxErr);
62 EXPECT_NEAR(t.m33, u.m33,
kMaxErr);
63 EXPECT_NEAR(t.m34, u.m34,
kMaxErr);
65 EXPECT_NEAR(t.m41, u.m41,
kMaxErr);
66 EXPECT_NEAR(t.m42, u.m42,
kMaxErr);
67 EXPECT_NEAR(t.m43, u.m43,
kMaxErr);
68 EXPECT_NEAR(t.m44, u.m44,
kMaxErr);
72 TEST(FlutterMutatorViewTest, BasicFrameIsCorrect) {
73 NSView* platformView = [[NSView alloc] init];
78 std::vector<FlutterPlatformViewMutation> mutations{
80 .type = kFlutterPlatformViewMutationTypeTransformation,
82 FlutterTransformation{
91 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
93 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
94 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
95 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
96 EXPECT_NE(mutatorView.platformViewContainer, nil);
99 TEST(FlutterMutatorViewTest, TransformedFrameIsCorrect) {
100 NSView* platformView = [[NSView alloc] init];
102 NSView* mutatorViewParent = [[NSView alloc] init];
103 mutatorViewParent.wantsLayer = YES;
104 mutatorViewParent.layer.contentsScale = 2.0;
105 [mutatorViewParent addSubview:mutatorView];
107 std::vector<FlutterPlatformViewMutation> mutations{
109 .type = kFlutterPlatformViewMutationTypeTransformation,
111 FlutterTransformation{
117 .type = kFlutterPlatformViewMutationTypeTransformation,
119 FlutterTransformation{
127 .type = kFlutterPlatformViewMutationTypeTransformation,
129 FlutterTransformation{
139 ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
140 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(92.5, 45, 45, 30)));
141 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
143 ExpectTransform3DEqual(mutatorView.platformViewContainer.layer.sublayerTransform,
144 CATransform3DMakeScale(1.5, 1.5, 1));
147 TEST(FlutterMutatorViewTest, FrameWithLooseClipIsCorrect) {
148 NSView* platformView = [[NSView alloc] init];
153 std::vector<FlutterPlatformViewMutation> mutations{
155 .type = kFlutterPlatformViewMutationTypeClipRect,
156 .clip_rect = FlutterRect{80, 40, 200, 100},
159 .type = kFlutterPlatformViewMutationTypeTransformation,
161 FlutterTransformation{
170 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
172 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
173 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
176 TEST(FlutterMutatorViewTest, FrameWithTightClipIsCorrect) {
177 NSView* platformView = [[NSView alloc] init];
182 std::vector<FlutterPlatformViewMutation> mutations{
184 .type = kFlutterPlatformViewMutationTypeClipRect,
185 .clip_rect = FlutterRect{80, 40, 200, 100},
188 .type = kFlutterPlatformViewMutationTypeClipRect,
189 .clip_rect = FlutterRect{110, 55, 120, 65},
192 .type = kFlutterPlatformViewMutationTypeTransformation,
194 FlutterTransformation{
203 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
205 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
207 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
208 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
211 TEST(FlutterMutatorViewTest, FrameWithTightClipAndTransformIsCorrect) {
212 NSView* platformView = [[NSView alloc] init];
214 NSView* mutatorViewParent = [[NSView alloc] init];
215 mutatorViewParent.wantsLayer = YES;
216 mutatorViewParent.layer.contentsScale = 2.0;
217 [mutatorViewParent addSubview:mutatorView];
219 std::vector<FlutterPlatformViewMutation> mutations{
221 .type = kFlutterPlatformViewMutationTypeTransformation,
223 FlutterTransformation{
229 .type = kFlutterPlatformViewMutationTypeClipRect,
230 .clip_rect = FlutterRect{80, 40, 200, 100},
233 .type = kFlutterPlatformViewMutationTypeClipRect,
234 .clip_rect = FlutterRect{110, 55, 120, 65},
237 .type = kFlutterPlatformViewMutationTypeTransformation,
239 FlutterTransformation{
247 .type = kFlutterPlatformViewMutationTypeTransformation,
249 FlutterTransformation{
258 ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
260 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
262 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-17.5, -10, 45, 30)));
263 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
267 TEST(FlutterMutatorViewTest, RoundRectClipsToSimpleRectangle) {
268 NSView* platformView = [[NSView alloc] init];
271 std::vector<FlutterPlatformViewMutation> mutations{
273 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
276 .rect = FlutterRect{110, 30, 120, 90},
277 .upper_left_corner_radius = FlutterSize{10, 10},
278 .upper_right_corner_radius = FlutterSize{10, 10},
279 .lower_right_corner_radius = FlutterSize{10, 10},
280 .lower_left_corner_radius = FlutterSize{10, 10},
284 .type = kFlutterPlatformViewMutationTypeTransformation,
286 FlutterTransformation{
295 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
297 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 50, 10, 20)));
299 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, 0, 30, 20)));
300 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
301 EXPECT_EQ(mutatorView.pathClipViews.count, 0ul);
307 TEST(FlutterMutatorViewTest, ViewsSetIsFlipped) {
308 NSView* platformView = [[NSView alloc] init];
311 std::vector<FlutterPlatformViewMutation> mutations{
313 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
316 .rect = FlutterRect{110, 60, 150, 150},
317 .upper_left_corner_radius = FlutterSize{10, 10},
318 .upper_right_corner_radius = FlutterSize{10, 10},
319 .lower_right_corner_radius = FlutterSize{10, 10},
320 .lower_left_corner_radius = FlutterSize{10, 10},
324 .type = kFlutterPlatformViewMutationTypeTransformation,
326 FlutterTransformation{
335 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
337 EXPECT_TRUE(mutatorView.isFlipped);
338 ASSERT_EQ(mutatorView.pathClipViews.count, 1ul);
339 EXPECT_TRUE(mutatorView.pathClipViews.firstObject.isFlipped);
340 EXPECT_TRUE(mutatorView.platformViewContainer.isFlipped);
343 TEST(FlutterMutatorViewTest, RectsClipsToPathWhenRotated) {
344 NSView* platformView = [[NSView alloc] init];
346 std::vector<FlutterPlatformViewMutation> mutations{
348 .type = kFlutterPlatformViewMutationTypeTransformation,
351 FlutterTransformation{
352 .scaleX = 0.9238795325112867,
353 .skewX = -0.3826834323650898,
354 .skewY = 0.3826834323650898,
355 .scaleY = 0.9238795325112867,
359 .type = kFlutterPlatformViewMutationTypeClipRect,
360 .clip_rect = FlutterRect{110, 60, 150, 150},
363 .type = kFlutterPlatformViewMutationTypeTransformation,
365 FlutterTransformation{
373 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
374 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
375 EXPECT_NEAR(mutatorView.platformViewContainer.frame.size.width, 35.370054622640396,
kMaxErr);
376 EXPECT_NEAR(mutatorView.platformViewContainer.frame.size.height, 29.958093621178421,
kMaxErr);
379 TEST(FlutterMutatorViewTest, RoundRectClipsToPath) {
380 NSView* platformView = [[NSView alloc] init];
383 std::vector<FlutterPlatformViewMutation> mutations{
385 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
388 .rect = FlutterRect{110, 60, 150, 150},
389 .upper_left_corner_radius = FlutterSize{10, 10},
390 .upper_right_corner_radius = FlutterSize{10, 10},
391 .lower_right_corner_radius = FlutterSize{10, 10},
392 .lower_left_corner_radius = FlutterSize{10, 10},
396 .type = kFlutterPlatformViewMutationTypeTransformation,
398 FlutterTransformation{
407 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
409 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
411 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
412 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
413 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
414 ExpectTransform3DEqual(mutatorView.pathClipViews.firstObject.layer.mask.transform,
415 CATransform3DMakeTranslation(-100, -50, 0));
418 TEST(FlutterMutatorViewTest, PathClipViewsAreAddedAndRemoved) {
419 NSView* platformView = [[NSView alloc] init];
422 std::vector<FlutterPlatformViewMutation> mutations{
424 .type = kFlutterPlatformViewMutationTypeTransformation,
426 FlutterTransformation{
435 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
437 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
438 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
440 std::vector<FlutterPlatformViewMutation> mutations2{
442 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
445 .rect = FlutterRect{110, 60, 150, 150},
446 .upper_left_corner_radius = FlutterSize{10, 10},
447 .upper_right_corner_radius = FlutterSize{10, 10},
448 .lower_right_corner_radius = FlutterSize{10, 10},
449 .lower_left_corner_radius = FlutterSize{10, 10},
453 .type = kFlutterPlatformViewMutationTypeTransformation,
455 FlutterTransformation{
464 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
466 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
468 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
469 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
470 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
472 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
473 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
474 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
476 std::vector<FlutterPlatformViewMutation> mutations3{
478 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
481 .rect = FlutterRect{110, 55, 150, 150},
482 .upper_left_corner_radius = FlutterSize{10, 10},
483 .upper_right_corner_radius = FlutterSize{10, 10},
484 .lower_right_corner_radius = FlutterSize{10, 10},
485 .lower_left_corner_radius = FlutterSize{10, 10},
489 .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
492 .rect = FlutterRect{30, 30, 120, 65},
493 .upper_left_corner_radius = FlutterSize{10, 10},
494 .upper_right_corner_radius = FlutterSize{10, 10},
495 .lower_right_corner_radius = FlutterSize{10, 10},
496 .lower_left_corner_radius = FlutterSize{10, 10},
500 .type = kFlutterPlatformViewMutationTypeTransformation,
502 FlutterTransformation{
511 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations3);
513 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
515 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
516 EXPECT_EQ(mutatorView.pathClipViews.count, 2ul);
518 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
519 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[1]);
520 EXPECT_EQ(mutatorView.pathClipViews[1].superview, mutatorView.pathClipViews[0]);
521 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
523 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
525 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
527 CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -10, 30, 20)));
528 EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
529 EXPECT_EQ(mutatorView.pathClipViews.count, 1ul);
531 EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
532 EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
533 EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
535 ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
537 EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
538 EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);