@@ -1856,6 +1856,102 @@ - (void)testClipRect {
18561856 }
18571857}
18581858
1859+ - (void )testClipRect_multipleClips {
1860+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1861+
1862+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
1863+ /* platform=*/ GetDefaultTaskRunner (),
1864+ /* raster=*/ GetDefaultTaskRunner (),
1865+ /* ui=*/ GetDefaultTaskRunner (),
1866+ /* io=*/ GetDefaultTaskRunner ());
1867+ auto flutterPlatformViewsController = std::make_shared<flutter::PlatformViewsController>();
1868+ flutterPlatformViewsController->SetTaskRunner (GetDefaultTaskRunner ());
1869+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1870+ /* delegate=*/ mock_delegate,
1871+ /* rendering_api=*/ mock_delegate.settings_ .enable_impeller
1872+ ? flutter::IOSRenderingAPI::kMetal
1873+ : flutter::IOSRenderingAPI::kSoftware ,
1874+ /* platform_views_controller=*/ flutterPlatformViewsController,
1875+ /* task_runners=*/ runners,
1876+ /* worker_task_runner=*/ nil ,
1877+ /* is_gpu_disabled_jsync_switch=*/ std::make_shared<fml::SyncSwitch>());
1878+
1879+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
1880+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc ] init ];
1881+ flutterPlatformViewsController->RegisterViewFactory (
1882+ factory, @" MockFlutterPlatformView" ,
1883+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
1884+ FlutterResult result = ^(id result) {
1885+ };
1886+ flutterPlatformViewsController->OnMethodCall (
1887+ [FlutterMethodCall
1888+ methodCallWithMethodName: @" create"
1889+ arguments: @{@" id" : @2 , @" viewType" : @" MockFlutterPlatformView" }],
1890+ result);
1891+
1892+ XCTAssertNotNil (gMockPlatformView );
1893+
1894+ UIView* flutterView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 10 , 10 )];
1895+ flutterPlatformViewsController->SetFlutterView (flutterView);
1896+ // Create embedded view params
1897+ flutter::MutatorsStack stack;
1898+ // Layer tree always pushes a screen scale factor to the stack
1899+ SkMatrix screenScaleMatrix =
1900+ SkMatrix::Scale ([UIScreen mainScreen ].scale , [UIScreen mainScreen ].scale );
1901+ stack.PushTransform (screenScaleMatrix);
1902+ // Push a clip rect
1903+ SkRect rect1 = SkRect::MakeXYWH (2 , 2 , 3 , 3 );
1904+ stack.PushClipRect (rect1);
1905+ // Push another clip rect
1906+ SkRect rect2 = SkRect::MakeXYWH (3 , 3 , 3 , 3 );
1907+ stack.PushClipRect (rect2);
1908+
1909+ auto embeddedViewParams =
1910+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make (10 , 10 ), stack);
1911+
1912+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (2 , std::move (embeddedViewParams));
1913+ flutterPlatformViewsController->CompositeWithParams (
1914+ 2 , flutterPlatformViewsController->GetCompositionParams (2 ));
1915+
1916+ gMockPlatformView .backgroundColor = UIColor.redColor ;
1917+ XCTAssertTrue ([gMockPlatformView .superview.superview isKindOfClass: ChildClippingView.class ]);
1918+ ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView .superview .superview ;
1919+ [flutterView addSubview: childClippingView];
1920+
1921+ [flutterView setNeedsLayout ];
1922+ [flutterView layoutIfNeeded ];
1923+
1924+ /*
1925+ clip 1 clip 2
1926+ 2 3 4 5 6 2 3 4 5 6
1927+ 2 + - - + 2
1928+ 3 | | 3 + - - +
1929+ 4 | | 4 | |
1930+ 5 + - - + 5 | |
1931+ 6 6 + - - +
1932+
1933+ Result should be the intersection of 2 clips
1934+ 2 3 4 5 6
1935+ 2
1936+ 3 + - +
1937+ 4 | |
1938+ 5 + - +
1939+ 6
1940+ */
1941+ CGRect insideClipping = CGRectMake (3 , 3 , 2 , 2 );
1942+ for (int i = 0 ; i < 10 ; i++) {
1943+ for (int j = 0 ; j < 10 ; j++) {
1944+ CGPoint point = CGPointMake (i, j);
1945+ int alpha = [self alphaOfPoint: CGPointMake (i, j) onView: flutterView];
1946+ if (CGRectContainsPoint (insideClipping, point)) {
1947+ XCTAssertEqual (alpha, 255 );
1948+ } else {
1949+ XCTAssertEqual (alpha, 0 );
1950+ }
1951+ }
1952+ }
1953+ }
1954+
18591955- (void )testClipRRect {
18601956 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
18611957
@@ -1959,6 +2055,126 @@ - (void)testClipRRect {
19592055 }
19602056}
19612057
2058+ - (void )testClipRRect_multipleClips {
2059+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2060+
2061+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
2062+ /* platform=*/ GetDefaultTaskRunner (),
2063+ /* raster=*/ GetDefaultTaskRunner (),
2064+ /* ui=*/ GetDefaultTaskRunner (),
2065+ /* io=*/ GetDefaultTaskRunner ());
2066+ auto flutterPlatformViewsController = std::make_shared<flutter::PlatformViewsController>();
2067+ flutterPlatformViewsController->SetTaskRunner (GetDefaultTaskRunner ());
2068+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2069+ /* delegate=*/ mock_delegate,
2070+ /* rendering_api=*/ mock_delegate.settings_ .enable_impeller
2071+ ? flutter::IOSRenderingAPI::kMetal
2072+ : flutter::IOSRenderingAPI::kSoftware ,
2073+ /* platform_views_controller=*/ flutterPlatformViewsController,
2074+ /* task_runners=*/ runners,
2075+ /* worker_task_runner=*/ nil ,
2076+ /* is_gpu_disabled_jsync_switch=*/ std::make_shared<fml::SyncSwitch>());
2077+
2078+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2079+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc ] init ];
2080+ flutterPlatformViewsController->RegisterViewFactory (
2081+ factory, @" MockFlutterPlatformView" ,
2082+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2083+ FlutterResult result = ^(id result) {
2084+ };
2085+ flutterPlatformViewsController->OnMethodCall (
2086+ [FlutterMethodCall
2087+ methodCallWithMethodName: @" create"
2088+ arguments: @{@" id" : @2 , @" viewType" : @" MockFlutterPlatformView" }],
2089+ result);
2090+
2091+ XCTAssertNotNil (gMockPlatformView );
2092+
2093+ UIView* flutterView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 10 , 10 )];
2094+ flutterPlatformViewsController->SetFlutterView (flutterView);
2095+ // Create embedded view params
2096+ flutter::MutatorsStack stack;
2097+ // Layer tree always pushes a screen scale factor to the stack
2098+ SkMatrix screenScaleMatrix =
2099+ SkMatrix::Scale ([UIScreen mainScreen ].scale , [UIScreen mainScreen ].scale );
2100+ stack.PushTransform (screenScaleMatrix);
2101+ // Push a clip rrect
2102+ SkRRect rrect = SkRRect::MakeRectXY (SkRect::MakeXYWH (2 , 2 , 6 , 6 ), 1 , 1 );
2103+ stack.PushClipRRect (rrect);
2104+ // Push a clip rect
2105+ SkRect rect = SkRect::MakeXYWH (4 , 2 , 6 , 6 );
2106+ stack.PushClipRect (rect);
2107+
2108+ auto embeddedViewParams =
2109+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make (10 , 10 ), stack);
2110+
2111+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (2 , std::move (embeddedViewParams));
2112+ flutterPlatformViewsController->CompositeWithParams (
2113+ 2 , flutterPlatformViewsController->GetCompositionParams (2 ));
2114+
2115+ gMockPlatformView .backgroundColor = UIColor.redColor ;
2116+ XCTAssertTrue ([gMockPlatformView .superview.superview isKindOfClass: ChildClippingView.class ]);
2117+ ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView .superview .superview ;
2118+ [flutterView addSubview: childClippingView];
2119+
2120+ [flutterView setNeedsLayout ];
2121+ [flutterView layoutIfNeeded ];
2122+
2123+ /*
2124+ clip 1 clip 2
2125+ 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9
2126+ 2 / - - - - \ 2 + - - - - +
2127+ 3 | | 3 | |
2128+ 4 | | 4 | |
2129+ 5 | | 5 | |
2130+ 6 | | 6 | |
2131+ 7 \ - - - - / 7 + - - - - +
2132+
2133+ Result should be the intersection of 2 clips
2134+ 2 3 4 5 6 7 8 9
2135+ 2 + - - \
2136+ 3 | |
2137+ 4 | |
2138+ 5 | |
2139+ 6 | |
2140+ 7 + - - /
2141+ */
2142+ CGRect clipping = CGRectMake (4 , 2 , 4 , 6 );
2143+ for (int i = 0 ; i < 10 ; i++) {
2144+ for (int j = 0 ; j < 10 ; j++) {
2145+ CGPoint point = CGPointMake (i, j);
2146+ int alpha = [self alphaOfPoint: CGPointMake (i, j) onView: flutterView];
2147+ if (i == 7 && (j == 2 || j == 7 )) {
2148+ // Upper and lower right corners should be partially transparent.
2149+ XCTAssert (0 < alpha && alpha < 255 );
2150+ } else if (
2151+ // left
2152+ (i == 4 && j >= 2 && j <= 7 ) ||
2153+ // right
2154+ (i == 7 && j >= 2 && j <= 7 ) ||
2155+ // top
2156+ (j == 2 && i >= 4 && i <= 7 ) ||
2157+ // bottom
2158+ (j == 7 && i >= 4 && i <= 7 )) {
2159+ // Since we are falling back to software rendering for this case
2160+ // The edge pixels can be anti-aliased, so it may not be fully opaque.
2161+ XCTAssert (alpha > 127 );
2162+ } else if ((i == 3 && j >= 1 && j <= 8 ) || (i == 8 && j >= 1 && j <= 8 ) ||
2163+ (j == 1 && i >= 3 && i <= 8 ) || (j == 8 && i >= 3 && i <= 8 )) {
2164+ // Since we are falling back to software rendering for this case
2165+ // The edge pixels can be anti-aliased, so it may not be fully transparent.
2166+ XCTAssert (alpha < 127 );
2167+ } else if (CGRectContainsPoint (clipping, point)) {
2168+ // Other pixels inside clipping should be fully opaque.
2169+ XCTAssertEqual (alpha, 255 );
2170+ } else {
2171+ // Pixels outside clipping should be fully transparent.
2172+ XCTAssertEqual (alpha, 0 );
2173+ }
2174+ }
2175+ }
2176+ }
2177+
19622178- (void )testClipPath {
19632179 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
19642180
@@ -2063,6 +2279,127 @@ - (void)testClipPath {
20632279 }
20642280}
20652281
2282+ - (void )testClipPath_multipleClips {
2283+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2284+
2285+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
2286+ /* platform=*/ GetDefaultTaskRunner (),
2287+ /* raster=*/ GetDefaultTaskRunner (),
2288+ /* ui=*/ GetDefaultTaskRunner (),
2289+ /* io=*/ GetDefaultTaskRunner ());
2290+ auto flutterPlatformViewsController = std::make_shared<flutter::PlatformViewsController>();
2291+ flutterPlatformViewsController->SetTaskRunner (GetDefaultTaskRunner ());
2292+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2293+ /* delegate=*/ mock_delegate,
2294+ /* rendering_api=*/ mock_delegate.settings_ .enable_impeller
2295+ ? flutter::IOSRenderingAPI::kMetal
2296+ : flutter::IOSRenderingAPI::kSoftware ,
2297+ /* platform_views_controller=*/ flutterPlatformViewsController,
2298+ /* task_runners=*/ runners,
2299+ /* worker_task_runner=*/ nil ,
2300+ /* is_gpu_disabled_jsync_switch=*/ std::make_shared<fml::SyncSwitch>());
2301+
2302+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2303+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc ] init ];
2304+ flutterPlatformViewsController->RegisterViewFactory (
2305+ factory, @" MockFlutterPlatformView" ,
2306+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2307+ FlutterResult result = ^(id result) {
2308+ };
2309+ flutterPlatformViewsController->OnMethodCall (
2310+ [FlutterMethodCall
2311+ methodCallWithMethodName: @" create"
2312+ arguments: @{@" id" : @2 , @" viewType" : @" MockFlutterPlatformView" }],
2313+ result);
2314+
2315+ XCTAssertNotNil (gMockPlatformView );
2316+
2317+ UIView* flutterView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 10 , 10 )];
2318+ flutterPlatformViewsController->SetFlutterView (flutterView);
2319+ // Create embedded view params
2320+ flutter::MutatorsStack stack;
2321+ // Layer tree always pushes a screen scale factor to the stack
2322+ SkMatrix screenScaleMatrix =
2323+ SkMatrix::Scale ([UIScreen mainScreen ].scale , [UIScreen mainScreen ].scale );
2324+ stack.PushTransform (screenScaleMatrix);
2325+ // Push a clip path
2326+ SkPath path;
2327+ path.addRoundRect (SkRect::MakeXYWH (2 , 2 , 6 , 6 ), 1 , 1 );
2328+ stack.PushClipPath (path);
2329+ // Push a clip rect
2330+ SkRect rect = SkRect::MakeXYWH (4 , 2 , 6 , 6 );
2331+ stack.PushClipRect (rect);
2332+
2333+ auto embeddedViewParams =
2334+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make (10 , 10 ), stack);
2335+
2336+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (2 , std::move (embeddedViewParams));
2337+ flutterPlatformViewsController->CompositeWithParams (
2338+ 2 , flutterPlatformViewsController->GetCompositionParams (2 ));
2339+
2340+ gMockPlatformView .backgroundColor = UIColor.redColor ;
2341+ XCTAssertTrue ([gMockPlatformView .superview.superview isKindOfClass: ChildClippingView.class ]);
2342+ ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView .superview .superview ;
2343+ [flutterView addSubview: childClippingView];
2344+
2345+ [flutterView setNeedsLayout ];
2346+ [flutterView layoutIfNeeded ];
2347+
2348+ /*
2349+ clip 1 clip 2
2350+ 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9
2351+ 2 / - - - - \ 2 + - - - - +
2352+ 3 | | 3 | |
2353+ 4 | | 4 | |
2354+ 5 | | 5 | |
2355+ 6 | | 6 | |
2356+ 7 \ - - - - / 7 + - - - - +
2357+
2358+ Result should be the intersection of 2 clips
2359+ 2 3 4 5 6 7 8 9
2360+ 2 + - - \
2361+ 3 | |
2362+ 4 | |
2363+ 5 | |
2364+ 6 | |
2365+ 7 + - - /
2366+ */
2367+ CGRect clipping = CGRectMake (4 , 2 , 4 , 6 );
2368+ for (int i = 0 ; i < 10 ; i++) {
2369+ for (int j = 0 ; j < 10 ; j++) {
2370+ CGPoint point = CGPointMake (i, j);
2371+ int alpha = [self alphaOfPoint: CGPointMake (i, j) onView: flutterView];
2372+ if (i == 7 && (j == 2 || j == 7 )) {
2373+ // Upper and lower right corners should be partially transparent.
2374+ XCTAssert (0 < alpha && alpha < 255 );
2375+ } else if (
2376+ // left
2377+ (i == 4 && j >= 2 && j <= 7 ) ||
2378+ // right
2379+ (i == 7 && j >= 2 && j <= 7 ) ||
2380+ // top
2381+ (j == 2 && i >= 4 && i <= 7 ) ||
2382+ // bottom
2383+ (j == 7 && i >= 4 && i <= 7 )) {
2384+ // Since we are falling back to software rendering for this case
2385+ // The edge pixels can be anti-aliased, so it may not be fully opaque.
2386+ XCTAssert (alpha > 127 );
2387+ } else if ((i == 3 && j >= 1 && j <= 8 ) || (i == 8 && j >= 1 && j <= 8 ) ||
2388+ (j == 1 && i >= 3 && i <= 8 ) || (j == 8 && i >= 3 && i <= 8 )) {
2389+ // Since we are falling back to software rendering for this case
2390+ // The edge pixels can be anti-aliased, so it may not be fully transparent.
2391+ XCTAssert (alpha < 127 );
2392+ } else if (CGRectContainsPoint (clipping, point)) {
2393+ // Other pixels inside clipping should be fully opaque.
2394+ XCTAssertEqual (alpha, 255 );
2395+ } else {
2396+ // Pixels outside clipping should be fully transparent.
2397+ XCTAssertEqual (alpha, 0 );
2398+ }
2399+ }
2400+ }
2401+ }
2402+
20662403- (void )testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
20672404 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
20682405
0 commit comments