Skip to content

Commit

Permalink
Do not apply the canvas bounds as a cull rectangle when recording a S…
Browse files Browse the repository at this point in the history
…kia picture (flutter#14027)

The picture may need to draw outside the bounds (specifically for shadows)

Fixes flutter#12618
  • Loading branch information
jason-simmons authored Jan 18, 2018
1 parent a67df9e commit 0434ae2
Showing 1 changed file with 19 additions and 36 deletions.
55 changes: 19 additions & 36 deletions packages/flutter/lib/src/rendering/object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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();
Expand All @@ -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);
}

Expand All @@ -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;
}());
Expand Down Expand Up @@ -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
Expand All @@ -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();
}
Expand Down Expand Up @@ -413,7 +405,7 @@ class PaintingContext {
new TransformLayer(transform: effectiveTransform),
painter,
offset,
childPaintBounds: MatrixUtils.inverseTransformRect(effectiveTransform, canvasBounds),
childPaintBounds: MatrixUtils.inverseTransformRect(effectiveTransform, estimatedBounds),
);
} else {
canvas
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 0434ae2

Please sign in to comment.