@@ -145,7 +145,7 @@ class PersistedHoudiniPicture extends PersistedPicture {
145
145
_canvas = canvas;
146
146
domRenderer.clearDom (rootElement);
147
147
rootElement.append (_canvas.rootElement);
148
- picture.recordingCanvas.apply (_canvas);
148
+ picture.recordingCanvas.apply (_canvas, _optimalLocalCullRect );
149
149
canvas.commit ();
150
150
}
151
151
}
@@ -231,7 +231,7 @@ class PersistedStandardPicture extends PersistedPicture {
231
231
_canvas = DomCanvas ();
232
232
domRenderer.clearDom (rootElement);
233
233
rootElement.append (_canvas.rootElement);
234
- picture.recordingCanvas.apply (_canvas);
234
+ picture.recordingCanvas.apply (_canvas, _optimalLocalCullRect );
235
235
}
236
236
237
237
void _applyBitmapPaint (EngineCanvas oldCanvas) {
@@ -244,7 +244,7 @@ class PersistedStandardPicture extends PersistedPicture {
244
244
oldCanvas.bounds = _optimalLocalCullRect;
245
245
_canvas = oldCanvas;
246
246
_canvas.clear ();
247
- picture.recordingCanvas.apply (_canvas);
247
+ picture.recordingCanvas.apply (_canvas, _optimalLocalCullRect );
248
248
} else {
249
249
// We can't use the old canvas because the size has changed, so we put
250
250
// it in a cache for later reuse.
@@ -265,7 +265,7 @@ class PersistedStandardPicture extends PersistedPicture {
265
265
domRenderer.clearDom (rootElement);
266
266
rootElement.append (_canvas.rootElement);
267
267
_canvas.clear ();
268
- picture.recordingCanvas.apply (_canvas);
268
+ picture.recordingCanvas.apply (_canvas, _optimalLocalCullRect );
269
269
},
270
270
));
271
271
}
@@ -352,7 +352,7 @@ class PersistedStandardPicture extends PersistedPicture {
352
352
/// to draw shapes and text.
353
353
abstract class PersistedPicture extends PersistedLeafSurface {
354
354
PersistedPicture (this .dx, this .dy, this .picture, this .hints)
355
- : localPaintBounds = picture.recordingCanvas.computePaintBounds () ;
355
+ : localPaintBounds = picture.recordingCanvas.pictureBounds ;
356
356
357
357
EngineCanvas _canvas;
358
358
@@ -491,7 +491,7 @@ abstract class PersistedPicture extends PersistedLeafSurface {
491
491
492
492
// The new cull rect contains area not covered by a previous rect. Perhaps
493
493
// the clip is growing, moving around the picture, or both. In this case
494
- // a part of the picture may not been painted. We will need to
494
+ // a part of the picture may not have been painted. We will need to
495
495
// request a new canvas and paint the picture on it. However, this is also
496
496
// a strong signal that the clip will continue growing as typically
497
497
// Flutter uses animated transitions. So instead of allocating the canvas
@@ -500,32 +500,45 @@ abstract class PersistedPicture extends PersistedLeafSurface {
500
500
// will hit the above case where the new cull rect is fully contained
501
501
// within the cull rect we compute now.
502
502
503
- // If any of the borders moved.
504
- // TODO(yjbanov): consider switching to Mouad's snap-to-10px strategy. It
505
- // might be sufficient, if not more effective.
506
- const double kPredictedGrowthFactor = 3.0 ;
507
- final double leftwardTrend = kPredictedGrowthFactor *
508
- math.max (oldOptimalLocalCullRect.left - _exactLocalCullRect.left, 0 );
509
- final double upwardTrend = kPredictedGrowthFactor *
510
- math.max (oldOptimalLocalCullRect.top - _exactLocalCullRect.top, 0 );
511
- final double rightwardTrend = kPredictedGrowthFactor *
512
- math.max (_exactLocalCullRect.right - oldOptimalLocalCullRect.right, 0 );
513
- final double bottomwardTrend = kPredictedGrowthFactor *
514
- math.max (
515
- _exactLocalCullRect.bottom - oldOptimalLocalCullRect.bottom, 0 );
503
+ // Compute the delta, by which each of the side of the clip rect has "moved"
504
+ // since the last time we updated the cull rect.
505
+ final double leftwardDelta = oldOptimalLocalCullRect.left - _exactLocalCullRect.left;
506
+ final double upwardDelta = oldOptimalLocalCullRect.top - _exactLocalCullRect.top;
507
+ final double rightwardDelta = _exactLocalCullRect.right - oldOptimalLocalCullRect.right;
508
+ final double bottomwardDelta = _exactLocalCullRect.bottom - oldOptimalLocalCullRect.bottom;
516
509
510
+ // Compute the new optimal rect to paint into.
517
511
final ui.Rect newLocalCullRect = ui.Rect .fromLTRB (
518
- oldOptimalLocalCullRect .left - leftwardTrend ,
519
- oldOptimalLocalCullRect .top - upwardTrend ,
520
- oldOptimalLocalCullRect .right + rightwardTrend ,
521
- oldOptimalLocalCullRect .bottom + bottomwardTrend ,
512
+ _exactLocalCullRect .left - _predictTrend (leftwardDelta, _exactLocalCullRect.width) ,
513
+ _exactLocalCullRect .top - _predictTrend (upwardDelta, _exactLocalCullRect.height) ,
514
+ _exactLocalCullRect .right + _predictTrend (rightwardDelta, _exactLocalCullRect.width) ,
515
+ _exactLocalCullRect .bottom + _predictTrend (bottomwardDelta, _exactLocalCullRect.height) ,
522
516
).intersect (localPaintBounds);
523
517
524
518
final bool localCullRectChanged = _optimalLocalCullRect != newLocalCullRect;
525
519
_optimalLocalCullRect = newLocalCullRect;
526
520
return localCullRectChanged;
527
521
}
528
522
523
+ /// Predicts the delta a particular side of a clip rect will move given the
524
+ /// [delta] it moved by last, and the respective [extent] (width or height)
525
+ /// of the clip.
526
+ static double _predictTrend (double delta, double extent) {
527
+ if (delta <= 0.0 ) {
528
+ // Shrinking. Give it 10% of the extent in case the trend is reversed.
529
+ return extent * 0.1 ;
530
+ } else {
531
+ // Growing. Predict 10 more frames of similar deltas. Give it at least
532
+ // 50% of the extent (protect from extremely slow growth trend such as
533
+ // slow scrolling). Give no more than the full extent (protects from
534
+ // fast scrolling that could lead to overallocation).
535
+ return math.min (
536
+ math.max (extent * 0.5 , delta * 10.0 ),
537
+ extent,
538
+ );
539
+ }
540
+ }
541
+
529
542
/// Number of bitmap pixel painted by this picture.
530
543
///
531
544
/// If the implementation does not paint onto a bitmap canvas, it should
0 commit comments