Flutter macOS Embedder
FlutterMutatorViewTest.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "third_party/googletest/googletest/include/gtest/gtest.h"
8 
10 
12 
13 @property(readonly, nonatomic, nonnull) NSMutableArray<NSView*>* pathClipViews;
14 @property(readonly, nonatomic, nullable) NSView* platformViewContainer;
15 
16 @end
17 
18 static constexpr float kMaxErr = 1e-10;
19 
20 namespace {
21 void ApplyFlutterLayer(FlutterMutatorView* view,
22  FlutterSize size,
23  const std::vector<FlutterPlatformViewMutation>& mutations) {
24  FlutterLayer layer;
25  layer.struct_size = sizeof(FlutterLayer);
26  layer.type = kFlutterLayerContentTypePlatformView;
27  // Offset is ignored by mutator view, the bounding rect is determined by
28  // width and transform.
29  layer.offset = FlutterPoint{0, 0};
30  layer.size = size;
31 
32  FlutterPlatformView flutterPlatformView;
33  flutterPlatformView.struct_size = sizeof(FlutterPlatformView);
34  flutterPlatformView.identifier = 0;
35 
36  std::vector<const FlutterPlatformViewMutation*> mutationPointers;
37  mutationPointers.reserve(mutations.size());
38  for (auto& mutation : mutations) {
39  mutationPointers.push_back(&mutation);
40  }
41  flutterPlatformView.mutations = mutationPointers.data();
42  flutterPlatformView.mutations_count = mutationPointers.size();
43  layer.platform_view = &flutterPlatformView;
44 
45  [view applyFlutterLayer:&layer];
46 }
47 
48 // Expect that each element within two CATransform3Ds is within an error bound.
49 //
50 // In order to avoid architecture-specific floating point differences we don't check for exact
51 // equality using, for example, CATransform3DEqualToTransform.
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);
57 
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);
62 
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);
67 
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);
72 }
73 } // namespace
74 
75 TEST(FlutterMutatorViewTest, BasicFrameIsCorrect) {
76  NSView* platformView = [[NSView alloc] init];
77  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
78 
79  EXPECT_EQ(mutatorView.platformView, platformView);
80 
81  std::vector<FlutterPlatformViewMutation> mutations{
82  {
83  .type = kFlutterPlatformViewMutationTypeTransformation,
84  .transformation =
85  FlutterTransformation{
86  .scaleX = 1,
87  .transX = 100,
88  .scaleY = 1,
89  .transY = 50,
90  },
91  },
92  };
93 
94  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
95 
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);
100 }
101 
102 TEST(FlutterMutatorViewTest, ClipsToBounds) {
103  NSView* platformView = [[NSView alloc] init];
104  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
105  EXPECT_TRUE(mutatorView.clipsToBounds);
106 }
107 
108 TEST(FlutterMutatorViewTest, TransformedFrameIsCorrect) {
109  NSView* platformView = [[NSView alloc] init];
110  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
111  NSView* mutatorViewParent = [[NSView alloc] init];
112  mutatorViewParent.wantsLayer = YES;
113  mutatorViewParent.layer.contentsScale = 2.0;
114  [mutatorViewParent addSubview:mutatorView];
115 
116  std::vector<FlutterPlatformViewMutation> mutations{
117  {
118  .type = kFlutterPlatformViewMutationTypeTransformation,
119  .transformation =
120  FlutterTransformation{
121  .scaleX = 2,
122  .scaleY = 2,
123  },
124  },
125  {
126  .type = kFlutterPlatformViewMutationTypeTransformation,
127  .transformation =
128  FlutterTransformation{
129  .scaleX = 1,
130  .transX = 100,
131  .scaleY = 1,
132  .transY = 50,
133  },
134  },
135  {
136  .type = kFlutterPlatformViewMutationTypeTransformation,
137  .transformation =
138  FlutterTransformation{
139  .scaleX = 1.5,
140  .transX = -7.5,
141  .scaleY = 1.5,
142  .transY = -5,
143  },
144  },
145  };
146 
147  // PlatformView size form engine comes in physical pixels
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)));
151 
152  ExpectTransform3DEqual(mutatorView.platformViewContainer.layer.sublayerTransform,
153  CATransform3DMakeScale(1.5, 1.5, 1));
154 }
155 
156 TEST(FlutterMutatorViewTest, FrameWithLooseClipIsCorrect) {
157  NSView* platformView = [[NSView alloc] init];
158  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
159 
160  EXPECT_EQ(mutatorView.platformView, platformView);
161 
162  std::vector<FlutterPlatformViewMutation> mutations{
163  {
164  .type = kFlutterPlatformViewMutationTypeClipRect,
165  .clip_rect = FlutterRect{80, 40, 200, 100},
166  },
167  {
168  .type = kFlutterPlatformViewMutationTypeTransformation,
169  .transformation =
170  FlutterTransformation{
171  .scaleX = 1,
172  .transX = 100,
173  .scaleY = 1,
174  .transY = 50,
175  },
176  },
177  };
178 
179  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
180 
181  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
182  EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
183 }
184 
185 TEST(FlutterMutatorViewTest, FrameWithTightClipIsCorrect) {
186  NSView* platformView = [[NSView alloc] init];
187  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
188 
189  EXPECT_EQ(mutatorView.platformView, platformView);
190 
191  std::vector<FlutterPlatformViewMutation> mutations{
192  {
193  .type = kFlutterPlatformViewMutationTypeClipRect,
194  .clip_rect = FlutterRect{80, 40, 200, 100},
195  },
196  {
197  .type = kFlutterPlatformViewMutationTypeClipRect,
198  .clip_rect = FlutterRect{110, 55, 120, 65},
199  },
200  {
201  .type = kFlutterPlatformViewMutationTypeTransformation,
202  .transformation =
203  FlutterTransformation{
204  .scaleX = 1,
205  .transX = 100,
206  .scaleY = 1,
207  .transY = 50,
208  },
209  },
210  };
211 
212  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
213 
214  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
215  EXPECT_TRUE(
216  CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
217  EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
218 }
219 
220 TEST(FlutterMutatorViewTest, FrameWithTightClipAndTransformIsCorrect) {
221  NSView* platformView = [[NSView alloc] init];
222  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
223  NSView* mutatorViewParent = [[NSView alloc] init];
224  mutatorViewParent.wantsLayer = YES;
225  mutatorViewParent.layer.contentsScale = 2.0;
226  [mutatorViewParent addSubview:mutatorView];
227 
228  std::vector<FlutterPlatformViewMutation> mutations{
229  {
230  .type = kFlutterPlatformViewMutationTypeTransformation,
231  .transformation =
232  FlutterTransformation{
233  .scaleX = 2,
234  .scaleY = 2,
235  },
236  },
237  {
238  .type = kFlutterPlatformViewMutationTypeClipRect,
239  .clip_rect = FlutterRect{80, 40, 200, 100},
240  },
241  {
242  .type = kFlutterPlatformViewMutationTypeClipRect,
243  .clip_rect = FlutterRect{110, 55, 120, 65},
244  },
245  {
246  .type = kFlutterPlatformViewMutationTypeTransformation,
247  .transformation =
248  FlutterTransformation{
249  .scaleX = 1,
250  .transX = 100,
251  .scaleY = 1,
252  .transY = 50,
253  },
254  },
255  {
256  .type = kFlutterPlatformViewMutationTypeTransformation,
257  .transformation =
258  FlutterTransformation{
259  .scaleX = 1.5,
260  .transX = -7.5,
261  .scaleY = 1.5,
262  .transY = -5,
263  },
264  },
265  };
266 
267  ApplyFlutterLayer(mutatorView, FlutterSize{30 * 2, 20 * 2}, mutations);
268 
269  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
270  EXPECT_TRUE(
271  CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-17.5, -10, 45, 30)));
272  EXPECT_TRUE(CGRectEqualToRect(platformView.frame, CGRectMake(0, 0, 30, 20)));
273 }
274 
275 // Rounded rectangle without hitting the corner
276 TEST(FlutterMutatorViewTest, RoundRectClipsToSimpleRectangle) {
277  NSView* platformView = [[NSView alloc] init];
278  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
279 
280  std::vector<FlutterPlatformViewMutation> mutations{
281  {
282  .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
283  .clip_rounded_rect =
284  FlutterRoundedRect{
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},
290  },
291  },
292  {
293  .type = kFlutterPlatformViewMutationTypeTransformation,
294  .transformation =
295  FlutterTransformation{
296  .scaleX = 1,
297  .transX = 100,
298  .scaleY = 1,
299  .transY = 50,
300  },
301  },
302  };
303 
304  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
305 
306  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 50, 10, 20)));
307  EXPECT_TRUE(
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);
311 }
312 
313 // Ensure that the mutator view, clip views, and container all use a flipped y axis. The transforms
314 // sent from the framework assume this, and so aside from the consistency with every other embedder,
315 // we can avoid a lot of extra math.
316 TEST(FlutterMutatorViewTest, ViewsSetIsFlipped) {
317  NSView* platformView = [[NSView alloc] init];
318  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
319 
320  std::vector<FlutterPlatformViewMutation> mutations{
321  {
322  .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
323  .clip_rounded_rect =
324  FlutterRoundedRect{
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},
330  },
331  },
332  {
333  .type = kFlutterPlatformViewMutationTypeTransformation,
334  .transformation =
335  FlutterTransformation{
336  .scaleX = 1,
337  .transX = 100,
338  .scaleY = 1,
339  .transY = 50,
340  },
341  },
342  };
343 
344  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
345 
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);
350 }
351 
352 TEST(FlutterMutatorViewTest, RectsClipsToPathWhenRotated) {
353  NSView* platformView = [[NSView alloc] init];
354  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
355  std::vector<FlutterPlatformViewMutation> mutations{
356  {
357  .type = kFlutterPlatformViewMutationTypeTransformation,
358  // Roation M_PI / 8
359  .transformation =
360  FlutterTransformation{
361  .scaleX = 0.9238795325112867,
362  .skewX = -0.3826834323650898,
363  .skewY = 0.3826834323650898,
364  .scaleY = 0.9238795325112867,
365  },
366  },
367  {
368  .type = kFlutterPlatformViewMutationTypeClipRect,
369  .clip_rect = FlutterRect{110, 60, 150, 150},
370  },
371  {
372  .type = kFlutterPlatformViewMutationTypeTransformation,
373  .transformation =
374  FlutterTransformation{
375  .scaleX = 1,
376  .transX = 100,
377  .scaleY = 1,
378  .transY = 50,
379  },
380  },
381  };
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);
386 }
387 
388 TEST(FlutterMutatorViewTest, RoundRectClipsToPath) {
389  NSView* platformView = [[NSView alloc] init];
390  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
391 
392  std::vector<FlutterPlatformViewMutation> mutations{
393  {
394  .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
395  .clip_rounded_rect =
396  FlutterRoundedRect{
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},
402  },
403  },
404  {
405  .type = kFlutterPlatformViewMutationTypeTransformation,
406  .transformation =
407  FlutterTransformation{
408  .scaleX = 1,
409  .transX = 100,
410  .scaleY = 1,
411  .transY = 50,
412  },
413  },
414  };
415 
416  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
417 
418  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
419  EXPECT_TRUE(
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));
425 }
426 
427 TEST(FlutterMutatorViewTest, PathClipViewsAreAddedAndRemoved) {
428  NSView* platformView = [[NSView alloc] init];
429  FlutterMutatorView* mutatorView = [[FlutterMutatorView alloc] initWithPlatformView:platformView];
430 
431  std::vector<FlutterPlatformViewMutation> mutations{
432  {
433  .type = kFlutterPlatformViewMutationTypeTransformation,
434  .transformation =
435  FlutterTransformation{
436  .scaleX = 1,
437  .transX = 100,
438  .scaleY = 1,
439  .transY = 50,
440  },
441  },
442  };
443 
444  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
445 
446  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
447  EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
448 
449  std::vector<FlutterPlatformViewMutation> mutations2{
450  {
451  .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
452  .clip_rounded_rect =
453  FlutterRoundedRect{
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},
459  },
460  },
461  {
462  .type = kFlutterPlatformViewMutationTypeTransformation,
463  .transformation =
464  FlutterTransformation{
465  .scaleX = 1,
466  .transX = 100,
467  .scaleY = 1,
468  .transY = 50,
469  },
470  },
471  };
472 
473  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
474 
475  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
476  EXPECT_TRUE(
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);
480 
481  EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
482  EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
483  EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
484 
485  std::vector<FlutterPlatformViewMutation> mutations3{
486  {
487  .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
488  .clip_rounded_rect =
489  FlutterRoundedRect{
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},
495  },
496  },
497  {
498  .type = kFlutterPlatformViewMutationTypeClipRoundedRect,
499  .clip_rounded_rect =
500  FlutterRoundedRect{
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},
506  },
507  },
508  {
509  .type = kFlutterPlatformViewMutationTypeTransformation,
510  .transformation =
511  FlutterTransformation{
512  .scaleX = 1,
513  .transX = 100,
514  .scaleY = 1,
515  .transY = 50,
516  },
517  },
518  };
519 
520  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations3);
521 
522  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 55, 10, 10)));
523  EXPECT_TRUE(
524  CGRectEqualToRect(mutatorView.subviews.firstObject.frame, CGRectMake(-10, -5, 30, 20)));
525  EXPECT_EQ(mutatorView.pathClipViews.count, 2ul);
526 
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);
531 
532  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations2);
533 
534  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(110, 60, 20, 10)));
535  EXPECT_TRUE(
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);
539 
540  EXPECT_EQ(platformView.superview, mutatorView.platformViewContainer);
541  EXPECT_EQ(mutatorView.platformViewContainer.superview, mutatorView.pathClipViews[0]);
542  EXPECT_EQ(mutatorView.pathClipViews[0].superview, mutatorView);
543 
544  ApplyFlutterLayer(mutatorView, FlutterSize{30, 20}, mutations);
545 
546  EXPECT_TRUE(CGRectEqualToRect(mutatorView.frame, CGRectMake(100, 50, 30, 20)));
547  EXPECT_EQ(mutatorView.pathClipViews.count, 0ull);
548 }
FlutterMutatorView.h
FlutterMutatorView
Definition: FlutterMutatorView.h:11
FlutterMutatorView::platformView
NSView * platformView
Returns wrapped platform view.
Definition: FlutterMutatorView.h:17
FlutterMutatorView(Private)::pathClipViews
NSMutableArray< NSView * > * pathClipViews
Definition: FlutterMutatorViewTest.mm:13
kMaxErr
static constexpr float kMaxErr
Definition: FlutterMutatorViewTest.mm:18
FlutterMutatorView(Private)::platformViewContainer
NSView * platformViewContainer
Definition: FlutterMutatorViewTest.mm:14
FlutterMutatorView(Private)
Definition: FlutterMutatorViewTest.mm:11
NSView+ClipsToBounds.h
TEST
TEST(FlutterMutatorViewTest, BasicFrameIsCorrect)
Definition: FlutterMutatorViewTest.mm:75
-[FlutterMutatorView applyFlutterLayer:]
void applyFlutterLayer:(nonnull const FlutterLayer *layer)