Skip to content

Commit

Permalink
Fix backdrop filter with platform views as children
Browse files Browse the repository at this point in the history
  • Loading branch information
harryterkelsen committed Mar 15, 2024
1 parent 76f33eb commit 738902c
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 4 deletions.
11 changes: 8 additions & 3 deletions lib/web_ui/lib/src/engine/canvaskit/layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,16 @@ class BackdropFilterEngineLayer extends ContainerLayer
@override
void paint(PaintContext paintContext) {
final CkPaint paint = CkPaint()..blendMode = _blendMode;
paintContext.internalNodesCanvas
.saveLayerWithFilter(paintBounds, _filter, paint);

// Only apply the backdrop filter to the current canvas. If we apply the
// backdrop filter to every canvas (i.e. by applying it to the
// [internalNodesCanvas]), then later when we compose the canvases into a
// single canvas, the backdrop filter will be applied multiple times.
final CkCanvas currentCanvas = paintContext.leafNodesCanvas!;
currentCanvas.saveLayerWithFilter(paintBounds, _filter, paint);
paint.dispose();
paintChildren(paintContext);
paintContext.internalNodesCanvas.restore();
currentCanvas.restore();
}

// TODO(dnfield): dispose of the _filter
Expand Down
82 changes: 81 additions & 1 deletion lib/web_ui/test/canvaskit/backdrop_filter_golden_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import 'common.dart';

Expand All @@ -18,7 +19,15 @@ const ui.Rect region = ui.Rect.fromLTRB(0, 0, 500, 500);
void testMain() {
group('BackdropFilter', () {
setUpCanvasKitTest(withImplicitView: true);
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1.0);

setUp(() {
EngineFlutterDisplay.instance.debugOverrideDevicePixelRatio(1);
});

tearDown(() {
PlatformViewManager.instance.debugClear();
CanvasKitRenderer.instance.debugClear();
});

test('blur renders to the edges', () async {
// Make a checkerboard picture so we can see the blur.
Expand Down Expand Up @@ -76,6 +85,77 @@ void testMain() {
builder.build(),
region: region);
});

test('works with an invisible platform view inside', () async {
ui_web.platformViewRegistry.registerViewFactory(
'test-platform-view',
(int viewId) => createDomHTMLDivElement()..id = 'view-0',
isVisible: false,
);
await createPlatformView(0, 'test-platform-view');

// Make a checkerboard picture so we can see the blur.
final CkPictureRecorder recorder = CkPictureRecorder();
final CkCanvas canvas = recorder.beginRecording(region);
canvas.drawColor(const ui.Color(0xffffffff), ui.BlendMode.srcOver);
final double sideLength = region.width / 20;
final int rows = (region.height / sideLength).ceil();

for (int row = 0; row < rows; row++) {
for (int column = 0; column < 10; column++) {
final ui.Rect rect = ui.Rect.fromLTWH(
row.isEven
? (column * 2) * sideLength
: (column * 2 + 1) * sideLength,
row * sideLength,
sideLength,
sideLength,
);
canvas.drawRect(rect, CkPaint()..color = const ui.Color(0xffff0000));
}
}
final CkPicture checkerboard = recorder.endRecording();

final LayerSceneBuilder builder = LayerSceneBuilder();
builder.pushOffset(0, 0);
builder.addPicture(ui.Offset.zero, checkerboard);
builder.pushBackdropFilter(ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10));

// Draw a green rectangle, then an invisible platform view, then a blue
// rectangle. Both rectangles should not be blurred.
final CkPictureRecorder greenRectRecorder = CkPictureRecorder();
final CkCanvas greenRectCanvas = greenRectRecorder.beginRecording(region);
final CkPaint greenPaint = CkPaint()..color = const ui.Color(0xff00ff00);
greenRectCanvas.drawRect(
ui.Rect.fromCenter(
center: ui.Offset(region.width / 3, region.height / 2),
width: region.width / 6,
height: region.height / 6),
greenPaint);
final CkPicture greenRectPicture = greenRectRecorder.endRecording();

final CkPictureRecorder blueRectRecorder = CkPictureRecorder();
final CkCanvas blueRectCanvas = blueRectRecorder.beginRecording(region);
final CkPaint bluePaint = CkPaint()..color = const ui.Color(0xff0000ff);
blueRectCanvas.drawRect(
ui.Rect.fromCenter(
center: ui.Offset(2 * region.width / 3, region.height / 2),
width: region.width / 6,
height: region.height / 6),
bluePaint);
final CkPicture blueRectPicture = blueRectRecorder.endRecording();

builder.addPicture(ui.Offset.zero, greenRectPicture);
builder.addPlatformView(0, width: 10, height: 10);
builder.addPicture(ui.Offset.zero, blueRectPicture);

// Pop the backdrop filter layer.
builder.pop();

await matchSceneGolden(
'canvaskit_backdropfilter_with_platformview.png', builder.build(),
region: region);
});
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/71520
}, skip: isSafari || isFirefox);
}

0 comments on commit 738902c

Please sign in to comment.