diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 15653800d6bb..f39436bc2007 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -2430,7 +2430,7 @@ class RenderTransform extends RenderProxyBox { return; } _origin = value; - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } @@ -2452,7 +2452,7 @@ class RenderTransform extends RenderProxyBox { return; } _alignment = value; - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } @@ -2467,13 +2467,10 @@ class RenderTransform extends RenderProxyBox { return; } _textDirection = value; - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } - @override - bool get isRepaintBoundary => alwaysNeedsCompositing; - @override bool get alwaysNeedsCompositing => child != null && _filterQuality != null; @@ -2498,7 +2495,7 @@ class RenderTransform extends RenderProxyBox { return; } _transform = Matrix4.copy(value); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } @@ -2516,48 +2513,48 @@ class RenderTransform extends RenderProxyBox { if (didNeedCompositing != alwaysNeedsCompositing) { markNeedsCompositingBitsUpdate(); } - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); } /// Sets the transform to the identity matrix. void setIdentity() { _transform!.setIdentity(); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } /// Concatenates a rotation about the x axis into the transform. void rotateX(double radians) { _transform!.rotateX(radians); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } /// Concatenates a rotation about the y axis into the transform. void rotateY(double radians) { _transform!.rotateY(radians); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } /// Concatenates a rotation about the z axis into the transform. void rotateZ(double radians) { _transform!.rotateZ(radians); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } /// Concatenates a translation by (x, y, z) into the transform. void translate(double x, [ double y = 0.0, double z = 0.0 ]) { _transform!.translate(x, y, z); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } /// Concatenates a scale into the transform. void scale(double x, [ double? y, double? z ]) { _transform!.scale(x, y, z); - markNeedsCompositedLayerUpdate(); + markNeedsPaint(); markNeedsSemanticsUpdate(); } @@ -2606,46 +2603,51 @@ class RenderTransform extends RenderProxyBox { ); } - @override - OffsetLayer updateCompositedLayer({required covariant ImageFilterLayer? oldLayer}) { - final ImageFilterLayer layer = oldLayer ?? ImageFilterLayer(); - layer.imageFilter = ui.ImageFilter.matrix( - _effectiveTransform!.storage, - filterQuality: filterQuality! - ); - return layer; - } - @override void paint(PaintingContext context, Offset offset) { - if (child == null) { - return; - } - if (isRepaintBoundary) { - return super.paint(context, offset); - } - - final Matrix4 transform = _effectiveTransform!; - final Offset? childOffset = MatrixUtils.getAsTranslation(transform); - if (childOffset != null) { - super.paint(context, offset + childOffset); - layer = null; - return; - } - // if the matrix is singular the children would be compressed to a line or - // single point, instead short-circuit and paint nothing. - final double det = transform.determinant(); - if (det == 0 || !det.isFinite) { - layer = null; - return; + if (child != null) { + final Matrix4 transform = _effectiveTransform!; + if (filterQuality == null) { + final Offset? childOffset = MatrixUtils.getAsTranslation(transform); + if (childOffset == null) { + // if the matrix is singular the children would be compressed to a line or + // single point, instead short-circuit and paint nothing. + final double det = transform.determinant(); + if (det == 0 || !det.isFinite) { + layer = null; + return; + } + layer = context.pushTransform( + needsCompositing, + offset, + transform, + super.paint, + oldLayer: layer is TransformLayer ? layer as TransformLayer? : null, + ); + } else { + super.paint(context, offset + childOffset); + layer = null; + } + } else { + final Matrix4 effectiveTransform = Matrix4.translationValues(offset.dx, offset.dy, 0.0) + ..multiply(transform)..translate(-offset.dx, -offset.dy); + final ui.ImageFilter filter = ui.ImageFilter.matrix( + effectiveTransform.storage, + filterQuality: filterQuality!, + ); + if (layer is ImageFilterLayer) { + final ImageFilterLayer filterLayer = layer! as ImageFilterLayer; + filterLayer.imageFilter = filter; + } else { + layer = ImageFilterLayer(imageFilter: filter); + } + context.pushLayer(layer!, super.paint, offset); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); + } } - layer = context.pushTransform( - needsCompositing, - offset, - transform, - super.paint, - oldLayer: layer is TransformLayer ? layer as TransformLayer? : null, - ); } @override diff --git a/packages/flutter/test/widgets/animated_image_filtered_repaint_test.dart b/packages/flutter/test/widgets/animated_image_filtered_repaint_test.dart index d3ed5601f499..afeecc8ad716 100644 --- a/packages/flutter/test/widgets/animated_image_filtered_repaint_test.dart +++ b/packages/flutter/test/widgets/animated_image_filtered_repaint_test.dart @@ -35,35 +35,6 @@ void main() { expect(RenderTestObject.paintCount, 1); }); - - testWidgets('Transform with FilterQuality avoids repainting child as it animates', (WidgetTester tester) async { - RenderTestObject.paintCount = 0; - await tester.pumpWidget( - Container( - color: Colors.red, - child: Transform.translate( - offset: const Offset(5.0, 10.0), - filterQuality: FilterQuality.low, - child: const TestWidget(), - ), - ) - ); - - expect(RenderTestObject.paintCount, 1); - - await tester.pumpWidget( - Container( - color: Colors.red, - child: Transform.translate( - offset: const Offset(25.0, 0.0), - filterQuality: FilterQuality.low, - child: const TestWidget(), - ), - ) - ); - - expect(RenderTestObject.paintCount, 1); - }); } class TestWidget extends SingleChildRenderObjectWidget { diff --git a/packages/flutter/test/widgets/transform_test.dart b/packages/flutter/test/widgets/transform_test.dart index 98758f8014c0..e677361c0b17 100644 --- a/packages/flutter/test/widgets/transform_test.dart +++ b/packages/flutter/test/widgets/transform_test.dart @@ -616,7 +616,7 @@ void main() { moreOrLessEquals(0.7071067811865476), moreOrLessEquals(0.7071067811865475), 0.0, 0.0, moreOrLessEquals(-0.7071067811865475), moreOrLessEquals(0.7071067811865476), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, - moreOrLessEquals(50), moreOrLessEquals(-20.710678118654755), 0.0, 1.0, + moreOrLessEquals(329.28932188134524), moreOrLessEquals(-194.97474683058329), 0.0, 1.0, ]); });