No shrinking for BackdropFilter's cull rect (#28174)
* No shrinking for BackdropFilter's cull rect
This will be a breaking change. Our old behavior may generate confusions
for a sample app like our added golden test: Skia will shrink the cull
rect (and thus the filtered area) to the text. The new behavior will
fill the BackdropFilter to its parent/ancestor clip. This is more
in align with our clip behaviors (no clip by default).
If this breaks your app, wrap the BackdropFilter with a ClipRect.
[wip] The golden images are not uploaded yet. I'll wait for the initial
round of review to approve the golden test before uploading them.
* Statically define the callback
* Add TODO to remind the hacking code removal
* Nit fix
* Update goldens
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index eb69561..76c84d9 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -1033,11 +1033,20 @@
@override
bool get alwaysNeedsCompositing => child != null;
+ // TODO(liyuqian): remove this after updating the engine BackdropFilterLayer.
+ void _addTrasnparentPaint(PaintingContext context, Offset offset) {
+ // Draw a fully transparent paint to make sure that the cull rect won't be
+ // shrunk by Skia.
+ final Paint transparentPaint = Paint()..color = const Color(0x00000000);
+ context.canvas.drawPaint(transparentPaint);
+ super.paint(context, offset);
+ }
+
@override
void paint(PaintingContext context, Offset offset) {
if (child != null) {
assert(needsCompositing);
- context.pushLayer(BackdropFilterLayer(filter: _filter), super.paint, offset);
+ context.pushLayer(BackdropFilterLayer(filter: _filter), _addTrasnparentPaint, offset);
}
}
}
diff --git a/packages/flutter/test/widgets/backdrop_filter_test.dart b/packages/flutter/test/widgets/backdrop_filter_test.dart
new file mode 100644
index 0000000..80294b3
--- /dev/null
+++ b/packages/flutter/test/widgets/backdrop_filter_test.dart
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:ui';
+
+import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:flutter/material.dart';
+
+void main() {
+ testWidgets('BackdropFilter\'s cull rect does not shrink', (WidgetTester tester) async {
+ await tester.pumpWidget(
+ MaterialApp(
+ home: Scaffold(
+ body: Stack(
+ fit: StackFit.expand,
+ children: <Widget>[
+ Text('0 0 ' * 10000),
+ Center(
+ // ClipRect needed for filtering the 200x200 area instead of the
+ // whole screen.
+ child: ClipRect(
+ child: BackdropFilter(
+ filter: ImageFilter.blur(
+ sigmaX: 5.0,
+ sigmaY: 5.0,
+ ),
+ child: Container(
+ alignment: Alignment.center,
+ width: 200.0,
+ height: 200.0,
+ child: const Text('Hello World'),
+ ),
+ ),
+ ),
+ ),
+ ],
+ )
+ )
+ )
+ );
+ await expectLater(
+ find.byType(RepaintBoundary).first,
+ matchesGoldenFile('backdrop_filter_test.cull_rect.1.png'),
+ skip: !Platform.isLinux,
+ );
+ });
+}