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,
+    );
+  });
+}