From 0434ae22ec69c6b91d2cfa00ac715a68942446de Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Wed, 17 Jan 2018 16:30:17 -0800 Subject: [PATCH] Do not apply the canvas bounds as a cull rectangle when recording a Skia picture (#14027) The picture may need to draw outside the bounds (specifically for shadows) Fixes https://github.com/flutter/flutter/issues/12618 --- .../flutter/lib/src/rendering/object.dart | 55 +++++++------------ 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 651d845575..45d676f83b 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -59,25 +59,19 @@ typedef void PaintingContextCallback(PaintingContext context, Offset offset); /// New [PaintingContext] objects are created automatically when using /// [PaintingContext.repaintCompositedChild] and [pushLayer]. class PaintingContext { - PaintingContext._(this._containerLayer, this.canvasBounds) + PaintingContext._(this._containerLayer, this.estimatedBounds) : assert(_containerLayer != null), - assert(canvasBounds != null); + assert(estimatedBounds != null); final ContainerLayer _containerLayer; - /// The bounds within which the painting context's [canvas] will record - /// painting commands. + /// An estimate of the bounds within which the painting context's [canvas] + /// will record painting commands. This can be useful for debugging. /// - /// A render object provided with this [PaintingContext] (e.g. in its - /// [RenderObject.paint] method) is permitted to paint outside the region that - /// the render object occupies during layout, but is not permitted to paint - /// outside these canvas paints bounds. These paint bounds are used to - /// construct memory-efficient composited layers, which means attempting to - /// paint outside these bounds can attempt to write to pixels that do not - /// exist in the composited layer. + /// The canvas will allow painting outside these bounds. /// - /// The [canvasBounds] rectangle is in the [canvas] coordinate system. - final Rect canvasBounds; + /// The [estimatedBounds] rectangle is in the [canvas] coordinate system. + final Rect estimatedBounds; /// Repaint the given render object. /// @@ -200,8 +194,6 @@ class PaintingContext { /// The current canvas can change whenever you paint a child using this /// context, which means it's fragile to hold a reference to the canvas /// returned by this getter. - /// - /// Only calls within the [canvasBounds] will be recorded. Canvas get canvas { if (_canvas == null) _startRecording(); @@ -210,9 +202,9 @@ class PaintingContext { void _startRecording() { assert(!_isRecording); - _currentLayer = new PictureLayer(canvasBounds); + _currentLayer = new PictureLayer(estimatedBounds); _recorder = new ui.PictureRecorder(); - _canvas = new Canvas(_recorder, canvasBounds); + _canvas = new Canvas(_recorder); _containerLayer.append(_currentLayer); } @@ -225,14 +217,14 @@ class PaintingContext { ..style = PaintingStyle.stroke ..strokeWidth = 6.0 ..color = debugCurrentRepaintColor.toColor(); - canvas.drawRect(canvasBounds.deflate(3.0), paint); + canvas.drawRect(estimatedBounds.deflate(3.0), paint); } if (debugPaintLayerBordersEnabled) { final Paint paint = new Paint() ..style = PaintingStyle.stroke ..strokeWidth = 1.0 ..color = const Color(0xFFFF9800); - canvas.drawRect(canvasBounds, paint); + canvas.drawRect(estimatedBounds, paint); } return true; }()); @@ -284,9 +276,9 @@ class PaintingContext { } /// Appends the given layer to the recording, and calls the `painter` callback - /// with that layer, providing the `childPaintBounds` as the paint bounds of - /// the child. Canvas recording commands are not guaranteed to be stored - /// outside of the paint bounds. + /// with that layer, providing the `childPaintBounds` as the estimated paint + /// bounds of the child. The `childPaintBounds` can be used for debugging but + /// have no effect on painting. /// /// The given layer must be an unattached orphan. (Providing a newly created /// object, rather than reusing an existing layer, satisfies that @@ -309,7 +301,7 @@ class PaintingContext { assert(painter != null); _stopRecordingIfNeeded(); _appendLayer(childLayer); - final PaintingContext childContext = new PaintingContext._(childLayer, childPaintBounds ?? canvasBounds); + final PaintingContext childContext = new PaintingContext._(childLayer, childPaintBounds ?? estimatedBounds); painter(childContext, offset); childContext._stopRecordingIfNeeded(); } @@ -413,7 +405,7 @@ class PaintingContext { new TransformLayer(transform: effectiveTransform), painter, offset, - childPaintBounds: MatrixUtils.inverseTransformRect(effectiveTransform, canvasBounds), + childPaintBounds: MatrixUtils.inverseTransformRect(effectiveTransform, estimatedBounds), ); } else { canvas @@ -444,7 +436,7 @@ class PaintingContext { } @override - String toString() => '$runtimeType#$hashCode(layer: $_containerLayer, canvas bounds: $canvasBounds)'; + String toString() => '$runtimeType#$hashCode(layer: $_containerLayer, canvas bounds: $estimatedBounds)'; } /// An abstract set of layout constraints. @@ -2037,17 +2029,8 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im }()); } - /// The bounds within which this render object will paint. - /// - /// A render object and its descendants are permitted to paint outside the - /// region it occupies during layout, but they are not permitted to paint - /// outside these paints bounds. These paint bounds are used to construct - /// memory-efficient composited layers, which means attempting to paint - /// outside these bounds can attempt to write to pixels that do not exist in - /// this render object's composited layer. - /// - /// The [paintBounds] are only actually enforced when the render object is a - /// repaint boundary; see [isRepaintBoundary]. + /// An estimate of the bounds within which this render object will paint. + /// Useful for debugging flags such as [debugPaintLayerBordersEnabled]. Rect get paintBounds; /// Override this method to paint debugging information.