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

Commit c90aa9a

Browse files
authored
fix: mask disappeared when having nested mask filter on Flutter web HTML (#45166)
Hi from [Dora team](https://www.dora.run/), which powers web developers to build their 3d websites in just a few seconds. This PR fixes: flutter/flutter#133443, related: flutter/flutter#58546 The original codes attempts to cache the css string but it causes bugs when encountering nested the same mask filter blur. We should also set `filter` properties when currentFilter == incoming mask filter using the cached css string, not just ignore it. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 989ae4e commit c90aa9a

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

lib/web_ui/lib/src/engine/canvas_pool.dart

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ class ContextStateHandle {
934934
}
935935

936936
ui.MaskFilter? _currentFilter;
937+
String? _currentFilterCss;
937938
SurfacePaintData? _lastUsedPaint;
938939

939940
/// Currently active shader bounds.
@@ -1003,19 +1004,20 @@ class ContextStateHandle {
10031004
}
10041005

10051006
final ui.MaskFilter? maskFilter = paint.maskFilter;
1006-
if (!_renderMaskFilterForWebkit) {
1007-
if (_currentFilter != maskFilter) {
1008-
_currentFilter = maskFilter;
1009-
context.filter = maskFilterToCanvasFilter(maskFilter);
1010-
}
1011-
} else {
1012-
// WebKit does not support the `filter` property. Instead we apply a
1013-
// shadow to the shape of the same color as the paint and the same blur
1014-
// as the mask filter.
1015-
//
1016-
// Note that on WebKit the cached value of _currentFilter is not useful.
1017-
// Instead we destructure it into the shadow properties and cache those.
1018-
if (maskFilter != null) {
1007+
if (maskFilter != null) {
1008+
if (!_renderMaskFilterForWebkit) {
1009+
if (_currentFilter != maskFilter) {
1010+
_currentFilter = maskFilter;
1011+
_currentFilterCss = maskFilterToCanvasFilter(maskFilter);
1012+
}
1013+
context.filter = _currentFilterCss;
1014+
} else {
1015+
// WebKit does not support the `filter` property. Instead we apply a
1016+
// shadow to the shape of the same color as the paint and the same blur
1017+
// as the mask filter.
1018+
//
1019+
// Note that on WebKit the cached value of _currentFilter is not useful.
1020+
// Instead we destructure it into the shadow properties and cache those.
10191021
context.save();
10201022
context.shadowBlur = convertSigmaToRadius(maskFilter.webOnlySigma);
10211023
// Shadow color must be fully opaque.

lib/web_ui/test/html/compositing/canvas_mask_filter_golden_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,38 @@ Future<void> testMain() async {
150150
await canvasScreenshot(rc, 'mask_filter_transformed_$browser',
151151
region: screenRect);
152152
});
153+
154+
test('multiple MaskFilter.blur in $browser', () async {
155+
const double screenWidth = 300.0;
156+
const double screenHeight = 300.0;
157+
const ui.Rect screenRect =
158+
ui.Rect.fromLTWH(0, 0, screenWidth, screenHeight);
159+
160+
ContextStateHandle.debugEmulateWebKitMaskFilter = isWebkit;
161+
final RecordingCanvas rc = RecordingCanvas(screenRect);
162+
163+
final SurfacePaint paint = SurfacePaint()
164+
..maskFilter = const ui.MaskFilter.blur(ui.BlurStyle.normal, 5);
165+
rc.save();
166+
rc.drawCircle(const ui.Offset(150, 150), 100,
167+
paint..color = const ui.Color(0xFFC8C800));
168+
rc.restore();
169+
rc.save();
170+
rc.drawCircle(const ui.Offset(150, 150), 50,
171+
paint..color = const ui.Color(0xFFC800C8));
172+
rc.restore();
173+
rc.save();
174+
rc.drawCircle(
175+
const ui.Offset(150, 150),
176+
20,
177+
paint
178+
..color = const ui.Color(0xFF00C8C8)
179+
..maskFilter = const ui.MaskFilter.blur(ui.BlurStyle.normal, 10));
180+
rc.restore();
181+
182+
await canvasScreenshot(rc, 'multiple_mask_filter_$browser',
183+
region: screenRect);
184+
});
153185
}
154186

155187
testMaskFilterBlur();

0 commit comments

Comments
 (0)