From 759553f1669d09e4ce859663aab2f34a69e66177 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Mon, 28 Aug 2023 17:23:27 +0800 Subject: [PATCH 1/3] fix: mask disappeared when having nested mask filter on Flutter web HTML --- lib/web_ui/lib/src/engine/canvas_pool.dart | 28 ++++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvas_pool.dart b/lib/web_ui/lib/src/engine/canvas_pool.dart index c5fe8378b5ba1..efd59166083f5 100644 --- a/lib/web_ui/lib/src/engine/canvas_pool.dart +++ b/lib/web_ui/lib/src/engine/canvas_pool.dart @@ -934,6 +934,7 @@ class ContextStateHandle { } ui.MaskFilter? _currentFilter; + String? _currentFilterCss; SurfacePaintData? _lastUsedPaint; /// Currently active shader bounds. @@ -1003,19 +1004,20 @@ class ContextStateHandle { } final ui.MaskFilter? maskFilter = paint.maskFilter; - if (!_renderMaskFilterForWebkit) { - if (_currentFilter != maskFilter) { - _currentFilter = maskFilter; - context.filter = maskFilterToCanvasFilter(maskFilter); - } - } else { - // WebKit does not support the `filter` property. Instead we apply a - // shadow to the shape of the same color as the paint and the same blur - // as the mask filter. - // - // Note that on WebKit the cached value of _currentFilter is not useful. - // Instead we destructure it into the shadow properties and cache those. - if (maskFilter != null) { + if (maskFilter != null) { + if (!_renderMaskFilterForWebkit) { + if (_currentFilter != maskFilter) { + _currentFilter = maskFilter; + _currentFilterCss = maskFilterToCanvasFilter(maskFilter); + } + context.filter = _currentFilterCss; + } else { + // WebKit does not support the `filter` property. Instead we apply a + // shadow to the shape of the same color as the paint and the same blur + // as the mask filter. + // + // Note that on WebKit the cached value of _currentFilter is not useful. + // Instead we destructure it into the shadow properties and cache those. context.save(); context.shadowBlur = convertSigmaToRadius(maskFilter.webOnlySigma); // Shadow color must be fully opaque. From d77a99b4e93b78b82bf3f6d1ca9b6cab39f0baa3 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 29 Aug 2023 09:25:37 +0800 Subject: [PATCH 2/3] add: golden test --- .../canvas_mask_filter_golden_test.dart | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart b/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart index 840bb0c23332d..0453fbe39e1dd 100644 --- a/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart +++ b/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart @@ -150,6 +150,32 @@ Future testMain() async { await canvasScreenshot(rc, 'mask_filter_transformed_$browser', region: screenRect); }); + + test('multiple MaskFilter.blur in $browser', () async { + const double screenWidth = 300.0; + const double screenHeight = 300.0; + const ui.Rect screenRect = + ui.Rect.fromLTWH(0, 0, screenWidth, screenHeight); + + ContextStateHandle.debugEmulateWebKitMaskFilter = isWebkit; + final RecordingCanvas rc = RecordingCanvas(screenRect); + + final SurfacePaint paint = SurfacePaint() + ..maskFilter = const ui.MaskFilter.blur(ui.BlurStyle.normal, 5); + rc.drawCircle(const ui.Offset(150, 150), 100, + paint..color = const ui.Color(0xFFC8C800)); + rc.drawCircle(const ui.Offset(150, 150), 50, + paint..color = const ui.Color(0xFFC800C8)); + rc.drawCircle( + const ui.Offset(150, 150), + 20, + paint + ..color = const ui.Color(0xFF00C8C8) + ..maskFilter = const ui.MaskFilter.blur(ui.BlurStyle.normal, 10)); + + await canvasScreenshot(rc, 'multiple_mask_filter_$browser', + region: screenRect); + }); } testMaskFilterBlur(); From 3528c73412d21e7ee1a51798019793e209af5273 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Tue, 29 Aug 2023 10:19:38 +0800 Subject: [PATCH 3/3] opt: add save/restore to canvas golden test --- .../html/compositing/canvas_mask_filter_golden_test.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart b/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart index 0453fbe39e1dd..e38aa59726892 100644 --- a/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart +++ b/lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart @@ -162,16 +162,22 @@ Future testMain() async { final SurfacePaint paint = SurfacePaint() ..maskFilter = const ui.MaskFilter.blur(ui.BlurStyle.normal, 5); + rc.save(); rc.drawCircle(const ui.Offset(150, 150), 100, paint..color = const ui.Color(0xFFC8C800)); + rc.restore(); + rc.save(); rc.drawCircle(const ui.Offset(150, 150), 50, paint..color = const ui.Color(0xFFC800C8)); + rc.restore(); + rc.save(); rc.drawCircle( const ui.Offset(150, 150), 20, paint ..color = const ui.Color(0xFF00C8C8) ..maskFilter = const ui.MaskFilter.blur(ui.BlurStyle.normal, 10)); + rc.restore(); await canvasScreenshot(rc, 'multiple_mask_filter_$browser', region: screenRect);