diff --git a/bin/cache/engine.version b/bin/cache/engine.version index 317c4f0b6e..a28ea2e3c2 100644 --- a/bin/cache/engine.version +++ b/bin/cache/engine.version @@ -1 +1 @@ -b8151a8d9bb2fd2c1d67e8007a53eba5489f3d0d +13f67343d008c9673f528ec2451c7d5a0528605c diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart index 246a63794c..27ff81e83c 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui show Picture, SceneBuilder; +import 'dart:ui' as ui show ImageFilter, Picture, SceneBuilder; import 'dart:ui' show Offset; import 'package:flutter/painting.dart'; @@ -448,3 +448,18 @@ class ShaderMaskLayer extends ContainerLayer { description.add('transferMode: $transferMode'); } } + +/// A composited layer that applies a filter to the existing contents of the scene. +class BackdropFilterLayer extends ContainerLayer { + BackdropFilterLayer({ this.filter }); + + /// The filter to apply to the existing contents of the scene. + ui.ImageFilter filter; + + @override + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { + builder.pushBackdropFilter(filter); + addChildrenToScene(builder, layerOffset); + builder.pop(); + } +} diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 90b4d0f019..77dc0fec86 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:developer'; -import 'dart:ui' as ui show PictureRecorder; +import 'dart:ui' as ui show ImageFilter, PictureRecorder; import 'package:flutter/gestures.dart'; import 'package:flutter/painting.dart'; @@ -333,6 +333,19 @@ class PaintingContext { painter(childContext, offset); childContext._stopRecordingIfNeeded(); } + + /// Push a backdrop filter. + /// + /// This function applies a filter to the existing painted content and then + /// synchronously calls the painter to paint on top of the filtered backdrop. + void pushBackdropFilter(Offset offset, ui.ImageFilter filter, PaintingContextCallback painter) { + _stopRecordingIfNeeded(); + BackdropFilterLayer backdropFilterLayer = new BackdropFilterLayer(filter: filter); + _appendLayer(backdropFilterLayer); + PaintingContext childContext = new PaintingContext._(backdropFilterLayer, _paintBounds); + painter(childContext, offset); + childContext._stopRecordingIfNeeded(); + } } /// An encapsulation of a renderer and a paint() method. diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 104e4a1ff3..efb999868c 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:ui' as ui show ImageFilter; + import 'package:flutter/gestures.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -673,6 +675,34 @@ class RenderShaderMask extends RenderProxyBox { } } +class RenderBackdropFilter extends RenderProxyBox { + RenderBackdropFilter({ RenderBox child, ui.ImageFilter filter }) + : _filter = filter, super(child) { + assert(filter != null); + } + + ui.ImageFilter get filter => _filter; + ui.ImageFilter _filter; + void set filter (ui.ImageFilter newFilter) { + assert(newFilter != null); + if (_filter == newFilter) + return; + _filter = newFilter; + markNeedsPaint(); + } + + @override + bool get alwaysNeedsCompositing => child != null; + + @override + void paint(PaintingContext context, Offset offset) { + if (child != null) { + assert(needsCompositing); + context.pushBackdropFilter(offset, _filter, super.paint); + } + } +} + /// A class that provides custom clips. abstract class CustomClipper { /// Returns a description of the clip given that the render object being diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 88f078d85a..0c8cc67ebf 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui show Image; +import 'dart:ui' as ui show Image, ImageFilter; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; @@ -122,6 +122,28 @@ class ShaderMask extends SingleChildRenderObjectWidget { } } +class BackdropFilter extends SingleChildRenderObjectWidget { + BackdropFilter({ + Key key, + this.filter, + Widget child + }) : super(key: key, child: child) { + assert(filter != null); + } + + final ui.ImageFilter filter; + + @override + RenderBackdropFilter createRenderObject(BuildContext context) { + return new RenderBackdropFilter(filter: filter); + } + + @override + void updateRenderObject(BuildContext context, RenderBackdropFilter renderObject) { + renderObject.filter = filter; + } +} + /// Paints a [Decoration] either before or after its child paints. /// Container insets its child by the widths of the borders, this Widget does not. ///