Control raster cache flags in CustomPaint widgets (#11398)
This commit is contained in:
parent
9f510ebdc9
commit
838bd63182
@ -2064,6 +2064,8 @@ class RenderCustomPaint extends RenderProxyBox {
|
||||
CustomPainter painter,
|
||||
CustomPainter foregroundPainter,
|
||||
Size preferredSize: Size.zero,
|
||||
this.isComplex: false,
|
||||
this.willChange: false,
|
||||
RenderBox child,
|
||||
}) : assert(preferredSize != null),
|
||||
_painter = painter,
|
||||
@ -2153,6 +2155,19 @@ class RenderCustomPaint extends RenderProxyBox {
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
/// Whether to hint that this layer's painting should be cached.
|
||||
///
|
||||
/// The compositor contains a raster cache that holds bitmaps of layers in
|
||||
/// order to avoid the cost of repeatedly rendering those layers on each
|
||||
/// frame. If this flag is not set, then the compositor will apply its own
|
||||
/// heuristics to decide whether the this layer is complex enough to benefit
|
||||
/// from caching.
|
||||
bool isComplex;
|
||||
|
||||
/// Whether the raster cache should be told that this painting is likely
|
||||
/// to change in the next frame.
|
||||
bool willChange;
|
||||
|
||||
@override
|
||||
void attach(PipelineOwner owner) {
|
||||
super.attach(owner);
|
||||
@ -2226,11 +2241,22 @@ class RenderCustomPaint extends RenderProxyBox {
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (_painter != null)
|
||||
if (_painter != null) {
|
||||
_paintWithPainter(context.canvas, offset, _painter);
|
||||
_setRasterCacheHints(context);
|
||||
}
|
||||
super.paint(context, offset);
|
||||
if (_foregroundPainter != null)
|
||||
if (_foregroundPainter != null) {
|
||||
_paintWithPainter(context.canvas, offset, _foregroundPainter);
|
||||
_setRasterCacheHints(context);
|
||||
}
|
||||
}
|
||||
|
||||
void _setRasterCacheHints(PaintingContext context) {
|
||||
if (isComplex)
|
||||
context.setIsComplexHint();
|
||||
if (willChange)
|
||||
context.setWillChangeHint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,10 @@ class BackdropFilter extends SingleChildRenderObjectWidget {
|
||||
///
|
||||
/// Custom painters normally size themselves to their child. If they do not have
|
||||
/// a child, they attempt to size themselves to the [size], which defaults to
|
||||
/// [Size.zero].
|
||||
/// [Size.zero]. [size] must not be null.
|
||||
///
|
||||
/// [isComplex] and [willChange] are hints to the compositor's raster cache
|
||||
/// and must not be null.
|
||||
///
|
||||
/// ## Sample code
|
||||
///
|
||||
@ -286,8 +289,17 @@ class BackdropFilter extends SingleChildRenderObjectWidget {
|
||||
/// * [Canvas], the class that a custom painter uses to paint.
|
||||
class CustomPaint extends SingleChildRenderObjectWidget {
|
||||
/// Creates a widget that delegates its painting.
|
||||
const CustomPaint({ Key key, this.painter, this.foregroundPainter, this.size: Size.zero, Widget child })
|
||||
: assert(size != null),
|
||||
const CustomPaint({
|
||||
Key key,
|
||||
this.painter,
|
||||
this.foregroundPainter,
|
||||
this.size: Size.zero,
|
||||
this.isComplex: false,
|
||||
this.willChange: false,
|
||||
Widget child
|
||||
}) : assert(size != null),
|
||||
assert(isComplex != null),
|
||||
assert(willChange != null),
|
||||
super(key: key, child: child);
|
||||
|
||||
/// The painter that paints before the children.
|
||||
@ -305,12 +317,27 @@ class CustomPaint extends SingleChildRenderObjectWidget {
|
||||
/// instead.
|
||||
final Size size;
|
||||
|
||||
/// Whether the painting is complex enough to benefit from caching.
|
||||
///
|
||||
/// The compositor contains a raster cache that holds bitmaps of layers in
|
||||
/// order to avoid the cost of repeatedly rendering those layers on each
|
||||
/// frame. If this flag is not set, then the compositor will apply its own
|
||||
/// heuristics to decide whether the this layer is complex enough to benefit
|
||||
/// from caching.
|
||||
final bool isComplex;
|
||||
|
||||
/// Whether the raster cache should be told that this painting is likely
|
||||
/// to change in the next frame.
|
||||
final bool willChange;
|
||||
|
||||
@override
|
||||
RenderCustomPaint createRenderObject(BuildContext context) {
|
||||
return new RenderCustomPaint(
|
||||
painter: painter,
|
||||
foregroundPainter: foregroundPainter,
|
||||
preferredSize: size,
|
||||
isComplex: isComplex,
|
||||
willChange: willChange,
|
||||
);
|
||||
}
|
||||
|
||||
@ -319,7 +346,9 @@ class CustomPaint extends SingleChildRenderObjectWidget {
|
||||
renderObject
|
||||
..painter = painter
|
||||
..foregroundPainter = foregroundPainter
|
||||
..preferredSize = size;
|
||||
..preferredSize = size
|
||||
..isComplex = isComplex
|
||||
..willChange = willChange;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class TestCustomPainter extends CustomPainter {
|
||||
@ -77,4 +78,27 @@ void main() {
|
||||
expect(target.currentContext.size, Size.zero);
|
||||
|
||||
});
|
||||
|
||||
testWidgets('Raster cache hints', (WidgetTester tester) async {
|
||||
final GlobalKey target = new GlobalKey();
|
||||
|
||||
final List<String> log = <String>[];
|
||||
await tester.pumpWidget(new CustomPaint(
|
||||
key: target,
|
||||
isComplex: true,
|
||||
painter: new TestCustomPainter(log: log),
|
||||
));
|
||||
RenderCustomPaint renderCustom = target.currentContext.findRenderObject();
|
||||
expect(renderCustom.isComplex, true);
|
||||
expect(renderCustom.willChange, false);
|
||||
|
||||
await tester.pumpWidget(new CustomPaint(
|
||||
key: target,
|
||||
willChange: true,
|
||||
foregroundPainter: new TestCustomPainter(log: log),
|
||||
));
|
||||
renderCustom = target.currentContext.findRenderObject();
|
||||
expect(renderCustom.isComplex, false);
|
||||
expect(renderCustom.willChange, true);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user