Unverified Commit e065c7fe authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[framework] make ImageFiltered a repaint boundary (#116385)

* ++

* ++

* ++
parent 5c975430
...@@ -79,7 +79,11 @@ class _ImageFilterRenderObject extends RenderProxyBox { ...@@ -79,7 +79,11 @@ class _ImageFilterRenderObject extends RenderProxyBox {
if (enabled == value) { if (enabled == value) {
return; return;
} }
final bool wasRepaintBoundary = isRepaintBoundary;
_enabled = value; _enabled = value;
if (isRepaintBoundary != wasRepaintBoundary) {
markNeedsCompositingBitsUpdate();
}
markNeedsPaint(); markNeedsPaint();
} }
...@@ -89,32 +93,20 @@ class _ImageFilterRenderObject extends RenderProxyBox { ...@@ -89,32 +93,20 @@ class _ImageFilterRenderObject extends RenderProxyBox {
assert(value != null); assert(value != null);
if (value != _imageFilter) { if (value != _imageFilter) {
_imageFilter = value; _imageFilter = value;
markNeedsPaint(); markNeedsCompositedLayerUpdate();
} }
} }
@override @override
bool get alwaysNeedsCompositing => child != null && enabled; bool get alwaysNeedsCompositing => child != null && enabled;
@override @override
void paint(PaintingContext context, Offset offset) { bool get isRepaintBoundary => alwaysNeedsCompositing;
assert(imageFilter != null);
if (!enabled) {
layer = null;
return super.paint(context, offset);
}
if (layer == null) { @override
layer = ImageFilterLayer(imageFilter: imageFilter, offset: offset); OffsetLayer updateCompositedLayer({required covariant ImageFilterLayer? oldLayer}) {
} else { final ImageFilterLayer layer = oldLayer ?? ImageFilterLayer();
final ImageFilterLayer filterLayer = layer! as ImageFilterLayer; layer.imageFilter = imageFilter;
filterLayer.imageFilter = imageFilter; return layer;
filterLayer.offset = offset;
}
context.pushLayer(layer!, super.paint, Offset.zero);
assert(() {
layer!.debugCreator = debugCreator;
return true;
}());
} }
} }
// Copyright 2014 The Flutter 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:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('ImageFiltered avoids repainting child as it animates', (WidgetTester tester) async {
RenderTestObject.paintCount = 0;
await tester.pumpWidget(
Container(
color: Colors.red,
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: const TestWidget(),
),
)
);
expect(RenderTestObject.paintCount, 1);
await tester.pumpWidget(
Container(
color: Colors.red,
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: const TestWidget(),
),
)
);
expect(RenderTestObject.paintCount, 1);
});
}
class TestWidget extends SingleChildRenderObjectWidget {
const TestWidget({super.key, super.child});
@override
RenderObject createRenderObject(BuildContext context) {
return RenderTestObject();
}
}
class RenderTestObject extends RenderProxyBox {
static int paintCount = 0;
@override
void paint(PaintingContext context, Offset offset) {
paintCount += 1;
super.paint(context, offset);
}
}
...@@ -31,8 +31,10 @@ void main() { ...@@ -31,8 +31,10 @@ void main() {
}); });
testWidgets('Image filter - blur with offset', (WidgetTester tester) async { testWidgets('Image filter - blur with offset', (WidgetTester tester) async {
final Key key = GlobalKey();
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
key: key,
child: Transform.translate( child: Transform.translate(
offset: const Offset(50, 50), offset: const Offset(50, 50),
child: ImageFiltered( child: ImageFiltered(
...@@ -43,7 +45,7 @@ void main() { ...@@ -43,7 +45,7 @@ void main() {
), ),
); );
await expectLater( await expectLater(
find.byType(ImageFiltered), find.byKey(key),
matchesGoldenFile('image_filter_blur_offset.png'), matchesGoldenFile('image_filter_blur_offset.png'),
); );
}); });
...@@ -119,8 +121,10 @@ void main() { ...@@ -119,8 +121,10 @@ void main() {
testWidgets('Image filter - matrix with offset', (WidgetTester tester) async { testWidgets('Image filter - matrix with offset', (WidgetTester tester) async {
final Matrix4 matrix = Matrix4.rotationZ(pi / 18); final Matrix4 matrix = Matrix4.rotationZ(pi / 18);
final ImageFilter matrixFilter = ImageFilter.matrix(matrix.storage); final ImageFilter matrixFilter = ImageFilter.matrix(matrix.storage);
final Key key = GlobalKey();
await tester.pumpWidget( await tester.pumpWidget(
RepaintBoundary( RepaintBoundary(
key: key,
child: Transform.translate( child: Transform.translate(
offset: const Offset(50, 50), offset: const Offset(50, 50),
child: ImageFiltered( child: ImageFiltered(
...@@ -147,7 +151,7 @@ void main() { ...@@ -147,7 +151,7 @@ void main() {
), ),
); );
await expectLater( await expectLater(
find.byType(ImageFiltered), find.byKey(key),
matchesGoldenFile('image_filter_matrix_offset.png'), matchesGoldenFile('image_filter_matrix_offset.png'),
); );
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment