Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 2ee59a5

Browse files
committed
skip painting clipped out pictures
1 parent 8e91235 commit 2ee59a5

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

lib/web_ui/lib/src/engine/surface/picture.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,11 @@ class PersistedStandardPicture extends PersistedPicture {
180180
return 1.0;
181181
} else {
182182
final BitmapCanvas oldCanvas = existingSurface._canvas;
183-
if (!oldCanvas.doesFitBounds(_exactLocalCullRect)) {
183+
if (oldCanvas == null) {
184+
// We did not allocate a canvas last time. This can happen when the
185+
// picture is completely clipped out of the view.
186+
return 1.0;
187+
} else if (!oldCanvas.doesFitBounds(_exactLocalCullRect)) {
184188
// The canvas needs to be resized before painting.
185189
return 1.0;
186190
} else {
@@ -547,7 +551,10 @@ abstract class PersistedPicture extends PersistedLeafSurface {
547551

548552
void _applyPaint(PersistedPicture oldSurface) {
549553
final EngineCanvas oldCanvas = oldSurface?._canvas;
550-
if (!picture.recordingCanvas.didDraw) {
554+
if (!picture.recordingCanvas.didDraw || _optimalLocalCullRect.isEmpty) {
555+
// The picture is empty, or it has been completely clipped out. Skip
556+
// painting. This removes all the setup work and scaffolding objects
557+
// that won't be useful for anything anyway.
551558
_recycleCanvas(oldCanvas);
552559
domRenderer.clearDom(rootElement);
553560
return;
@@ -642,7 +649,7 @@ abstract class PersistedPicture extends PersistedLeafSurface {
642649
super.debugValidate(validationErrors);
643650

644651
if (picture.recordingCanvas.didDraw) {
645-
if (debugCanvas == null) {
652+
if (!_optimalLocalCullRect.isEmpty && debugCanvas == null) {
646653
validationErrors
647654
.add('$runtimeType has non-trivial picture but it has null canvas');
648655
}

lib/web_ui/test/compositing_test.dart renamed to lib/web_ui/test/engine/surface/scene_builder_test.dart

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import 'package:ui/ui.dart';
1010

1111
import 'package:test/test.dart';
1212

13-
import 'matchers.dart';
13+
import '../../matchers.dart';
1414

1515
void main() {
1616
group('SceneBuilder', () {
@@ -210,6 +210,31 @@ void main() {
210210
});
211211
});
212212

213+
test('skips painting picture when picture fully clipped out', () async {
214+
final Picture picture = _drawPicture();
215+
216+
// Picture not clipped out, so we should see a `<flt-canvas>`
217+
{
218+
final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
219+
builder.pushOffset(0, 0);
220+
builder.addPicture(Offset.zero, picture);
221+
builder.pop();
222+
html.HtmlElement content = builder.build().webOnlyRootElement;
223+
expect(content.querySelectorAll('flt-picture').single.children, isNotEmpty);
224+
}
225+
226+
// Picture fully clipped out, so we should not see a `<flt-canvas>`
227+
{
228+
final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
229+
builder.pushOffset(0, 0);
230+
builder.pushClipRect(const Rect.fromLTRB(1000, 1000, 2000, 2000));
231+
builder.addPicture(Offset.zero, picture);
232+
builder.pop();
233+
builder.pop();
234+
html.HtmlElement content = builder.build().webOnlyRootElement;
235+
expect(content.querySelectorAll('flt-picture').single.children, isEmpty);
236+
}
237+
});
213238
}
214239

215240
typedef TestLayerBuilder = EngineLayer Function(

0 commit comments

Comments
 (0)