Unverified Commit 065c0fea authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Do not crash on LeaderLayer.applyTransform after retained rendering (#96144)

parent 02bf594f
......@@ -2234,7 +2234,7 @@ class LeaderLayer extends ContainerLayer {
void attach(Object owner) {
super.attach(owner);
assert(link._leader == null);
_lastOffset = null;
assert(_debugSetLastOffset(null));
link._leader = this;
}
......@@ -2242,7 +2242,7 @@ class LeaderLayer extends ContainerLayer {
void detach() {
assert(link._leader == this);
link._leader = null;
_lastOffset = null;
assert(_debugSetLastOffset(null));
super.detach();
}
......@@ -2251,7 +2251,17 @@ class LeaderLayer extends ContainerLayer {
/// This is reset to null when the layer is attached or detached, to help
/// catch cases where the follower layer ends up before the leader layer, but
/// not every case can be detected.
Offset? _lastOffset;
Offset? _debugLastOffset;
bool _debugSetLastOffset(Offset? offset) {
bool result = false;
assert(() {
_debugLastOffset = offset;
result = true;
return true;
}());
return result;
}
@override
bool findAnnotations<S extends Object>(AnnotationResult<S> result, Offset localPosition, { required bool onlyFirst }) {
......@@ -2261,14 +2271,14 @@ class LeaderLayer extends ContainerLayer {
@override
void addToScene(ui.SceneBuilder builder) {
assert(offset != null);
_lastOffset = offset;
if (_lastOffset != Offset.zero)
assert(_debugSetLastOffset(offset));
if (offset != Offset.zero)
engineLayer = builder.pushTransform(
Matrix4.translationValues(_lastOffset!.dx, _lastOffset!.dy, 0.0).storage,
Matrix4.translationValues(offset.dx, offset.dy, 0.0).storage,
oldLayer: _engineLayer as ui.TransformEngineLayer?,
);
addChildrenToScene(builder);
if (_lastOffset != Offset.zero)
if (offset != Offset.zero)
builder.pop();
}
......@@ -2281,9 +2291,8 @@ class LeaderLayer extends ContainerLayer {
/// children.
@override
void applyTransform(Layer? child, Matrix4 transform) {
assert(_lastOffset != null);
if (_lastOffset != Offset.zero)
transform.translate(_lastOffset!.dx, _lastOffset!.dy);
if (offset != Offset.zero)
transform.translate(offset.dx, offset.dy);
}
@override
......@@ -2499,7 +2508,7 @@ class FollowerLayer extends ContainerLayer {
'Linked LeaderLayer anchor is not in the same layer tree as the FollowerLayer.',
);
assert(
leader._lastOffset != null,
leader._debugLastOffset != null,
'LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.',
);
......
......@@ -218,6 +218,36 @@ void main() {
expect(leaderLayer.debugSubtreeNeedsAddToScene, false);
});
test('LeaderLayer.applyTransform can be called after retained rendering', () {
void expectTransform(RenderObject leader) {
final LeaderLayer leaderLayer = leader.debugLayer! as LeaderLayer;
final Matrix4 expected = Matrix4.identity()
..translate(leaderLayer.offset.dx, leaderLayer.offset.dy);
final Matrix4 transformed = Matrix4.identity();
leaderLayer.applyTransform(null, transformed);
expect(transformed, expected);
}
final LayerLink link = LayerLink();
late RenderLeaderLayer leader;
final RenderRepaintBoundary root = RenderRepaintBoundary(
child:RenderRepaintBoundary(
child: leader = RenderLeaderLayer(link: link),
),
);
layout(root, phase: EnginePhase.composite);
expectTransform(leader);
// Causes a repaint, but the LeaderLayer of RenderLeaderLayer will be added
// as retained and LeaderLayer.addChildrenToScene will not be called.
root.markNeedsPaint();
pumpFrame(phase: EnginePhase.composite);
// The LeaderLayer.applyTransform call shouldn't crash.
expectTransform(leader);
});
test('depthFirstIterateChildren', () {
final ContainerLayer a = ContainerLayer();
final ContainerLayer b = ContainerLayer();
......
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