@@ -1787,6 +1787,100 @@ - (void)testClipRect {
17871787 }
17881788}
17891789
1790+ - (void )testClipRect_multipleClips {
1791+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1792+ auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
1793+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
1794+ /* platform=*/ thread_task_runner,
1795+ /* raster=*/ thread_task_runner,
1796+ /* ui=*/ thread_task_runner,
1797+ /* io=*/ thread_task_runner);
1798+ auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
1799+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1800+ /* delegate=*/ mock_delegate,
1801+ /* rendering_api=*/ mock_delegate.settings_ .enable_impeller
1802+ ? flutter::IOSRenderingAPI::kMetal
1803+ : flutter::IOSRenderingAPI::kSoftware ,
1804+ /* platform_views_controller=*/ flutterPlatformViewsController,
1805+ /* task_runners=*/ runners,
1806+ /* worker_task_runner=*/ nil ,
1807+ /* is_gpu_disabled_jsync_switch=*/ std::make_shared<fml::SyncSwitch>());
1808+
1809+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
1810+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc ] init ];
1811+ flutterPlatformViewsController->RegisterViewFactory (
1812+ factory, @" MockFlutterPlatformView" ,
1813+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
1814+ FlutterResult result = ^(id result) {
1815+ };
1816+ flutterPlatformViewsController->OnMethodCall (
1817+ [FlutterMethodCall
1818+ methodCallWithMethodName: @" create"
1819+ arguments: @{@" id" : @2 , @" viewType" : @" MockFlutterPlatformView" }],
1820+ result);
1821+
1822+ XCTAssertNotNil (gMockPlatformView );
1823+
1824+ UIView* flutterView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 10 , 10 )];
1825+ flutterPlatformViewsController->SetFlutterView (flutterView);
1826+ // Create embedded view params
1827+ flutter::MutatorsStack stack;
1828+ // Layer tree always pushes a screen scale factor to the stack
1829+ SkMatrix screenScaleMatrix =
1830+ SkMatrix::Scale ([UIScreen mainScreen ].scale , [UIScreen mainScreen ].scale );
1831+ stack.PushTransform (screenScaleMatrix);
1832+ // Push a clip rect
1833+ SkRect rect1 = SkRect::MakeXYWH (2 , 2 , 3 , 3 );
1834+ stack.PushClipRect (rect1);
1835+ // Push another clip rect
1836+ SkRect rect2 = SkRect::MakeXYWH (3 , 3 , 3 , 3 );
1837+ stack.PushClipRect (rect2);
1838+
1839+ auto embeddedViewParams =
1840+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make (10 , 10 ), stack);
1841+
1842+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (2 , std::move (embeddedViewParams));
1843+ flutterPlatformViewsController->CompositeEmbeddedView (2 );
1844+
1845+ gMockPlatformView .backgroundColor = UIColor.redColor ;
1846+ XCTAssertTrue ([gMockPlatformView .superview.superview isKindOfClass: ChildClippingView.class ]);
1847+ ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView .superview .superview ;
1848+ [flutterView addSubview: childClippingView];
1849+
1850+ [flutterView setNeedsLayout ];
1851+ [flutterView layoutIfNeeded ];
1852+
1853+ /*
1854+ clip 1 clip 2
1855+ 2 3 4 5 6 2 3 4 5 6
1856+ 2 + - - + 2
1857+ 3 | | 3 + - - +
1858+ 4 | | 4 | |
1859+ 5 + - - + 5 | |
1860+ 6 6 + - - +
1861+
1862+ Result should be the intersection of 2 clips
1863+ 2 3 4 5 6
1864+ 2
1865+ 3 + - +
1866+ 4 | |
1867+ 5 + - +
1868+ 6
1869+ */
1870+ CGRect insideClipping = CGRectMake (3 , 3 , 2 , 2 );
1871+ for (int i = 0 ; i < 10 ; i++) {
1872+ for (int j = 0 ; j < 10 ; j++) {
1873+ CGPoint point = CGPointMake (i, j);
1874+ int alpha = [self alphaOfPoint: CGPointMake (i, j) onView: flutterView];
1875+ if (CGRectContainsPoint (insideClipping, point)) {
1876+ XCTAssertEqual (alpha, 255 );
1877+ } else {
1878+ XCTAssertEqual (alpha, 0 );
1879+ }
1880+ }
1881+ }
1882+ }
1883+
17901884- (void )testClipRRect {
17911885 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
17921886 auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
@@ -1887,6 +1981,124 @@ - (void)testClipRRect {
18871981 }
18881982}
18891983
1984+ - (void )testClipRRect_multipleClips {
1985+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
1986+ auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
1987+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
1988+ /* platform=*/ thread_task_runner,
1989+ /* raster=*/ thread_task_runner,
1990+ /* ui=*/ thread_task_runner,
1991+ /* io=*/ thread_task_runner);
1992+ auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
1993+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1994+ /* delegate=*/ mock_delegate,
1995+ /* rendering_api=*/ mock_delegate.settings_ .enable_impeller
1996+ ? flutter::IOSRenderingAPI::kMetal
1997+ : flutter::IOSRenderingAPI::kSoftware ,
1998+ /* platform_views_controller=*/ flutterPlatformViewsController,
1999+ /* task_runners=*/ runners,
2000+ /* worker_task_runner=*/ nil ,
2001+ /* is_gpu_disabled_jsync_switch=*/ std::make_shared<fml::SyncSwitch>());
2002+
2003+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2004+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc ] init ];
2005+ flutterPlatformViewsController->RegisterViewFactory (
2006+ factory, @" MockFlutterPlatformView" ,
2007+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2008+ FlutterResult result = ^(id result) {
2009+ };
2010+ flutterPlatformViewsController->OnMethodCall (
2011+ [FlutterMethodCall
2012+ methodCallWithMethodName: @" create"
2013+ arguments: @{@" id" : @2 , @" viewType" : @" MockFlutterPlatformView" }],
2014+ result);
2015+
2016+ XCTAssertNotNil (gMockPlatformView );
2017+
2018+ UIView* flutterView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 10 , 10 )];
2019+ flutterPlatformViewsController->SetFlutterView (flutterView);
2020+ // Create embedded view params
2021+ flutter::MutatorsStack stack;
2022+ // Layer tree always pushes a screen scale factor to the stack
2023+ SkMatrix screenScaleMatrix =
2024+ SkMatrix::Scale ([UIScreen mainScreen ].scale , [UIScreen mainScreen ].scale );
2025+ stack.PushTransform (screenScaleMatrix);
2026+ // Push a clip rrect
2027+ SkRRect rrect = SkRRect::MakeRectXY (SkRect::MakeXYWH (2 , 2 , 6 , 6 ), 1 , 1 );
2028+ stack.PushClipRRect (rrect);
2029+ // Push a clip rect
2030+ SkRect rect = SkRect::MakeXYWH (4 , 2 , 6 , 6 );
2031+ stack.PushClipRect (rect);
2032+
2033+ auto embeddedViewParams =
2034+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make (10 , 10 ), stack);
2035+
2036+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (2 , std::move (embeddedViewParams));
2037+ flutterPlatformViewsController->CompositeEmbeddedView (2 );
2038+
2039+ gMockPlatformView .backgroundColor = UIColor.redColor ;
2040+ XCTAssertTrue ([gMockPlatformView .superview.superview isKindOfClass: ChildClippingView.class ]);
2041+ ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView .superview .superview ;
2042+ [flutterView addSubview: childClippingView];
2043+
2044+ [flutterView setNeedsLayout ];
2045+ [flutterView layoutIfNeeded ];
2046+
2047+ /*
2048+ clip 1 clip 2
2049+ 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9
2050+ 2 / - - - - \ 2 + - - - - +
2051+ 3 | | 3 | |
2052+ 4 | | 4 | |
2053+ 5 | | 5 | |
2054+ 6 | | 6 | |
2055+ 7 \ - - - - / 7 + - - - - +
2056+
2057+ Result should be the intersection of 2 clips
2058+ 2 3 4 5 6 7 8 9
2059+ 2 + - - \
2060+ 3 | |
2061+ 4 | |
2062+ 5 | |
2063+ 6 | |
2064+ 7 + - - /
2065+ */
2066+ CGRect clipping = CGRectMake (4 , 2 , 4 , 6 );
2067+ for (int i = 0 ; i < 10 ; i++) {
2068+ for (int j = 0 ; j < 10 ; j++) {
2069+ CGPoint point = CGPointMake (i, j);
2070+ int alpha = [self alphaOfPoint: CGPointMake (i, j) onView: flutterView];
2071+ if (i == 7 && (j == 2 || j == 7 )) {
2072+ // Upper and lower right corners should be partially transparent.
2073+ XCTAssert (0 < alpha && alpha < 255 );
2074+ } else if (
2075+ // left
2076+ (i == 4 && j >= 2 && j <= 7 ) ||
2077+ // right
2078+ (i == 7 && j >= 2 && j <= 7 ) ||
2079+ // top
2080+ (j == 2 && i >= 4 && i <= 7 ) ||
2081+ // bottom
2082+ (j == 7 && i >= 4 && i <= 7 )) {
2083+ // Since we are falling back to software rendering for this case
2084+ // The edge pixels can be anti-aliased, so it may not be fully opaque.
2085+ XCTAssert (alpha > 127 );
2086+ } else if ((i == 3 && j >= 1 && j <= 8 ) || (i == 8 && j >= 1 && j <= 8 ) ||
2087+ (j == 1 && i >= 3 && i <= 8 ) || (j == 8 && i >= 3 && i <= 8 )) {
2088+ // Since we are falling back to software rendering for this case
2089+ // The edge pixels can be anti-aliased, so it may not be fully transparent.
2090+ XCTAssert (alpha < 127 );
2091+ } else if (CGRectContainsPoint (clipping, point)) {
2092+ // Other pixels inside clipping should be fully opaque.
2093+ XCTAssertEqual (alpha, 255 );
2094+ } else {
2095+ // Pixels outside clipping should be fully transparent.
2096+ XCTAssertEqual (alpha, 0 );
2097+ }
2098+ }
2099+ }
2100+ }
2101+
18902102- (void )testClipPath {
18912103 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
18922104 auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
@@ -1988,6 +2200,125 @@ - (void)testClipPath {
19882200 }
19892201}
19902202
2203+ - (void )testClipPath_multipleClips {
2204+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2205+ auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
2206+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
2207+ /* platform=*/ thread_task_runner,
2208+ /* raster=*/ thread_task_runner,
2209+ /* ui=*/ thread_task_runner,
2210+ /* io=*/ thread_task_runner);
2211+ auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
2212+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2213+ /* delegate=*/ mock_delegate,
2214+ /* rendering_api=*/ mock_delegate.settings_ .enable_impeller
2215+ ? flutter::IOSRenderingAPI::kMetal
2216+ : flutter::IOSRenderingAPI::kSoftware ,
2217+ /* platform_views_controller=*/ flutterPlatformViewsController,
2218+ /* task_runners=*/ runners,
2219+ /* worker_task_runner=*/ nil ,
2220+ /* is_gpu_disabled_jsync_switch=*/ std::make_shared<fml::SyncSwitch>());
2221+
2222+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2223+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc ] init ];
2224+ flutterPlatformViewsController->RegisterViewFactory (
2225+ factory, @" MockFlutterPlatformView" ,
2226+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2227+ FlutterResult result = ^(id result) {
2228+ };
2229+ flutterPlatformViewsController->OnMethodCall (
2230+ [FlutterMethodCall
2231+ methodCallWithMethodName: @" create"
2232+ arguments: @{@" id" : @2 , @" viewType" : @" MockFlutterPlatformView" }],
2233+ result);
2234+
2235+ XCTAssertNotNil (gMockPlatformView );
2236+
2237+ UIView* flutterView = [[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 10 , 10 )];
2238+ flutterPlatformViewsController->SetFlutterView (flutterView);
2239+ // Create embedded view params
2240+ flutter::MutatorsStack stack;
2241+ // Layer tree always pushes a screen scale factor to the stack
2242+ SkMatrix screenScaleMatrix =
2243+ SkMatrix::Scale ([UIScreen mainScreen ].scale , [UIScreen mainScreen ].scale );
2244+ stack.PushTransform (screenScaleMatrix);
2245+ // Push a clip path
2246+ SkPath path;
2247+ path.addRoundRect (SkRect::MakeXYWH (2 , 2 , 6 , 6 ), 1 , 1 );
2248+ stack.PushClipPath (path);
2249+ // Push a clip rect
2250+ SkRect rect = SkRect::MakeXYWH (4 , 2 , 6 , 6 );
2251+ stack.PushClipRect (rect);
2252+
2253+ auto embeddedViewParams =
2254+ std::make_unique<flutter::EmbeddedViewParams>(screenScaleMatrix, SkSize::Make (10 , 10 ), stack);
2255+
2256+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (2 , std::move (embeddedViewParams));
2257+ flutterPlatformViewsController->CompositeEmbeddedView (2 );
2258+
2259+ gMockPlatformView .backgroundColor = UIColor.redColor ;
2260+ XCTAssertTrue ([gMockPlatformView .superview.superview isKindOfClass: ChildClippingView.class ]);
2261+ ChildClippingView* childClippingView = (ChildClippingView*)gMockPlatformView .superview .superview ;
2262+ [flutterView addSubview: childClippingView];
2263+
2264+ [flutterView setNeedsLayout ];
2265+ [flutterView layoutIfNeeded ];
2266+
2267+ /*
2268+ clip 1 clip 2
2269+ 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9
2270+ 2 / - - - - \ 2 + - - - - +
2271+ 3 | | 3 | |
2272+ 4 | | 4 | |
2273+ 5 | | 5 | |
2274+ 6 | | 6 | |
2275+ 7 \ - - - - / 7 + - - - - +
2276+
2277+ Result should be the intersection of 2 clips
2278+ 2 3 4 5 6 7 8 9
2279+ 2 + - - \
2280+ 3 | |
2281+ 4 | |
2282+ 5 | |
2283+ 6 | |
2284+ 7 + - - /
2285+ */
2286+ CGRect clipping = CGRectMake (4 , 2 , 4 , 6 );
2287+ for (int i = 0 ; i < 10 ; i++) {
2288+ for (int j = 0 ; j < 10 ; j++) {
2289+ CGPoint point = CGPointMake (i, j);
2290+ int alpha = [self alphaOfPoint: CGPointMake (i, j) onView: flutterView];
2291+ if (i == 7 && (j == 2 || j == 7 )) {
2292+ // Upper and lower right corners should be partially transparent.
2293+ XCTAssert (0 < alpha && alpha < 255 );
2294+ } else if (
2295+ // left
2296+ (i == 4 && j >= 2 && j <= 7 ) ||
2297+ // right
2298+ (i == 7 && j >= 2 && j <= 7 ) ||
2299+ // top
2300+ (j == 2 && i >= 4 && i <= 7 ) ||
2301+ // bottom
2302+ (j == 7 && i >= 4 && i <= 7 )) {
2303+ // Since we are falling back to software rendering for this case
2304+ // The edge pixels can be anti-aliased, so it may not be fully opaque.
2305+ XCTAssert (alpha > 127 );
2306+ } else if ((i == 3 && j >= 1 && j <= 8 ) || (i == 8 && j >= 1 && j <= 8 ) ||
2307+ (j == 1 && i >= 3 && i <= 8 ) || (j == 8 && i >= 3 && i <= 8 )) {
2308+ // Since we are falling back to software rendering for this case
2309+ // The edge pixels can be anti-aliased, so it may not be fully transparent.
2310+ XCTAssert (alpha < 127 );
2311+ } else if (CGRectContainsPoint (clipping, point)) {
2312+ // Other pixels inside clipping should be fully opaque.
2313+ XCTAssertEqual (alpha, 255 );
2314+ } else {
2315+ // Pixels outside clipping should be fully transparent.
2316+ XCTAssertEqual (alpha, 0 );
2317+ }
2318+ }
2319+ }
2320+ }
2321+
19912322- (void )testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
19922323 flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
19932324 auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
0 commit comments