Commit dfbd8c6a authored by Adam Barth's avatar Adam Barth

Add debugDumpLayerTree to dump the layer tree

To help debugging issues with the layer tree.
parent fd1dd7fa
...@@ -107,7 +107,7 @@ class StockHomeState extends State<StockHome> { ...@@ -107,7 +107,7 @@ class StockHomeState extends State<StockHome> {
), ),
new DrawerItem( new DrawerItem(
icon: 'device/dvr', icon: 'device/dvr',
onPressed: () { debugDumpApp(); debugDumpRenderTree(); }, onPressed: () { debugDumpApp(); debugDumpRenderTree(); debugDumpLayerTree(); },
child: new Text('Dump App to Console') child: new Text('Dump App to Console')
), ),
new DrawerDivider(), new DrawerDivider(),
......
...@@ -292,3 +292,8 @@ class FlutterBinding extends HitTestTarget { ...@@ -292,3 +292,8 @@ class FlutterBinding extends HitTestTarget {
void debugDumpRenderTree() { void debugDumpRenderTree() {
debugPrint(FlutterBinding.instance.renderView.toStringDeep()); debugPrint(FlutterBinding.instance.renderView.toStringDeep());
} }
/// Prints a textual representation of the entire layer tree
void debugDumpLayerTree() {
debugPrint(FlutterBinding.instance.renderView.layer.toStringDeep());
}
...@@ -6,6 +6,8 @@ import 'dart:ui' as ui; ...@@ -6,6 +6,8 @@ import 'dart:ui' as ui;
import 'dart:async'; import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'package:vector_math/vector_math_64.dart';
/// Causes each RenderBox to paint a box around its bounds. /// Causes each RenderBox to paint a box around its bounds.
bool debugPaintSizeEnabled = false; bool debugPaintSizeEnabled = false;
...@@ -36,6 +38,12 @@ int debugPaintPointersColorValue = 0x00BBBB; ...@@ -36,6 +38,12 @@ int debugPaintPointersColorValue = 0x00BBBB;
/// The color to use when painting RenderError boxes in checked mode. /// The color to use when painting RenderError boxes in checked mode.
ui.Color debugErrorBoxColor = const ui.Color(0xFFFF0000); ui.Color debugErrorBoxColor = const ui.Color(0xFFFF0000);
List<String> debugDescribeTransform(Matrix4 transform) {
List<String> matrix = transform.toString().split('\n').map((String s) => ' $s').toList();
matrix.removeLast();
return matrix;
}
/// Prints a message to the console, which you can access using the "flutter" /// Prints a message to the console, which you can access using the "flutter"
/// tool's "logs" command ("flutter logs"). /// tool's "logs" command ("flutter logs").
/// ///
......
...@@ -7,6 +7,7 @@ import 'dart:ui' as ui; ...@@ -7,6 +7,7 @@ import 'dart:ui' as ui;
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'basic_types.dart'; import 'basic_types.dart';
import 'debug.dart';
export 'basic_types.dart'; export 'basic_types.dart';
...@@ -66,6 +67,31 @@ abstract class Layer { ...@@ -66,6 +67,31 @@ abstract class Layer {
/// The layerOffset is the accumulated offset of this layer's parent from the /// The layerOffset is the accumulated offset of this layer's parent from the
/// origin of the builder's coordinate system. /// origin of the builder's coordinate system.
void addToScene(ui.SceneBuilder builder, Offset layerOffset); void addToScene(ui.SceneBuilder builder, Offset layerOffset);
String toString() => '$runtimeType';
dynamic debugOwner;
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
String result = '$prefixLineOne$this\n';
final String childrenDescription = debugDescribeChildren(prefixOtherLines);
final String settingsPrefix = childrenDescription != '' ? '$prefixOtherLines \u2502 ' : '$prefixOtherLines ';
List<String> settings = <String>[];
debugDescribeSettings(settings);
result += settings.map((String setting) => "$settingsPrefix$setting\n").join();
if (childrenDescription == '')
result += '$prefixOtherLines\n';
result += childrenDescription;
return result;
}
void debugDescribeSettings(List<String> settings) {
if (debugOwner != null)
settings.add('owner: $debugOwner');
settings.add('offset: $offset');
}
String debugDescribeChildren(String prefix) => '';
} }
/// A composited layer containing a [Picture] /// A composited layer containing a [Picture]
...@@ -88,6 +114,10 @@ class PictureLayer extends Layer { ...@@ -88,6 +114,10 @@ class PictureLayer extends Layer {
builder.addPicture(offset + layerOffset, picture, paintBounds); builder.addPicture(offset + layerOffset, picture, paintBounds);
} }
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('paintBounds: $paintBounds');
}
} }
/// A layer that indicates to the compositor that it should display /// A layer that indicates to the compositor that it should display
...@@ -113,7 +143,6 @@ class StatisticsLayer extends Layer { ...@@ -113,7 +143,6 @@ class StatisticsLayer extends Layer {
builder.addStatistics(optionsMask, paintBounds.shift(layerOffset)); builder.addStatistics(optionsMask, paintBounds.shift(layerOffset));
builder.setRasterizerTracingThreshold(rasterizerThreshold); builder.setRasterizerTracingThreshold(rasterizerThreshold);
} }
} }
...@@ -210,6 +239,23 @@ class ContainerLayer extends Layer { ...@@ -210,6 +239,23 @@ class ContainerLayer extends Layer {
} }
} }
String debugDescribeChildren(String prefix) {
String result = '$prefix \u2502\n';
if (_firstChild != null) {
Layer child = _firstChild;
int count = 1;
while (child != _lastChild) {
result += '${child.toStringDeep("$prefix \u251C\u2500child $count: ", "$prefix \u2502")}';
count += 1;
child = child._nextSibling;
}
if (child != null) {
assert(child == _lastChild);
result += '${child.toStringDeep("$prefix \u2514\u2500child $count: ", "$prefix ")}';
}
}
return result;
}
} }
/// A composite layer that clips its children using a rectangle /// A composite layer that clips its children using a rectangle
...@@ -227,6 +273,10 @@ class ClipRectLayer extends ContainerLayer { ...@@ -227,6 +273,10 @@ class ClipRectLayer extends ContainerLayer {
builder.pop(); builder.pop();
} }
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('clipRect: $clipRect');
}
} }
/// A composite layer that clips its children using a rounded rectangle /// A composite layer that clips its children using a rounded rectangle
...@@ -248,6 +298,11 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -248,6 +298,11 @@ class ClipRRectLayer extends ContainerLayer {
builder.pop(); builder.pop();
} }
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('bounds: $bounds');
settings.add('clipRRect: $clipRRect');
}
} }
/// A composite layer that clips its children using a path /// A composite layer that clips its children using a path
...@@ -269,6 +324,11 @@ class ClipPathLayer extends ContainerLayer { ...@@ -269,6 +324,11 @@ class ClipPathLayer extends ContainerLayer {
builder.pop(); builder.pop();
} }
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('bounds: $bounds');
settings.add('clipPath: $clipPath');
}
} }
/// A composited layer that applies a transformation matrix to its children /// A composited layer that applies a transformation matrix to its children
...@@ -285,6 +345,12 @@ class TransformLayer extends ContainerLayer { ...@@ -285,6 +345,12 @@ class TransformLayer extends ContainerLayer {
addChildrenToScene(builder, Offset.zero); addChildrenToScene(builder, Offset.zero);
builder.pop(); builder.pop();
} }
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('transform:');
settings.addAll(debugDescribeTransform(transform));
}
} }
/// A composited layer that makes its children partially transparent /// A composited layer that makes its children partially transparent
...@@ -306,4 +372,10 @@ class OpacityLayer extends ContainerLayer { ...@@ -306,4 +372,10 @@ class OpacityLayer extends ContainerLayer {
addChildrenToScene(builder, offset + layerOffset); addChildrenToScene(builder, offset + layerOffset);
builder.pop(); builder.pop();
} }
void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings);
settings.add('bounds: $bounds');
settings.add('alpha: $alpha');
}
} }
...@@ -74,6 +74,10 @@ class PaintingContext { ...@@ -74,6 +74,10 @@ class PaintingContext {
assert(child.needsPaint); assert(child.needsPaint);
child._layer ??= new ContainerLayer(); child._layer ??= new ContainerLayer();
child._layer.removeAllChildren(); child._layer.removeAllChildren();
assert(() {
child._layer.debugOwner = child.debugOwner ?? child.runtimeType;
return true;
});
PaintingContext childContext = new PaintingContext._(child._layer, child.paintBounds); PaintingContext childContext = new PaintingContext._(child._layer, child.paintBounds);
child._paintWithContext(childContext, Offset.zero); child._paintWithContext(childContext, Offset.zero);
childContext._stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
...@@ -104,6 +108,10 @@ class PaintingContext { ...@@ -104,6 +108,10 @@ class PaintingContext {
} else { } else {
assert(child._layer != null); assert(child._layer != null);
child._layer.detach(); child._layer.detach();
assert(() {
child._layer.debugOwner = child.debugOwner ?? child.runtimeType;
return true;
});
} }
_appendLayer(child._layer, offset); _appendLayer(child._layer, offset);
} }
...@@ -435,7 +443,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -435,7 +443,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// Override in subclasses with children and call the visitor for each child /// Override in subclasses with children and call the visitor for each child
void visitChildren(RenderObjectVisitor visitor) { } void visitChildren(RenderObjectVisitor visitor) { }
dynamic debugOwner = ''; dynamic debugOwner;
void _debugReportException(String method, dynamic exception, StackTrace stack) { void _debugReportException(String method, dynamic exception, StackTrace stack) {
debugPrint('-- EXCEPTION --'); debugPrint('-- EXCEPTION --');
debugPrint('The following exception was raised during $method():'); debugPrint('The following exception was raised during $method():');
...@@ -443,7 +451,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -443,7 +451,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
debugPrint('Stack trace:'); debugPrint('Stack trace:');
debugPrint('$stack'); debugPrint('$stack');
debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}'); debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}');
if (debugOwner != '') if (debugOwner != null)
debugPrint('That RenderObject had the following owner:\n$debugOwner'); debugPrint('That RenderObject had the following owner:\n$debugOwner');
if (debugRenderingExceptionHandler != null) if (debugRenderingExceptionHandler != null)
debugRenderingExceptionHandler(this, method, exception, stack); debugRenderingExceptionHandler(this, method, exception, stack);
...@@ -1094,10 +1102,10 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1094,10 +1102,10 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// per string. Subclasses should override this to have their information /// per string. Subclasses should override this to have their information
/// included in toStringDeep(). /// included in toStringDeep().
void debugDescribeSettings(List<String> settings) { void debugDescribeSettings(List<String> settings) {
if (debugOwner != null)
settings.add('owner: $debugOwner');
settings.add('parentData: $parentData'); settings.add('parentData: $parentData');
settings.add('constraints: $constraints'); settings.add('constraints: $constraints');
if (debugOwner != '')
settings.add('owner: $debugOwner');
} }
/// Returns a string describing the current node's descendants. Each line of /// Returns a string describing the current node's descendants. Each line of
......
...@@ -10,6 +10,7 @@ import 'package:flutter/gestures.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter/gestures.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'box.dart'; import 'box.dart';
import 'debug.dart';
import 'object.dart'; import 'object.dart';
export 'package:flutter/src/painting/box_painter.dart'; export 'package:flutter/src/painting/box_painter.dart';
...@@ -875,10 +876,8 @@ class RenderTransform extends RenderProxyBox { ...@@ -875,10 +876,8 @@ class RenderTransform extends RenderProxyBox {
void debugDescribeSettings(List<String> settings) { void debugDescribeSettings(List<String> settings) {
super.debugDescribeSettings(settings); super.debugDescribeSettings(settings);
List<String> matrix = _transform.toString().split('\n').map((String s) => ' $s').toList();
matrix.removeLast();
settings.add('transform matrix:'); settings.add('transform matrix:');
settings.addAll(matrix); settings.addAll(debugDescribeTransform(_transform));
settings.add('origin: $origin'); settings.add('origin: $origin');
settings.add('alignment: $alignment'); settings.add('alignment: $alignment');
} }
......
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