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 
6 
7 #include "flutter/display_list/effects/dl_image_filter.h"
8 #include "flutter/fml/platform/darwin/cf_utils.h"
10 
12 
13 static constexpr int kMaxPointsInVerb = 4;
14 static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;
15 
16 namespace flutter {
17 
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 
29 
31  : layer_pool_(std::make_unique<FlutterPlatformViewLayerPool>()),
32  weak_factory_(std::make_unique<fml::WeakPtrFactory<FlutterPlatformViewsController>>(this)) {
33  mask_view_pool_.reset(
35 };
36 
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 
116  _preparedOnce = NO;
117  _gaussianBlurFilter = nil;
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"]) {
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"]) {
139  }
140  }
141  _preparedOnce = YES;
142 }
143 
144 + (BOOL)isUIVisualEffectViewImplementationValid {
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 
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 - (fml::CFRef<CGPathRef>)getTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix;
240 
241 @end
242 
243 @implementation FlutterClippingMaskView {
244  std::vector<fml::CFRef<CGPathRef>> paths_;
246  CGRect rectSoFar_;
247 }
248 
249 - (instancetype)initWithFrame:(CGRect)frame {
250  return [self initWithFrame:frame screenScale:[UIScreen mainScreen].scale];
251 }
252 
253 - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale {
254  if (self = [super initWithFrame:frame]) {
255  self.backgroundColor = UIColor.clearColor;
256  _reverseScreenScale = CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1);
257  rectSoFar_ = self.bounds;
259  }
260  return self;
261 }
262 
263 + (Class)layerClass {
264  return [CAShapeLayer class];
265 }
266 
267 - (CAShapeLayer*)shapeLayer {
268  return (CAShapeLayer*)self.layer;
269 }
270 
271 - (void)reset {
272  paths_.clear();
273  rectSoFar_ = self.bounds;
275  [self shapeLayer].path = nil;
276  [self setNeedsDisplay];
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)drawRect:(CGRect)rect {
289  // It's hard to compute intersection of arbitrary non-rect paths.
290  // So we fallback to software rendering.
291  if (containsNonRectPath_ && paths_.size() > 1) {
292  CGContextRef context = UIGraphicsGetCurrentContext();
293  CGContextSaveGState(context);
294 
295  // For mask view, only the alpha channel is used.
296  CGContextSetAlpha(context, 1);
297 
298  for (size_t i = 0; i < paths_.size(); i++) {
299  CGContextAddPath(context, paths_.at(i));
300  CGContextClip(context);
301  }
302  CGContextFillRect(context, rect);
303  CGContextRestoreGState(context);
304  } else {
305  // Either a single path, or multiple rect paths.
306  // Use hardware rendering with CAShapeLayer.
307  [super drawRect:rect];
308  if (![self shapeLayer].path) {
309  if (paths_.size() == 1) {
310  // A single path, either rect or non-rect.
311  [self shapeLayer].path = paths_.at(0);
312  } else {
313  // Multiple paths, all paths must be rects.
314  CGPathRef pathSoFar = CGPathCreateWithRect(rectSoFar_, nil);
315  [self shapeLayer].path = pathSoFar;
316  CGPathRelease(pathSoFar);
317  }
318  }
319  }
320 }
321 
322 - (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix {
323  CGRect clipRect = flutter::GetCGRectFromSkRect(clipSkRect);
324  CGPathRef path = CGPathCreateWithRect(clipRect, nil);
325  // The `matrix` is based on the physical pixels, convert it to UIKit points.
326  CATransform3D matrixInPoints =
327  CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
328  paths_.push_back([self getTransformedPath:path matrix:matrixInPoints]);
329  CGAffineTransform affine = [self affineWithMatrix:matrixInPoints];
330  // Make sure the rect is not rotated (only translated or scaled).
331  if (affine.b == 0 && affine.c == 0) {
332  rectSoFar_ = CGRectIntersection(rectSoFar_, CGRectApplyAffineTransform(clipRect, affine));
333  } else {
334  containsNonRectPath_ = YES;
335  }
336 }
337 
338 - (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix {
339  containsNonRectPath_ = YES;
340  CGPathRef pathRef = nullptr;
341  switch (clipSkRRect.getType()) {
342  case SkRRect::kEmpty_Type: {
343  break;
344  }
345  case SkRRect::kRect_Type: {
346  [self clipRect:clipSkRRect.rect() matrix:matrix];
347  return;
348  }
349  case SkRRect::kOval_Type:
350  case SkRRect::kSimple_Type: {
351  CGRect clipRect = flutter::GetCGRectFromSkRect(clipSkRRect.rect());
352  pathRef = CGPathCreateWithRoundedRect(clipRect, clipSkRRect.getSimpleRadii().x(),
353  clipSkRRect.getSimpleRadii().y(), nil);
354  break;
355  }
356  case SkRRect::kNinePatch_Type:
357  case SkRRect::kComplex_Type: {
358  CGMutablePathRef mutablePathRef = CGPathCreateMutable();
359  // Complex types, we manually add each corner.
360  SkRect clipSkRect = clipSkRRect.rect();
361  SkVector topLeftRadii = clipSkRRect.radii(SkRRect::kUpperLeft_Corner);
362  SkVector topRightRadii = clipSkRRect.radii(SkRRect::kUpperRight_Corner);
363  SkVector bottomRightRadii = clipSkRRect.radii(SkRRect::kLowerRight_Corner);
364  SkVector bottomLeftRadii = clipSkRRect.radii(SkRRect::kLowerLeft_Corner);
365 
366  // Start drawing RRect
367  // Move point to the top left corner adding the top left radii's x.
368  CGPathMoveToPoint(mutablePathRef, nil, clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop);
369  // Move point horizontally right to the top right corner and add the top right curve.
370  CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight - topRightRadii.x(),
371  clipSkRect.fTop);
372  CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fTop,
373  clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y(),
374  clipSkRect.fRight, clipSkRect.fTop + topRightRadii.y());
375  // Move point vertically down to the bottom right corner and add the bottom right curve.
376  CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fRight,
377  clipSkRect.fBottom - bottomRightRadii.y());
378  CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fRight, clipSkRect.fBottom,
379  clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom,
380  clipSkRect.fRight - bottomRightRadii.x(), clipSkRect.fBottom);
381  // Move point horizontally left to the bottom left corner and add the bottom left curve.
382  CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft + bottomLeftRadii.x(),
383  clipSkRect.fBottom);
384  CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fBottom,
385  clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y(),
386  clipSkRect.fLeft, clipSkRect.fBottom - bottomLeftRadii.y());
387  // Move point vertically up to the top left corner and add the top left curve.
388  CGPathAddLineToPoint(mutablePathRef, nil, clipSkRect.fLeft,
389  clipSkRect.fTop + topLeftRadii.y());
390  CGPathAddCurveToPoint(mutablePathRef, nil, clipSkRect.fLeft, clipSkRect.fTop,
391  clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop,
392  clipSkRect.fLeft + topLeftRadii.x(), clipSkRect.fTop);
393  CGPathCloseSubpath(mutablePathRef);
394 
395  pathRef = mutablePathRef;
396  break;
397  }
398  }
399  // The `matrix` is based on the physical pixels, convert it to UIKit points.
400  CATransform3D matrixInPoints =
401  CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
402  // TODO(cyanglaz): iOS does not seem to support hard edge on CAShapeLayer. It clearly stated that
403  // the CAShaperLayer will be drawn antialiased. Need to figure out a way to do the hard edge
404  // clipping on iOS.
405  paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
406 }
407 
408 - (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
409  if (!path.isValid()) {
410  return;
411  }
412  if (path.isEmpty()) {
413  return;
414  }
415  containsNonRectPath_ = YES;
416  CGMutablePathRef pathRef = CGPathCreateMutable();
417 
418  // Loop through all verbs and translate them into CGPath
419  SkPath::Iter iter(path, true);
420  SkPoint pts[kMaxPointsInVerb];
421  SkPath::Verb verb = iter.next(pts);
422  SkPoint last_pt_from_last_verb = SkPoint::Make(0, 0);
423  while (verb != SkPath::kDone_Verb) {
424  if (verb == SkPath::kLine_Verb || verb == SkPath::kQuad_Verb || verb == SkPath::kConic_Verb ||
425  verb == SkPath::kCubic_Verb) {
426  FML_DCHECK(last_pt_from_last_verb == pts[0]);
427  }
428  switch (verb) {
429  case SkPath::kMove_Verb: {
430  CGPathMoveToPoint(pathRef, nil, pts[0].x(), pts[0].y());
431  last_pt_from_last_verb = pts[0];
432  break;
433  }
434  case SkPath::kLine_Verb: {
435  CGPathAddLineToPoint(pathRef, nil, pts[1].x(), pts[1].y());
436  last_pt_from_last_verb = pts[1];
437  break;
438  }
439  case SkPath::kQuad_Verb: {
440  CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
441  last_pt_from_last_verb = pts[2];
442  break;
443  }
444  case SkPath::kConic_Verb: {
445  // Conic is not available in quartz, we use quad to approximate.
446  // TODO(cyanglaz): Better approximate the conic path.
447  // https://github.com/flutter/flutter/issues/35062
448  CGPathAddQuadCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
449  last_pt_from_last_verb = pts[2];
450  break;
451  }
452  case SkPath::kCubic_Verb: {
453  CGPathAddCurveToPoint(pathRef, nil, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(),
454  pts[3].x(), pts[3].y());
455  last_pt_from_last_verb = pts[3];
456  break;
457  }
458  case SkPath::kClose_Verb: {
459  CGPathCloseSubpath(pathRef);
460  break;
461  }
462  case SkPath::kDone_Verb: {
463  break;
464  }
465  }
466  verb = iter.next(pts);
467  }
468  // The `matrix` is based on the physical pixels, convert it to UIKit points.
469  CATransform3D matrixInPoints =
470  CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
471  paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
472 }
473 
474 - (CGAffineTransform)affineWithMatrix:(CATransform3D)matrix {
475  return CGAffineTransformMake(matrix.m11, matrix.m12, matrix.m21, matrix.m22, matrix.m41,
476  matrix.m42);
477 }
478 
479 - (fml::CFRef<CGPathRef>)getTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix {
480  CGAffineTransform affine = [self affineWithMatrix:matrix];
481  CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(path, &affine);
482 
483  CGPathRelease(path);
484  return fml::CFRef<CGPathRef>(transformedPath);
485 }
486 
487 @end
488 
490 
491 // The maximum number of `FlutterClippingMaskView` the pool can contain.
492 // This prevents the pool to grow infinately and limits the maximum memory a pool can use.
493 @property(nonatomic) NSUInteger capacity;
494 
495 // The pool contains the views that are available to use.
496 // The number of items in the pool must not excceds `capacity`.
497 @property(nonatomic) NSMutableSet<FlutterClippingMaskView*>* pool;
498 
499 @end
500 
501 @implementation FlutterClippingMaskViewPool : NSObject
502 
503 - (instancetype)initWithCapacity:(NSInteger)capacity {
504  if (self = [super init]) {
505  // Most of cases, there are only one PlatformView in the scene.
506  // Thus init with the capacity of 1.
507  _pool = [[NSMutableSet alloc] initWithCapacity:1];
508  _capacity = capacity;
509  }
510  return self;
511 }
512 
513 - (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame {
514  FML_DCHECK(self.pool.count <= self.capacity);
515  if (self.pool.count == 0) {
516  // The pool is empty, alloc a new one.
517  return [[FlutterClippingMaskView alloc] initWithFrame:frame
518  screenScale:UIScreen.mainScreen.scale];
519  }
520  FlutterClippingMaskView* maskView = [self.pool anyObject];
521  maskView.frame = frame;
522  [maskView reset];
523  [self.pool removeObject:maskView];
524  return maskView;
525 }
526 
527 - (void)insertViewToPoolIfNeeded:(FlutterClippingMaskView*)maskView {
528  FML_DCHECK(![self.pool containsObject:maskView]);
529  FML_DCHECK(self.pool.count <= self.capacity);
530  if (self.pool.count == self.capacity) {
531  return;
532  }
533  [self.pool addObject:maskView];
534 }
535 
536 @end
containsNonRectPath_
BOOL containsNonRectPath_
Definition: FlutterPlatformViews_Internal.mm:243
-[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:322
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
rectSoFar_
CGRect rectSoFar_
Definition: FlutterPlatformViews_Internal.mm:246
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:271
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