Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c0bbc06

Browse files
author
auto-submit[bot]
committed
Revert "[ios][platform_view] Use CAShapeLayer as the mask to avoid software rendering (#53072)"
This reverts commit 1314faf.
1 parent 1314faf commit c0bbc06

13 files changed

+38
-150
lines changed

shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm

Lines changed: 14 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,15 +1773,17 @@ - (void)testClipRect {
17731773
[mockFlutterView setNeedsLayout];
17741774
[mockFlutterView layoutIfNeeded];
17751775

1776-
CGRect insideClipping = CGRectMake(2, 2, 3, 3);
17771776
for (int i = 0; i < 10; i++) {
17781777
for (int j = 0; j < 10; j++) {
17791778
CGPoint point = CGPointMake(i, j);
17801779
int alpha = [self alphaOfPoint:CGPointMake(i, j) onView:mockFlutterView];
1780+
// Edges of the clipping might have a semi transparent pixel, we only check the pixels that
1781+
// are fully inside the clipped area.
1782+
CGRect insideClipping = CGRectMake(3, 3, 1, 1);
17811783
if (CGRectContainsPoint(insideClipping, point)) {
17821784
XCTAssertEqual(alpha, 255);
17831785
} else {
1784-
XCTAssertEqual(alpha, 0);
1786+
XCTAssertLessThan(alpha, 255);
17851787
}
17861788
}
17871789
}
@@ -1846,42 +1848,17 @@ - (void)testClipRRect {
18461848
[mockFlutterView setNeedsLayout];
18471849
[mockFlutterView layoutIfNeeded];
18481850

1849-
/*
1850-
ClippingMask outterClipping
1851-
2 3 4 5 6 7 2 3 4 5 6 7
1852-
2 / - - - - \ 2 + - - - - +
1853-
3 | | 3 | |
1854-
4 | | 4 | |
1855-
5 | | 5 | |
1856-
6 | | 6 | |
1857-
7 \ - - - - / 7 + - - - - +
1858-
1859-
innerClipping1 innerClipping2
1860-
2 3 4 5 6 7 2 3 4 5 6 7
1861-
2 + - - + 2
1862-
3 | | 3 + - - - - +
1863-
4 | | 4 | |
1864-
5 | | 5 | |
1865-
6 | | 6 + - - - - +
1866-
7 + - - + 7
1867-
*/
1868-
CGRect innerClipping1 = CGRectMake(3, 2, 4, 6);
1869-
CGRect innerClipping2 = CGRectMake(2, 3, 6, 4);
1870-
CGRect outterClipping = CGRectMake(2, 2, 6, 6);
18711851
for (int i = 0; i < 10; i++) {
18721852
for (int j = 0; j < 10; j++) {
18731853
CGPoint point = CGPointMake(i, j);
18741854
int alpha = [self alphaOfPoint:CGPointMake(i, j) onView:mockFlutterView];
1875-
if (CGRectContainsPoint(innerClipping1, point) ||
1876-
CGRectContainsPoint(innerClipping2, point)) {
1877-
// Pixels inside either of the 2 inner clippings should be fully opaque.
1855+
// Edges of the clipping might have a semi transparent pixel, we only check the pixels that
1856+
// are fully inside the clipped area.
1857+
CGRect insideClipping = CGRectMake(3, 3, 4, 4);
1858+
if (CGRectContainsPoint(insideClipping, point)) {
18781859
XCTAssertEqual(alpha, 255);
1879-
} else if (CGRectContainsPoint(outterClipping, point)) {
1880-
// Corner pixels (i.e. (2, 2), (2, 7), (7, 2) and (7, 7)) should be partially transparent.
1881-
XCTAssert(0 < alpha && alpha < 255);
18821860
} else {
1883-
// Pixels outside outterClipping should be fully transparent.
1884-
XCTAssertEqual(alpha, 0);
1861+
XCTAssertLessThan(alpha, 255);
18851862
}
18861863
}
18871864
}
@@ -1947,42 +1924,17 @@ - (void)testClipPath {
19471924
[mockFlutterView setNeedsLayout];
19481925
[mockFlutterView layoutIfNeeded];
19491926

1950-
/*
1951-
ClippingMask outterClipping
1952-
2 3 4 5 6 7 2 3 4 5 6 7
1953-
2 / - - - - \ 2 + - - - - +
1954-
3 | | 3 | |
1955-
4 | | 4 | |
1956-
5 | | 5 | |
1957-
6 | | 6 | |
1958-
7 \ - - - - / 7 + - - - - +
1959-
1960-
innerClipping1 innerClipping2
1961-
2 3 4 5 6 7 2 3 4 5 6 7
1962-
2 + - - + 2
1963-
3 | | 3 + - - - - +
1964-
4 | | 4 | |
1965-
5 | | 5 | |
1966-
6 | | 6 + - - - - +
1967-
7 + - - + 7
1968-
*/
1969-
CGRect innerClipping1 = CGRectMake(3, 2, 4, 6);
1970-
CGRect innerClipping2 = CGRectMake(2, 3, 6, 4);
1971-
CGRect outterClipping = CGRectMake(2, 2, 6, 6);
19721927
for (int i = 0; i < 10; i++) {
19731928
for (int j = 0; j < 10; j++) {
19741929
CGPoint point = CGPointMake(i, j);
19751930
int alpha = [self alphaOfPoint:CGPointMake(i, j) onView:mockFlutterView];
1976-
if (CGRectContainsPoint(innerClipping1, point) ||
1977-
CGRectContainsPoint(innerClipping2, point)) {
1978-
// Pixels inside either of the 2 inner clippings should be fully opaque.
1931+
// Edges of the clipping might have a semi transparent pixel, we only check the pixels that
1932+
// are fully inside the clipped area.
1933+
CGRect insideClipping = CGRectMake(3, 3, 4, 4);
1934+
if (CGRectContainsPoint(insideClipping, point)) {
19791935
XCTAssertEqual(alpha, 255);
1980-
} else if (CGRectContainsPoint(outterClipping, point)) {
1981-
// Corner pixels (i.e. (2, 2), (2, 7), (7, 2) and (7, 7)) should be partially transparent.
1982-
XCTAssert(0 < alpha && alpha < 255);
19831936
} else {
1984-
// Pixels outside outterClipping should be fully transparent.
1985-
XCTAssertEqual(alpha, 0);
1937+
XCTAssertLessThan(alpha, 255);
19861938
}
19871939
}
19881940
}
@@ -3037,69 +2989,6 @@ - (void)testDifferentClipMaskViewIsUsedForEachView {
30372989
XCTAssertNotEqual(maskView1, maskView2);
30382990
}
30392991

3040-
- (void)testMaskViewUsesCAShapeLayerAsTheBackingLayer {
3041-
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
3042-
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
3043-
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
3044-
/*platform=*/thread_task_runner,
3045-
/*raster=*/thread_task_runner,
3046-
/*ui=*/thread_task_runner,
3047-
/*io=*/thread_task_runner);
3048-
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
3049-
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
3050-
/*delegate=*/mock_delegate,
3051-
/*rendering_api=*/mock_delegate.settings_.enable_impeller
3052-
? flutter::IOSRenderingAPI::kMetal
3053-
: flutter::IOSRenderingAPI::kSoftware,
3054-
/*platform_views_controller=*/flutterPlatformViewsController,
3055-
/*task_runners=*/runners,
3056-
/*worker_task_runner=*/nil,
3057-
/*is_gpu_disabled_jsync_switch=*/std::make_shared<fml::SyncSwitch>());
3058-
3059-
FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
3060-
[[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init];
3061-
flutterPlatformViewsController->RegisterViewFactory(
3062-
factory, @"MockFlutterPlatformView",
3063-
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
3064-
FlutterResult result = ^(id result) {
3065-
};
3066-
3067-
flutterPlatformViewsController->OnMethodCall(
3068-
[FlutterMethodCall
3069-
methodCallWithMethodName:@"create"
3070-
arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}],
3071-
result);
3072-
3073-
XCTAssertNotNil(gMockPlatformView);
3074-
UIView* mockFlutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
3075-
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
3076-
// Create embedded view params
3077-
flutter::MutatorsStack stack1;
3078-
// Layer tree always pushes a screen scale factor to the stack
3079-
SkMatrix screenScaleMatrix =
3080-
SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
3081-
stack1.PushTransform(screenScaleMatrix);
3082-
// Push a clip rect
3083-
SkRect rect = SkRect::MakeXYWH(2, 2, 3, 3);
3084-
stack1.PushClipRect(rect);
3085-
3086-
auto embeddedViewParams1 = std::make_unique<flutter::EmbeddedViewParams>(
3087-
screenScaleMatrix, SkSize::Make(10, 10), stack1);
3088-
3089-
flutter::MutatorsStack stack2;
3090-
stack2.PushClipRect(rect);
3091-
auto embeddedViewParams2 = std::make_unique<flutter::EmbeddedViewParams>(
3092-
screenScaleMatrix, SkSize::Make(10, 10), stack2);
3093-
3094-
flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1));
3095-
flutterPlatformViewsController->CompositeEmbeddedView(1);
3096-
UIView* childClippingView = gMockPlatformView.superview.superview;
3097-
3098-
UIView* maskView = childClippingView.maskView;
3099-
XCTAssert([maskView.layer isKindOfClass:[CAShapeLayer class]],
3100-
@"Mask view must use CAShapeLayer as its backing layer.");
3101-
}
3102-
31032992
// Return true if a correct visual effect view is found. It also implies all the validation in this
31042993
// method passes.
31052994
//

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,12 @@ @interface FlutterClippingMaskView ()
236236
// information about screen scale.
237237
@property(nonatomic) CATransform3D reverseScreenScale;
238238

239-
- (void)addTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix;
239+
- (fml::CFRef<CGPathRef>)getTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix;
240240

241241
@end
242242

243243
@implementation FlutterClippingMaskView {
244-
CGMutablePathRef pathSoFar_;
244+
std::vector<fml::CFRef<CGPathRef>> paths_;
245245
}
246246

247247
- (instancetype)initWithFrame:(CGRect)frame {
@@ -252,31 +252,15 @@ - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale {
252252
if (self = [super initWithFrame:frame]) {
253253
self.backgroundColor = UIColor.clearColor;
254254
_reverseScreenScale = CATransform3DMakeScale(1 / screenScale, 1 / screenScale, 1);
255-
pathSoFar_ = CGPathCreateMutable();
256255
}
257256
return self;
258257
}
259258

260-
+ (Class)layerClass {
261-
return [CAShapeLayer class];
262-
}
263-
264-
- (CAShapeLayer*)shapeLayer {
265-
return (CAShapeLayer*)self.layer;
266-
}
267-
268259
- (void)reset {
269-
CGPathRelease(pathSoFar_);
270-
pathSoFar_ = CGPathCreateMutable();
271-
[self shapeLayer].path = nil;
260+
paths_.clear();
272261
[self setNeedsDisplay];
273262
}
274263

275-
- (void)dealloc {
276-
CGPathRelease(pathSoFar_);
277-
[super dealloc];
278-
}
279-
280264
// In some scenarios, when we add this view as a maskView of the ChildClippingView, iOS added
281265
// this view as a subview of the ChildClippingView.
282266
// This results this view blocking touch events on the ChildClippingView.
@@ -286,13 +270,28 @@ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
286270
return NO;
287271
}
288272

273+
- (void)drawRect:(CGRect)rect {
274+
CGContextRef context = UIGraphicsGetCurrentContext();
275+
CGContextSaveGState(context);
276+
277+
// For mask view, only the alpha channel is used.
278+
CGContextSetAlpha(context, 1);
279+
280+
for (size_t i = 0; i < paths_.size(); i++) {
281+
CGContextAddPath(context, paths_.at(i));
282+
CGContextClip(context);
283+
}
284+
CGContextFillRect(context, rect);
285+
CGContextRestoreGState(context);
286+
}
287+
289288
- (void)clipRect:(const SkRect&)clipSkRect matrix:(const SkMatrix&)matrix {
290289
CGRect clipRect = flutter::GetCGRectFromSkRect(clipSkRect);
291290
CGPathRef path = CGPathCreateWithRect(clipRect, nil);
292291
// The `matrix` is based on the physical pixels, convert it to UIKit points.
293292
CATransform3D matrixInPoints =
294293
CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
295-
[self addTransformedPath:path matrix:matrixInPoints];
294+
paths_.push_back([self getTransformedPath:path matrix:matrixInPoints]);
296295
}
297296

298297
- (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix {
@@ -361,7 +360,7 @@ - (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const SkMatrix&)matrix {
361360
// TODO(cyanglaz): iOS does not seem to support hard edge on CAShapeLayer. It clearly stated that
362361
// the CAShaperLayer will be drawn antialiased. Need to figure out a way to do the hard edge
363362
// clipping on iOS.
364-
[self addTransformedPath:pathRef matrix:matrixInPoints];
363+
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
365364
}
366365

367366
- (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
@@ -426,15 +425,15 @@ - (void)clipPath:(const SkPath&)path matrix:(const SkMatrix&)matrix {
426425
// The `matrix` is based on the physical pixels, convert it to UIKit points.
427426
CATransform3D matrixInPoints =
428427
CATransform3DConcat(flutter::GetCATransform3DFromSkMatrix(matrix), _reverseScreenScale);
429-
[self addTransformedPath:pathRef matrix:matrixInPoints];
428+
paths_.push_back([self getTransformedPath:pathRef matrix:matrixInPoints]);
430429
}
431430

432-
- (void)addTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix {
431+
- (fml::CFRef<CGPathRef>)getTransformedPath:(CGPathRef)path matrix:(CATransform3D)matrix {
433432
CGAffineTransform affine =
434433
CGAffineTransformMake(matrix.m11, matrix.m12, matrix.m21, matrix.m22, matrix.m41, matrix.m42);
435-
CGPathAddPath(pathSoFar_, &affine, path);
436-
[self shapeLayer].path = pathSoFar_;
434+
CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(path, &affine);
437435
CGPathRelease(path);
436+
return fml::CFRef<CGPathRef>(transformedPath);
438437
}
439438

440439
@end
-8.64 KB
Loading
Loading
Loading
Loading
-8.27 KB
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)