Commit 687ff57e authored by Adam Barth's avatar Adam Barth

Merge pull request #1528 from abarth/layer_offset

Viewport fails to clip its AssetImage child
parents 9bf4016e 167fbced
...@@ -17,11 +17,6 @@ export 'basic_types.dart'; ...@@ -17,11 +17,6 @@ export 'basic_types.dart';
/// are uploaded into the engine and displayed by the compositor. This class is /// are uploaded into the engine and displayed by the compositor. This class is
/// the base class for all composited layers. /// the base class for all composited layers.
abstract class Layer { abstract class Layer {
Layer({ this.offset: Offset.zero });
/// Offset from parent in the parent's coordinate system.
Offset offset;
/// This layer's parent in the layer tree /// This layer's parent in the layer tree
ContainerLayer get parent => _parent; ContainerLayer get parent => _parent;
ContainerLayer _parent; ContainerLayer _parent;
...@@ -95,7 +90,6 @@ abstract class Layer { ...@@ -95,7 +90,6 @@ abstract class Layer {
void debugDescribeSettings(List<String> settings) { void debugDescribeSettings(List<String> settings) {
if (debugOwner != null) if (debugOwner != null)
settings.add('owner: $debugOwner'); settings.add('owner: $debugOwner');
settings.add('offset: $offset');
} }
String debugDescribeChildren(String prefix) => ''; String debugDescribeChildren(String prefix) => '';
...@@ -103,16 +97,13 @@ abstract class Layer { ...@@ -103,16 +97,13 @@ abstract class Layer {
/// A composited layer containing a [Picture] /// A composited layer containing a [Picture]
class PictureLayer extends Layer { class PictureLayer extends Layer {
PictureLayer({ Offset offset: Offset.zero })
: super(offset: offset);
/// The picture recorded for this layer /// The picture recorded for this layer
/// ///
/// The picture's coodinate system matches this layer's coodinate system /// The picture's coodinate system matches this layer's coodinate system
ui.Picture picture; ui.Picture picture;
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
builder.addPicture(offset + layerOffset, picture); builder.addPicture(layerOffset, picture);
} }
} }
...@@ -120,11 +111,10 @@ class PictureLayer extends Layer { ...@@ -120,11 +111,10 @@ class PictureLayer extends Layer {
/// certain performance statistics within it. /// certain performance statistics within it.
class PerformanceOverlayLayer extends Layer { class PerformanceOverlayLayer extends Layer {
PerformanceOverlayLayer({ PerformanceOverlayLayer({
Offset offset: Offset.zero,
this.overlayRect, this.overlayRect,
this.optionsMask, this.optionsMask,
this.rasterizerThreshold this.rasterizerThreshold
}) : super(offset: offset); });
/// The rectangle in this layer's coodinate system that the overlay should occupy. /// The rectangle in this layer's coodinate system that the overlay should occupy.
Rect overlayRect; Rect overlayRect;
...@@ -136,7 +126,7 @@ class PerformanceOverlayLayer extends Layer { ...@@ -136,7 +126,7 @@ class PerformanceOverlayLayer extends Layer {
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
assert(optionsMask != null); assert(optionsMask != null);
builder.addPerformanceOverlay(optionsMask, overlayRect.shift(offset + layerOffset)); builder.addPerformanceOverlay(optionsMask, overlayRect.shift(layerOffset));
builder.setRasterizerTracingThreshold(rasterizerThreshold); builder.setRasterizerTracingThreshold(rasterizerThreshold);
} }
} }
...@@ -144,8 +134,6 @@ class PerformanceOverlayLayer extends Layer { ...@@ -144,8 +134,6 @@ class PerformanceOverlayLayer extends Layer {
/// A composited layer that has a list of children /// A composited layer that has a list of children
class ContainerLayer extends Layer { class ContainerLayer extends Layer {
ContainerLayer({ Offset offset: Offset.zero }) : super(offset: offset);
/// The first composited layer in this layer's child list /// The first composited layer in this layer's child list
Layer get firstChild => _firstChild; Layer get firstChild => _firstChild;
Layer _firstChild; Layer _firstChild;
...@@ -230,7 +218,7 @@ class ContainerLayer extends Layer { ...@@ -230,7 +218,7 @@ class ContainerLayer extends Layer {
} }
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
addChildrenToScene(builder, offset + layerOffset); addChildrenToScene(builder, layerOffset);
} }
/// Uploads all of this layer's children to the engine /// Uploads all of this layer's children to the engine
...@@ -261,9 +249,26 @@ class ContainerLayer extends Layer { ...@@ -261,9 +249,26 @@ class ContainerLayer extends Layer {
} }
} }
class OffsetLayer extends ContainerLayer {
OffsetLayer({ this.offset: Offset.zero });
/// Offset from parent in the parent's coordinate system.
Offset offset;
void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
addChildrenToScene(builder, offset + layerOffset);
}
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('offset: $offset');
}
}
/// A composite layer that clips its children using a rectangle /// A composite layer that clips its children using a rectangle
class ClipRectLayer extends ContainerLayer { class ClipRectLayer extends ContainerLayer {
ClipRectLayer({ Offset offset: Offset.zero, this.clipRect }) : super(offset: offset); ClipRectLayer({ this.clipRect });
/// The rectangle to clip in the parent's coordinate system /// The rectangle to clip in the parent's coordinate system
Rect clipRect; Rect clipRect;
...@@ -271,9 +276,8 @@ class ClipRectLayer extends ContainerLayer { ...@@ -271,9 +276,8 @@ class ClipRectLayer extends ContainerLayer {
// instead of in the coordinate system of this layer? // instead of in the coordinate system of this layer?
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
Offset childOffset = offset + layerOffset; builder.pushClipRect(clipRect.shift(layerOffset));
builder.pushClipRect(clipRect.shift(childOffset)); addChildrenToScene(builder, layerOffset);
addChildrenToScene(builder, childOffset);
builder.pop(); builder.pop();
} }
...@@ -285,7 +289,7 @@ class ClipRectLayer extends ContainerLayer { ...@@ -285,7 +289,7 @@ class ClipRectLayer extends ContainerLayer {
/// A composite layer that clips its children using a rounded rectangle /// A composite layer that clips its children using a rounded rectangle
class ClipRRectLayer extends ContainerLayer { class ClipRRectLayer extends ContainerLayer {
ClipRRectLayer({ Offset offset: Offset.zero, this.clipRRect }) : super(offset: offset); ClipRRectLayer({ this.clipRRect });
/// The rounded-rect to clip in the parent's coordinate system /// The rounded-rect to clip in the parent's coordinate system
ui.RRect clipRRect; ui.RRect clipRRect;
...@@ -293,9 +297,8 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -293,9 +297,8 @@ class ClipRRectLayer extends ContainerLayer {
// instead of in the coordinate system of this layer? // instead of in the coordinate system of this layer?
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
Offset childOffset = offset + layerOffset; builder.pushClipRRect(clipRRect.shift(layerOffset));
builder.pushClipRRect(clipRRect.shift(childOffset)); addChildrenToScene(builder, layerOffset);
addChildrenToScene(builder, childOffset);
builder.pop(); builder.pop();
} }
...@@ -307,7 +310,7 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -307,7 +310,7 @@ class ClipRRectLayer extends ContainerLayer {
/// A composite layer that clips its children using a path /// A composite layer that clips its children using a path
class ClipPathLayer extends ContainerLayer { class ClipPathLayer extends ContainerLayer {
ClipPathLayer({ Offset offset: Offset.zero, this.clipPath }) : super(offset: offset); ClipPathLayer({ this.clipPath });
/// The path to clip in the parent's coordinate system /// The path to clip in the parent's coordinate system
Path clipPath; Path clipPath;
...@@ -315,9 +318,8 @@ class ClipPathLayer extends ContainerLayer { ...@@ -315,9 +318,8 @@ class ClipPathLayer extends ContainerLayer {
// in the coordinate system of this layer? // in the coordinate system of this layer?
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
Offset childOffset = offset + layerOffset; builder.pushClipPath(clipPath.shift(layerOffset));
builder.pushClipPath(clipPath.shift(childOffset)); addChildrenToScene(builder, layerOffset);
addChildrenToScene(builder, childOffset);
builder.pop(); builder.pop();
} }
...@@ -328,8 +330,8 @@ class ClipPathLayer extends ContainerLayer { ...@@ -328,8 +330,8 @@ class ClipPathLayer extends ContainerLayer {
} }
/// A composited layer that applies a transformation matrix to its children /// A composited layer that applies a transformation matrix to its children
class TransformLayer extends ContainerLayer { class TransformLayer extends OffsetLayer {
TransformLayer({ Offset offset: Offset.zero, this.transform }) : super(offset: offset); TransformLayer({ Offset offset: Offset.zero, this.transform }): super(offset: offset);
/// The matrix to apply /// The matrix to apply
Matrix4 transform; Matrix4 transform;
...@@ -351,7 +353,7 @@ class TransformLayer extends ContainerLayer { ...@@ -351,7 +353,7 @@ class TransformLayer extends ContainerLayer {
/// A composited layer that makes its children partially transparent /// A composited layer that makes its children partially transparent
class OpacityLayer extends ContainerLayer { class OpacityLayer extends ContainerLayer {
OpacityLayer({ Offset offset: Offset.zero, this.alpha }) : super(offset: offset); OpacityLayer({ this.alpha });
/// The amount to multiply into the alpha channel /// The amount to multiply into the alpha channel
/// ///
...@@ -360,9 +362,8 @@ class OpacityLayer extends ContainerLayer { ...@@ -360,9 +362,8 @@ class OpacityLayer extends ContainerLayer {
int alpha; int alpha;
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
Offset childOffset = offset + layerOffset;
builder.pushOpacity(alpha); builder.pushOpacity(alpha);
addChildrenToScene(builder, childOffset); addChildrenToScene(builder, layerOffset);
builder.pop(); builder.pop();
} }
...@@ -374,7 +375,7 @@ class OpacityLayer extends ContainerLayer { ...@@ -374,7 +375,7 @@ class OpacityLayer extends ContainerLayer {
/// A composited layer that applies a shader to hits children. /// A composited layer that applies a shader to hits children.
class ShaderMaskLayer extends ContainerLayer { class ShaderMaskLayer extends ContainerLayer {
ShaderMaskLayer({ Offset offset: Offset.zero, this.shader, this.maskRect, this.transferMode }) : super(offset: offset); ShaderMaskLayer({ this.shader, this.maskRect, this.transferMode });
/// The shader to apply to the children. /// The shader to apply to the children.
ui.Shader shader; ui.Shader shader;
...@@ -386,9 +387,8 @@ class ShaderMaskLayer extends ContainerLayer { ...@@ -386,9 +387,8 @@ class ShaderMaskLayer extends ContainerLayer {
TransferMode transferMode; TransferMode transferMode;
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
Offset childOffset = offset + layerOffset; builder.pushShaderMask(shader, maskRect.shift(layerOffset), transferMode);
builder.pushShaderMask(shader, maskRect.shift(childOffset), transferMode); addChildrenToScene(builder, layerOffset);
addChildrenToScene(builder, childOffset);
builder.pop(); builder.pop();
} }
......
...@@ -69,7 +69,7 @@ class PaintingContext { ...@@ -69,7 +69,7 @@ class PaintingContext {
static void repaintCompositedChild(RenderObject child) { static void repaintCompositedChild(RenderObject child) {
assert(child.isRepaintBoundary); assert(child.isRepaintBoundary);
assert(child.needsPaint); assert(child.needsPaint);
child._layer ??= new ContainerLayer(); child._layer ??= new OffsetLayer();
child._layer.removeAllChildren(); child._layer.removeAllChildren();
assert(() { assert(() {
child._layer.debugOwner = child.debugOwner ?? child.runtimeType; child._layer.debugOwner = child.debugOwner ?? child.runtimeType;
...@@ -110,12 +110,12 @@ class PaintingContext { ...@@ -110,12 +110,12 @@ class PaintingContext {
return true; return true;
}); });
} }
_appendLayer(child._layer, offset); child._layer.offset = offset;
_appendLayer(child._layer);
} }
void _appendLayer(Layer layer, Offset offset) { void _appendLayer(Layer layer) {
assert(!_isRecording); assert(!_isRecording);
layer.offset = offset;
_containerLayer.append(layer); _containerLayer.append(layer);
} }
...@@ -190,11 +190,11 @@ class PaintingContext { ...@@ -190,11 +190,11 @@ class PaintingContext {
void pushPerformanceOverlay(Offset offset, int optionsMask, int rasterizerThreshold, Size size) { void pushPerformanceOverlay(Offset offset, int optionsMask, int rasterizerThreshold, Size size) {
_stopRecordingIfNeeded(); _stopRecordingIfNeeded();
PerformanceOverlayLayer performanceOverlayLayer = new PerformanceOverlayLayer( PerformanceOverlayLayer performanceOverlayLayer = new PerformanceOverlayLayer(
overlayRect: new Rect.fromLTWH(0.0, 0.0, size.width, size.height), overlayRect: new Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
optionsMask: optionsMask, optionsMask: optionsMask,
rasterizerThreshold: rasterizerThreshold rasterizerThreshold: rasterizerThreshold
); );
_appendLayer(performanceOverlayLayer, offset); _appendLayer(performanceOverlayLayer);
} }
/// Push a rectangular clip rect. /// Push a rectangular clip rect.
...@@ -203,12 +203,13 @@ class PaintingContext { ...@@ -203,12 +203,13 @@ class PaintingContext {
/// is clipped by the given clip. The given clip should not incorporate the /// is clipped by the given clip. The given clip should not incorporate the
/// painting offset. /// painting offset.
void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter) { void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter) {
Rect offsetClipRect = clipRect.shift(offset);
if (needsCompositing) { if (needsCompositing) {
_stopRecordingIfNeeded(); _stopRecordingIfNeeded();
ClipRectLayer clipLayer = new ClipRectLayer(clipRect: clipRect); ClipRectLayer clipLayer = new ClipRectLayer(clipRect: offsetClipRect);
_appendLayer(clipLayer, offset); _appendLayer(clipLayer);
PaintingContext childContext = new PaintingContext._(clipLayer, clipRect); PaintingContext childContext = new PaintingContext._(clipLayer, offsetClipRect);
painter(childContext, Offset.zero); painter(childContext, offset);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
} else { } else {
canvas.save(); canvas.save();
...@@ -224,16 +225,18 @@ class PaintingContext { ...@@ -224,16 +225,18 @@ class PaintingContext {
/// is clipped by the given clip. The given clip should not incorporate the /// is clipped by the given clip. The given clip should not incorporate the
/// painting offset. /// painting offset.
void pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, ui.RRect clipRRect, PaintingContextCallback painter) { void pushClipRRect(bool needsCompositing, Offset offset, Rect bounds, ui.RRect clipRRect, PaintingContextCallback painter) {
Rect offsetBounds = bounds.shift(offset);
ui.RRect offsetClipRRect = clipRRect.shift(offset);
if (needsCompositing) { if (needsCompositing) {
_stopRecordingIfNeeded(); _stopRecordingIfNeeded();
ClipRRectLayer clipLayer = new ClipRRectLayer(clipRRect: clipRRect); ClipRRectLayer clipLayer = new ClipRRectLayer(clipRRect: offsetClipRRect);
_appendLayer(clipLayer, offset); _appendLayer(clipLayer);
PaintingContext childContext = new PaintingContext._(clipLayer, bounds); PaintingContext childContext = new PaintingContext._(clipLayer, offsetBounds);
painter(childContext, Offset.zero); painter(childContext, offset);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
} else { } else {
canvas.saveLayer(bounds.shift(offset), _disableAntialias); canvas.saveLayer(offsetBounds, _disableAntialias);
canvas.clipRRect(clipRRect.shift(offset)); canvas.clipRRect(offsetClipRRect);
painter(this, offset); painter(this, offset);
canvas.restore(); canvas.restore();
} }
...@@ -245,12 +248,14 @@ class PaintingContext { ...@@ -245,12 +248,14 @@ class PaintingContext {
/// is clipped by the given clip. The given clip should not incorporate the /// is clipped by the given clip. The given clip should not incorporate the
/// painting offset. /// painting offset.
void pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter) { void pushClipPath(bool needsCompositing, Offset offset, Rect bounds, Path clipPath, PaintingContextCallback painter) {
Rect offsetBounds = bounds.shift(offset);
Path offsetClipPath = clipPath.shift(offset);
if (needsCompositing) { if (needsCompositing) {
_stopRecordingIfNeeded(); _stopRecordingIfNeeded();
ClipPathLayer clipLayer = new ClipPathLayer(clipPath: clipPath); ClipPathLayer clipLayer = new ClipPathLayer(clipPath: offsetClipPath);
_appendLayer(clipLayer, offset); _appendLayer(clipLayer);
PaintingContext childContext = new PaintingContext._(clipLayer, bounds); PaintingContext childContext = new PaintingContext._(clipLayer, offsetBounds);
painter(childContext, Offset.zero); painter(childContext, offset);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
} else { } else {
canvas.saveLayer(bounds.shift(offset), _disableAntialias); canvas.saveLayer(bounds.shift(offset), _disableAntialias);
...@@ -268,8 +273,9 @@ class PaintingContext { ...@@ -268,8 +273,9 @@ class PaintingContext {
void pushTransform(bool needsCompositing, Offset offset, Matrix4 transform, PaintingContextCallback painter) { void pushTransform(bool needsCompositing, Offset offset, Matrix4 transform, PaintingContextCallback painter) {
if (needsCompositing) { if (needsCompositing) {
_stopRecordingIfNeeded(); _stopRecordingIfNeeded();
TransformLayer transformLayer = new TransformLayer(transform: transform); TransformLayer transformLayer = new TransformLayer(offset: offset, transform: transform);
_appendLayer(transformLayer, offset); _appendLayer(transformLayer);
// TODO(abarth): We need to run _paintBounds through the inverse of transform.
PaintingContext childContext = new PaintingContext._(transformLayer, _paintBounds); PaintingContext childContext = new PaintingContext._(transformLayer, _paintBounds);
painter(childContext, Offset.zero); painter(childContext, Offset.zero);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
...@@ -290,9 +296,9 @@ class PaintingContext { ...@@ -290,9 +296,9 @@ class PaintingContext {
void pushOpacity(Offset offset, int alpha, PaintingContextCallback painter) { void pushOpacity(Offset offset, int alpha, PaintingContextCallback painter) {
_stopRecordingIfNeeded(); _stopRecordingIfNeeded();
OpacityLayer opacityLayer = new OpacityLayer(alpha: alpha); OpacityLayer opacityLayer = new OpacityLayer(alpha: alpha);
_appendLayer(opacityLayer, offset); _appendLayer(opacityLayer);
PaintingContext childContext = new PaintingContext._(opacityLayer, _paintBounds); PaintingContext childContext = new PaintingContext._(opacityLayer, _paintBounds);
painter(childContext, Offset.zero); painter(childContext, offset);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
} }
...@@ -307,9 +313,9 @@ class PaintingContext { ...@@ -307,9 +313,9 @@ class PaintingContext {
maskRect: maskRect, maskRect: maskRect,
transferMode: transferMode transferMode: transferMode
); );
_appendLayer(shaderLayer, offset); _appendLayer(shaderLayer);
PaintingContext childContext = new PaintingContext._(shaderLayer, _paintBounds); PaintingContext childContext = new PaintingContext._(shaderLayer, _paintBounds);
painter(childContext, Offset.zero); painter(childContext, offset);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
} }
} }
...@@ -1156,11 +1162,11 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1156,11 +1162,11 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// getter changes. /// getter changes.
bool get alwaysNeedsCompositing => false; bool get alwaysNeedsCompositing => false;
ContainerLayer _layer; OffsetLayer _layer;
/// The compositing layer that this render object uses to repaint. /// The compositing layer that this render object uses to repaint.
/// ///
/// Call only when [isRepaintBoundary] is true. /// Call only when [isRepaintBoundary] is true.
ContainerLayer get layer { OffsetLayer get layer {
assert(isRepaintBoundary); assert(isRepaintBoundary);
assert(!_needsPaint); assert(!_needsPaint);
return _layer; return _layer;
...@@ -1522,7 +1528,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1522,7 +1528,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
if (!node._needsSemanticsUpdate) { if (!node._needsSemanticsUpdate) {
node._needsSemanticsUpdate = true; node._needsSemanticsUpdate = true;
_nodesNeedingSemantics.add(node); _nodesNeedingSemantics.add(node);
} }
} else { } else {
// The shape of the semantics tree around us may have changed. // The shape of the semantics tree around us may have changed.
// The worst case is that we may have removed a branch of the // The worst case is that we may have removed a branch of the
...@@ -1541,7 +1547,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1541,7 +1547,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
if (!node._needsSemanticsUpdate) { if (!node._needsSemanticsUpdate) {
node._needsSemanticsUpdate = true; node._needsSemanticsUpdate = true;
_nodesNeedingSemantics.add(node); _nodesNeedingSemantics.add(node);
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment