| Flutter iOS Embedder |

FlutterPlatformViews_Internal.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
5 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
6
7 #include "flutter/display_list/effects/dl_image_filter.h"
8 #include "flutter/fml/platform/darwin/cf_utils.h"
9 #import "flutter/shell/platform/darwin/ios/ios_surface.h"
10
11 FLUTTER_ASSERT_ARC
12
13 static constexpr int kMaxPointsInVerb = 4;
14 static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;
15
16 namespace flutter {
17
18 FlutterPlatformViewLayer::FlutterPlatformViewLayer(
19 const fml::scoped_nsobject<UIView>& overlay_view,
20 const fml::scoped_nsobject<UIView>& overlay_view_wrapper,
21 std::unique_ptr<IOSSurface> ios_surface,
22 std::unique_ptr<Surface> surface)
23 : overlay_view(overlay_view),
24 overlay_view_wrapper(overlay_view_wrapper),
25 ios_surface(std::move(ios_surface)),
26 surface(std::move(surface)){};
27
28 FlutterPlatformViewLayer::~FlutterPlatformViewLayer() = default;
29
30 FlutterPlatformViewsController::FlutterPlatformViewsController()
31 : layer_pool_(std::make_unique<FlutterPlatformViewLayerPool>()),
32 weak_factory_(std::make_unique<fml::WeakPtrFactory<FlutterPlatformViewsController>>(this)) {
33 mask_view_pool_.reset(
34 [[FlutterClippingMaskViewPool alloc] initWithCapacity:kFlutterClippingMaskViewPoolCapacity]);
35 };
36
37 FlutterPlatformViewsController::~FlutterPlatformViewsController() = default;
38
39 fml::WeakPtr<flutter::FlutterPlatformViewsController> FlutterPlatformViewsController::GetWeakPtr() {
40 return weak_factory_->GetWeakPtr();
41 }
42
43 CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
44 // Skia only supports 2D transform so we don't map z.
45 CATransform3D transform = CATransform3DIdentity;
46 transform.m11 = matrix.getScaleX();
47 transform.m21 = matrix.getSkewX();
48 transform.m41 = matrix.getTranslateX();
49 transform.m14 = matrix.getPerspX();
50
51 transform.m12 = matrix.getSkewY();
52 transform.m22 = matrix.getScaleY();
53 transform.m42 = matrix.getTranslateY();
54 transform.m24 = matrix.getPerspY();
55 return transform;
56 }
57
58 void ResetAnchor(CALayer* layer) {
59 // Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz.
60 layer.anchorPoint = CGPointZero;
61 layer.position = CGPointZero;
62 }
63
64 CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) {
65 return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft,
66 clipSkRect.fBottom - clipSkRect.fTop);
67 }
68
69 BOOL BlurRadiusEqualToBlurRadius(CGFloat radius1, CGFloat radius2) {
70 const CGFloat epsilon = 0.01;
71 return radius1 - radius2 < epsilon;
72 }
73
74 } // namespace flutter
75
76 @interface PlatformViewFilter ()
77
78 // `YES` if the backdropFilterView has been configured at least once.
79 @property(nonatomic) BOOL backdropFilterViewConfigured;
80 @property(nonatomic) UIVisualEffectView* backdropFilterView;
81
82 // Updates the `visualEffectView` with the current filter parameters.
83 // Also sets `self.backdropFilterView` to the updated visualEffectView.
84 - (void)updateVisualEffectView:(UIVisualEffectView*)visualEffectView;
85
86 @end
87
88 @implementation PlatformViewFilter
89
90 static NSObject* _gaussianBlurFilter = nil;
91 // The index of "_UIVisualEffectBackdropView" in UIVisualEffectView's subViews.
92 static NSInteger _indexOfBackdropView = -1;
93 // The index of "_UIVisualEffectSubview" in UIVisualEffectView's subViews.
94 static NSInteger _indexOfVisualEffectSubview = -1;
95 static BOOL _preparedOnce = NO;
96
97 - (instancetype)initWithFrame:(CGRect)frame
98 blurRadius:(CGFloat)blurRadius
99 visualEffectView:(UIVisualEffectView*)visualEffectView {
100 if (self = [super init]) {
101 _frame = frame;
102 _blurRadius = blurRadius;
103 [PlatformViewFilter prepareOnce:visualEffectView];
104 if (![PlatformViewFilter isUIVisualEffectViewImplementationValid]) {
105 FML_DLOG(ERROR) << "Apple's API for UIVisualEffectView changed. Update the implementation to "
106 "access the gaussianBlur CAFilter.";
107 return nil;
108 }
109 _backdropFilterView = visualEffectView;
110 _backdropFilterViewConfigured = NO;
111 }
112 return self;
113 }
114
115 + (void)resetPreparation {
116 _preparedOnce = NO;
117 _gaussianBlurFilter = nil;
118 _indexOfBackdropView = -1;
119 _indexOfVisualEffectSubview = -1;
120 }
121
122 + (void)prepareOnce:(UIVisualEffectView*)visualEffectView {
123 if (_preparedOnce) {
124 return;
125 }
126 for (NSUInteger i = 0; i < visualEffectView.subviews.count; i++) {
127 UIView* view = visualEffectView.subviews[i];
128 if ([NSStringFromClass([view class]) hasSuffix:@"BackdropView"]) {
129 _indexOfBackdropView = i;
130 for (NSObject* filter in view.layer.filters) {
131 if ([[filter valueForKey:@"name"] isEqual:@"gaussianBlur"] &&
132 [[filter valueForKey:@"inputRadius"] isKindOfClass:[NSNumber class]]) {
133 _gaussianBlurFilter = filter;
134 break;
135 }
136 }
137 } else if ([NSStringFromClass([view class]) hasSuffix:@"VisualEffectSubview"]) {
138 _indexOfVisualEffectSubview = i;
139 }
140 }
141 _preparedOnce = YES;
142 }
143
144 + (BOOL)isUIVisualEffectViewImplementationValid {
145 return _indexOfBackdropView > -1 && _indexOfVisualEffectSubview > -1 && _gaussianBlurFilter;
146 }
147
148 - (UIVisualEffectView*)backdropFilterView {
149 FML_DCHECK(_backdropFilterView);
150 if (!self.backdropFilterViewConfigured) {
151 [self updateVisualEffectView:_backdropFilterView];
152 self.backdropFilterViewConfigured = YES;
153 }
154 return _backdropFilterView;
155 }
156
157 - (void)updateVisualEffectView:(UIVisualEffectView*)visualEffectView {
158 NSObject* gaussianBlurFilter = [_gaussianBlurFilter copy];
159 FML_DCHECK(gaussianBlurFilter);
160 UIView* backdropView = visualEffectView.subviews[_indexOfBackdropView];
161 [gaussianBlurFilter setValue:@(_blurRadius) forKey:@"inputRadius"];
162 backdropView.layer.filters = @[ gaussianBlurFilter ];
163
164 UIView* visualEffectSubview = visualEffectView.subviews[_indexOfVisualEffectSubview];
165 visualEffectSubview.layer.backgroundColor = UIColor.clearColor.CGColor;
166 visualEffectView.frame = _frame;
167
168 self.backdropFilterView = visualEffectView;
169 }
170
171 @end
172
173 @interface ChildClippingView ()
174
175 @property(nonatomic, copy) NSArray<PlatformViewFilter*>* filters;
176 @property(nonatomic) NSMutableArray<UIVisualEffectView*>* backdropFilterSubviews;
177
178 @end
179
180 @implementation ChildClippingView
181
182 // The ChildClippingView's frame is the bounding rect of the platform view. we only want touches to
183 // be hit tested and consumed by this view if they are inside the embedded platform view which could
184 // be smaller the embedded platform view is rotated.
185 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
186 for (UIView* view in self.subviews) {
187 if ([view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
188 return YES;
189 }
190 }
191 return NO;
192 }
193
194 - (void)applyBlurBackdropFilters:(NSArray<PlatformViewFilter*>*)filters {
195 FML_DCHECK(self.filters.count == self.backdropFilterSubviews.count);
196 if (self.filters.count == 0 && filters.count == 0) {
197 return;
198 }
199 self.filters = filters;
200 NSUInteger index = 0;
201 for (index = 0; index < self.filters.count; index++) {
202 UIVisualEffectView* backdropFilterView;
203 PlatformViewFilter* filter = self.filters[index];
204 if (self.backdropFilterSubviews.count <= index) {
205 backdropFilterView = filter.backdropFilterView;
206 [self addSubview:backdropFilterView];
207 [self.backdropFilterSubviews addObject:backdropFilterView];
208 } else {
209 [filter updateVisualEffectView:self.backdropFilterSubviews[index]];
210 }
211 }
212 for (NSUInteger i = self.backdropFilterSubviews.count; i > index; i--) {
213 [self.backdropFilterSubviews[i - 1] removeFromSuperview];
214 [self.backdropFilterSubviews removeLastObject];
215 }
216 }
217
218 - (NSMutableArray*)backdropFilterSubviews {
219 if (!_backdropFilterSubviews) {
220 _backdropFilterSubviews = [[NSMutableArray alloc] init];
221 }
222 return _backdropFilterSubviews;
223 }
224
225 @end
226
227 @interface FlutterClippingMaskView ()
228
229 // A `CATransform3D` matrix represnts a scale transform that revese UIScreen.scale.
230 //
231 // The transform matrix passed in clipRect/clipRRect/clipPath methods are in device coordinate
232 // space. The transfrom matrix concats `reverseScreenScale` to create a transform matrix in the iOS
233 // logical coordinates (points).
234 //
235 // See https://developer.apple.com/documentation/uikit/uiscreen/1617836-scale?language=objc for
236 // information about screen scale.
237 @property(nonatomic) CATransform3D reverseScreenScale;
238
239 - (void)addTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix;
240
241 @end
242
243 @implementation FlutterClippingMaskView {
244 CGMutablePathRef pathSoFar_;
245 }
246
247 - (instancetype)initWithFrame:(CGRect)frame {
248 return [self initWithFrame:frame screenScale:[UIScreen mainScreen].scale];
249 }
250
251 - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale {
252 if (self = [super initWithFrame:frame]) {
253 self.backgroundColor = UIColor.clearColor;
254 _reverseScreenScale = CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1);
255 pathSoFar_ = CGPathCreateMutable();
256 }
257 return self;
258 }
259
260 + (Class)layerClass {
261 return [CAShapeLayer class];
262 }
263
264 - (CAShapeLayer*)shapeLayer {
265 return (CAShapeLayer*)self.layer;
266 }
267
268 - (void)reset {
269 CGPathRelease(pathSoFar_);
270 pathSoFar_ = CGPathCreateMutable();
271 [self shapeLayer].path = nil;
272 [self setNeedsDisplay];
273 }
274
275 - (void)dealloc {
276 CGPathRelease(pathSoFar_);
277 }
278
279 // In some scenarios, when we add this view as a maskView of the ChildClippingView, iOS added
280 // this view as a subview of the ChildClippingView.
281 // This results this view blocking touch events on the ChildClippingView.
282 // So we should always ignore any touch events sent to this view.
283 // See https://github.com/flutter/flutter/issues/66044
284 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
285 return NO;
286 }
287
288 - (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix {
289 CGRect clipRect = flutter::GetCGRectFromSkRect(clipSkRect);
290 CGPathRef path = CGPathCreateWithRect(clipRect, nil);
291 // The `matrix` is based on the physical pixels, convert it to UIKit points.
292 CATransform3D matrixInPoints =
293 CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
294 [self addTransformedPath:path matrix:matrixInPoints];
295 }
296
297 - (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix {
298 CGPathRef pathRef = nullptr;
299 switch (clipSkRRect.getType()) {
300 case SkRRect::kEmpty_Type: {
301 break;
302 }
303 case SkRRect::kRect_Type: {
304 [self clipRect:clipSkRRect.rect() matrix:matrix];
305 return;
306 }
307 case SkRRect::kOval_Type:
308 case SkRRect::kSimple_Type: {
309 CGRect clipRect = flutter::GetCGRectFromSkRect(clipSkRRect.rect());
310 pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(),
311 clipSkRRect.getSimpleRadii().y(), nil);
312 break;
313 }
314 case SkRRect::kNinePatch_Type:
315 case SkRRect::kComplex_Type: {
316 CGMutablePathRef mutablePathRef = CGPathCreateMutable();
317 // Complex types, we manually add each corner.
318 SkRect clipSkRect = clipSkRRect.rect();
319 SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner);
320 SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner);
321 SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner);
322 SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner);
323
324 // Start drawing RRect
325 // Move point to the top left corner adding the top left radii's x.
326 CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop);
327 // Move point horizontally right to the top right corner and add the top right curve.
328 CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(),
329 clipSkRect.fTop);
330 CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop,
331 clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(),
332 clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y());
333 // Move point vertically down to the bottom right corner and add the bottom right curve.
334 CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight,
335 clipSkRect.fBottom - bottomRightRadii.y());
336 CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom,
337 clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom,
338 clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom);
339 // Move point horizontally left to the bottom left corner and add the bottom left curve.
340 CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(),
341 clipSkRect.fBottom);
342 CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom,
343 clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(),
344 clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y());
345 // Move point vertically up to the top left corner and add the top left curve.
346 CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft,
347 clipSkRect.fTop + topLeftRadii.y());
348 CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop,
349 clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop,
350 clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop);
351 CGPathCloseSubpath(mutablePathRef);
352
353 pathRef = mutablePathRef;
354 break;
355 }
356 }
357 // The `matrix` is based on the physical pixels, convert it to UIKit points.
358 CATransform3D matrixInPoints =
359 CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
360 // TODO(cyanglaz): iOS does not seem to support hard edge on CAShapeLayer. It clearly stated that
361 // the CAShaperLayer will be drawn antialiased. Need to figure out a way to do the hard edge
362 // clipping on iOS.
363 [self addTransformedPath:pathRef matrix:matrixInPoints];
364 }
365
366 - (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
367 if (!path.isValid()) {
368 return;
369 }
370 if (path.isEmpty()) {
371 return;
372 }
373 CGMutablePathRef pathRef = CGPathCreateMutable();
374
375 // Loop through all verbs and translate them into CGPath
376 SkPath::Iter iter(path, true);
377 SkPoint pts[kMaxPointsInVerb];
378 SkPath::Verb verb = iter.next(pts);
379 SkPoint last_pt_from_last_verb = SkPoint::Make(0, 0);
380 while (verb != SkPath::kDone_Verb) {
381 if (verb == SkPath::kLine_Verb || verb == SkPath::kQuad_Verb || verb == SkPath::kConic_Verb ||
382 verb == SkPath::kCubic_Verb) {
383 FML_DCHECK(last_pt_from_last_verb == pts[0]);
384 }
385 switch (verb) {
386 case SkPath::kMove_Verb: {
387 CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y());
388 last_pt_from_last_verb = pts[0];
389 break;
390 }
391 case SkPath::kLine_Verb: {
392 CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y());
393 last_pt_from_last_verb = pts[1];
394 break;
395 }
396 case SkPath::kQuad_Verb: {
397 CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
398 last_pt_from_last_verb = pts[2];
399 break;
400 }
401 case SkPath::kConic_Verb: {
402 // Conic is not available in quartz, we use quad to approximate.
403 // TODO(cyanglaz): Better approximate the conic path.
404 // https://github.com/flutter/flutter/issues/35062
405 CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
406 last_pt_from_last_verb = pts[2];
407 break;
408 }
409 case SkPath::kCubic_Verb: {
410 CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(),
411 pts[3].x(), pts[3].y());
412 last_pt_from_last_verb = pts[3];
413 break;
414 }
415 case SkPath::kClose_Verb: {
416 CGPathCloseSubpath(pathRef);
417 break;
418 }
419 case SkPath::kDone_Verb: {
420 break;
421 }
422 }
423 verb = iter.next(pts);
424 }
425 // The `matrix` is based on the physical pixels, convert it to UIKit points.
426 CATransform3D matrixInPoints =
427 CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
428 [self addTransformedPath:pathRef matrix:matrixInPoints];
429 }
430
431 - (void)addTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix {
432 CGAffineTransform affine =
433 CGAffineTransformMake(matrix.m11, matrix.m12, matrix.m21, matrix.m22, matrix.m41, matrix.m42);
434 CGPathAddPath(pathSoFar_, &affine, path);
435 [self shapeLayer].path = pathSoFar_;
436 CGPathRelease(path);
437 }
438
439 @end
440
441 @interface FlutterClippingMaskViewPool ()
442
443 // The maximum number of `FlutterClippingMaskView` the pool can contain.
444 // This prevents the pool to grow infinately and limits the maximum memory a pool can use.
445 @property(nonatomic) NSUInteger capacity;
446
447 // The pool contains the views that are available to use.
448 // The number of items in the pool must not excceds `capacity`.
449 @property(nonatomic) NSMutableSet<FlutterClippingMaskView*>* pool;
450
451 @end
452
453 @implementation FlutterClippingMaskViewPool : NSObject
454
455 - (instancetype)initWithCapacity:(NSInteger)capacity {
456 if (self = [super init]) {
457 // Most of cases, there are only one PlatformView in the scene.
458 // Thus init with the capacity of 1.
459 _pool = [[NSMutableSet alloc] initWithCapacity:1];
460 _capacity = capacity;
461 }
462 return self;
463 }
464
465 - (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame {
466 FML_DCHECK(self.pool.count <= self.capacity);
467 if (self.pool.count == 0) {
468 // The pool is empty, alloc a new one.
469 return [[FlutterClippingMaskView alloc] initWithFrame:frame
470 screenScale:UIScreen.mainScreen.scale];
471 }
472 FlutterClippingMaskView* maskView = [self.pool anyObject];
473 maskView.frame = frame;
474 [maskView reset];
475 [self.pool removeObject:maskView];
476 return maskView;
477 }
478
479 - (void)insertViewToPoolIfNeeded:(FlutterClippingMaskView*)maskView {
480 FML_DCHECK(![self.pool containsObject:maskView]);
481 FML_DCHECK(self.pool.count <= self.capacity);
482 if (self.pool.count == self.capacity) {
483 return;
484 }
485 [self.pool addObject:maskView];
486 }
487
488 @end
-[flutter::FlutterPlatformViewsController FlutterPlatformViewsController]
FlutterPlatformViewsController()
Definition: FlutterPlatformViews_Internal.mm:30
-[flutter::FlutterPlatformViewLayer ~FlutterPlatformViewLayer]
~FlutterPlatformViewLayer()
-[flutter::FlutterPlatformViewsController GetWeakPtr]
fml::WeakPtr< flutter::FlutterPlatformViewsController > GetWeakPtr()
Definition: FlutterPlatformViews_Internal.mm:39
_gaussianBlurFilter
static NSObject * _gaussianBlurFilter
Definition: FlutterPlatformViews_Internal.mm:90
PlatformViewFilter::frame
CGRect frame
Definition: FlutterPlatformViews_Internal.h:84
flutter::BlurRadiusEqualToBlurRadius
BOOL BlurRadiusEqualToBlurRadius(CGFloat radius1, CGFloat radius2)
Definition: FlutterPlatformViews_Internal.mm:69
_indexOfVisualEffectSubview
static NSInteger _indexOfVisualEffectSubview
Definition: FlutterPlatformViews_Internal.mm:94
_preparedOnce
static BOOL _preparedOnce
Definition: FlutterPlatformViews_Internal.mm:95
-[FlutterClippingMaskView clipRect:matrix:]
void clipRect:matrix:(const SkRect &clipSkRect,[matrix] const SkMatrix &matrix)
Definition: FlutterPlatformViews_Internal.mm:288
initWithFrame
instancetype initWithFrame
Definition: FlutterTextInputPlugin.h:172
flutter::ResetAnchor
void ResetAnchor(CALayer *layer)
Definition: FlutterPlatformViews_Internal.mm:58
-[ChildClippingView backdropFilterSubviews]
NSMutableArray * backdropFilterSubviews()
Definition: FlutterPlatformViews_Internal.mm:218
kFlutterClippingMaskViewPoolCapacity
static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity
Definition: FlutterPlatformViews_Internal.mm:14
PlatformViewFilter::blurRadius
CGFloat blurRadius
Definition: FlutterPlatformViews_Internal.h:89
ios_surface.h
flutter::FlutterPlatformViewLayerPool
Definition: FlutterPlatformViews_Internal.h:167
-[FlutterClippingMaskView reset]
void reset()
Definition: FlutterPlatformViews_Internal.mm:268
PlatformViewFilter::backdropFilterView
UIVisualEffectView * backdropFilterView
Definition: FlutterPlatformViews_Internal.h:95
flutter
Definition: accessibility_bridge.h:28
FlutterPlatformViews_Internal.h
_indexOfBackdropView
static NSInteger _indexOfBackdropView
Definition: FlutterPlatformViews_Internal.mm:92
-[flutter::FlutterPlatformViewsController ~FlutterPlatformViewsController]
~FlutterPlatformViewsController()
FlutterClippingMaskViewPool
Definition: FlutterPlatformViews_Internal.h:62
-[flutter::FlutterPlatformViewLayer FlutterPlatformViewLayer]
FlutterPlatformViewLayer(const fml::scoped_nsobject< UIView > &overlay_view, const fml::scoped_nsobject< UIView > &overlay_view_wrapper, std::unique_ptr< IOSSurface > ios_surface, std::unique_ptr< Surface > surface)
Definition: FlutterPlatformViews_Internal.mm:18
ChildClippingView
Definition: FlutterPlatformViews_Internal.h:119
+[PlatformViewFilter resetPreparation]
void resetPreparation()
Definition: FlutterPlatformViews_Internal.mm:115
flutter::GetCATransform3DFromSkMatrix
CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix &matrix)
Definition: FlutterPlatformViews_Internal.mm:43
flutter::GetCGRectFromSkRect
CGRect GetCGRectFromSkRect(const SkRect &clipSkRect)
Definition: FlutterPlatformViews_Internal.mm:64
PlatformViewFilter
Definition: FlutterPlatformViews_Internal.h:80
kMaxPointsInVerb
static constexpr FLUTTER_ASSERT_ARC int kMaxPointsInVerb
Definition: FlutterPlatformViews_Internal.mm:13
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13
flutter::FlutterPlatformViewsController
Definition: FlutterPlatformViews_Internal.h:205
FlutterClippingMaskView
Definition: FlutterPlatformViews_Internal.h:31