debug.dart 10.4 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/foundation.dart';
6
import 'package:flutter/painting.dart';
7
import 'package:vector_math/vector_math_64.dart';
8

9
export 'package:flutter/foundation.dart' show debugPrint;
10

11 12 13 14 15 16 17
// Any changes to this file should be reflected in the debugAssertAllRenderVarsUnset()
// function below.

const Color _kDebugPaintSizeColor = const Color(0xFF00FFFF);
const Color _kDebugPaintSpacingColor = const Color(0x90909090);
const Color _kDebugPaintPaddingColor = const Color(0x900090FF);
const Color _kDebugPaintPaddingInnerEdgeColor = const Color(0xFF0090FF);
Ian Hickson's avatar
Ian Hickson committed
18 19
const Color _kDebugPaintBoxArrowColor = const Color(0xFFFFFF00);
const Color _kDebugPaintSliverArrowColor = const Color(0xFF33CC33);
20 21 22 23 24 25 26
const Color _kDebugPaintAlphabeticBaselineColor = const Color(0xFF00FF00);
const Color _kDebugPaintIdeographicBaselineColor = const Color(0xFFFFD000);
const Color _kDebugPaintLayerBordersColor = const Color(0xFFFF9800);
const int _kDebugPaintPointersColorValue = 0x00BBBB;
const HSVColor _kDebugCurrentRepaintColor = const HSVColor.fromAHSV(0.4, 60.0, 1.0, 1.0);
const double _kDebugRepaintRainbowHueIncrement = 2.0;

27
/// Causes each RenderBox to paint a box around its bounds, and some extra
Ian Hickson's avatar
Ian Hickson committed
28
/// boxes, such as [RenderPadding], to draw construction lines.
29
bool debugPaintSizeEnabled = false;
Adam Barth's avatar
Adam Barth committed
30 31

/// The color to use when painting RenderObject bounds.
32
Color debugPaintSizeColor = _kDebugPaintSizeColor;
33

34
/// The color to use when painting some boxes that just add space (e.g. an empty
Ian Hickson's avatar
Ian Hickson committed
35
/// RenderConstrainedBox or [RenderPadding]).
36 37 38
///
/// Used by, among other methods, [debugPaintPadding], which is called by
/// [RenderPadding.debugPaintSize] when [debugPaintSizeEnabled] is true.
39
Color debugPaintSpacingColor = _kDebugPaintSpacingColor;
40

Ian Hickson's avatar
Ian Hickson committed
41
/// The color to use when painting [RenderPadding] edges.
42 43 44
///
/// Used by, among other methods, [debugPaintPadding], which is called by
/// [RenderPadding.debugPaintSize] when [debugPaintSizeEnabled] is true.
45
Color debugPaintPaddingColor = _kDebugPaintPaddingColor;
46

Ian Hickson's avatar
Ian Hickson committed
47
/// The color to use when painting [RenderPadding] edges. This color is painted on
48 49 50 51
/// top of [debugPaintPaddingColor].
///
/// Used by, among other methods, [debugPaintPadding], which is called by
/// [RenderPadding.debugPaintSize] when [debugPaintSizeEnabled] is true.
52
Color debugPaintPaddingInnerEdgeColor = _kDebugPaintPaddingInnerEdgeColor;
53

Ian Hickson's avatar
Ian Hickson committed
54 55 56 57 58
/// The color to use when painting the arrows used to show [RenderPositionedBox] alignment.
Color debugPaintBoxArrowColor = _kDebugPaintBoxArrowColor;

/// The color to use when painting the arrows used to show [RenderSliver] alignment.
Color debugPaintSliverArrowColor = _kDebugPaintSliverArrowColor;
59

Adam Barth's avatar
Adam Barth committed
60
/// Causes each RenderBox to paint a line at each of its baselines.
61
bool debugPaintBaselinesEnabled = false;
Adam Barth's avatar
Adam Barth committed
62 63

/// The color to use when painting alphabetic baselines.
64
Color debugPaintAlphabeticBaselineColor = _kDebugPaintAlphabeticBaselineColor;
Adam Barth's avatar
Adam Barth committed
65

66
/// The color to use when painting ideographic baselines.
67
Color debugPaintIdeographicBaselineColor = _kDebugPaintIdeographicBaselineColor;
68

Adam Barth's avatar
Adam Barth committed
69
/// Causes each Layer to paint a box around its bounds.
70
bool debugPaintLayerBordersEnabled = false;
Adam Barth's avatar
Adam Barth committed
71 72

/// The color to use when painting Layer borders.
73
Color debugPaintLayerBordersColor = _kDebugPaintLayerBordersColor;
74

75 76 77 78 79 80
/// Causes objects like [RenderPointerListener] to flash while they are being
/// tapped. This can be useful to see how large the hit box is, e.g. when
/// debugging buttons that are harder to hit than expected.
///
/// For details on how to support this in your [RenderBox] subclass, see
/// [RenderBox.debugHandleEvent].
81
bool debugPaintPointersEnabled = false;
82 83

/// The color to use when reporting pointers for [debugPaintPointersEnabled].
84
int debugPaintPointersColorValue = _kDebugPaintPointersColorValue;
85

86
/// Overlay a rotating set of colors when repainting layers in checked mode.
87
bool debugRepaintRainbowEnabled = false;
88

89 90 91
/// Overlay a rotating set of colors when repainting text in checked mode.
bool debugRepaintTextRainbowEnabled = false;

92
/// The current color to overlay when repainting a layer.
93
HSVColor debugCurrentRepaintColor = _kDebugCurrentRepaintColor;
94 95

/// The amount to increment the hue of the current repaint color.
96
double debugRepaintRainbowHueIncrement = _kDebugRepaintRainbowHueIncrement;
97

98
/// Log the call stacks that mark render objects as needing layout.
99 100 101 102 103
///
/// For sanity, this only logs the stack traces of cases where an object is
/// added to the list of nodes needing layout. This avoids printing multiple
/// redundant stack traces as a single [RenderObject.markNeedsLayout] call walks
/// up the tree.
104 105
bool debugPrintMarkNeedsLayoutStacks = false;

106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
/// Log the call stacks that mark render objects as needing paint.
bool debugPrintMarkNeedsPaintStacks = false;

/// Log the dirty render objects that are laid out each frame.
///
/// Combined with [debugPrintBeginFrameBanner], this allows you to distinguish
/// layouts triggered by the initial mounting of a render tree (e.g. in a call
/// to [runApp]) from the regular layouts triggered by the pipeline.
///
/// Combined with [debugPrintMarkNeedsLayoutStacks], this lets you watch a
/// render object's dirty/clean lifecycle.
///
/// See also:
///
///  * [debugProfilePaintsEnabled], which does something similar for
///    painting but using the timeline view.
///
///  * [debugPrintRebuildDirtyWidgets], which does something similar for widgets
///    being rebuilt.
///
///  * The discussion at [RendererBinding.drawFrame].
bool debugPrintLayouts = false;

129
/// Check the intrinsic sizes of each [RenderBox] during layout.
130 131 132
///
/// By default this is turned off since these checks are expensive, but it is
/// enabled by the test framework.
133 134
bool debugCheckIntrinsicSizes = false;

135 136 137 138 139
/// Adds [dart:developer.Timeline] events for every [RenderObject] painted.
///
/// This is only enabled in debug builds. The timing information this exposes is
/// not representative of actual paints. However, it can expose unexpected
/// painting in the timeline.
140
///
Ian Hickson's avatar
Ian Hickson committed
141 142 143
/// For details on how to use [dart:developer.Timeline] events in the Dart
/// Observatory to optimize your app, see:
/// <https://fuchsia.googlesource.com/sysui/+/master/docs/performance.md>
144 145 146 147 148 149
///
/// See also:
///
///  * [debugPrintLayouts], which does something similar for layout but using
///    console output.
///
150 151 152
///  * [debugProfileBuildsEnabled], which does something similar for widgets
///    being rebuilt, and [debugPrintRebuildDirtyWidgets], its console
///    equivalent.
153 154
///
///  * The discussion at [RendererBinding.drawFrame].
155 156 157
bool debugProfilePaintsEnabled = false;


158
/// Returns a list of strings representing the given transform in a format
159
/// useful for [TransformProperty].
160 161
///
/// If the argument is null, returns a list with the single string "null".
162
List<String> debugDescribeTransform(Matrix4 transform) {
163 164
  if (transform == null)
    return const <String>['null'];
165
  final List<String> matrix = transform.toString().split('\n').map((String s) => '  $s').toList();
166 167 168
  matrix.removeLast();
  return matrix;
}
169

170 171 172 173 174 175 176 177 178 179 180 181 182 183
/// Property which handles [Matrix4] that represent transforms.
class TransformProperty extends DiagnosticsProperty<Matrix4> {
  TransformProperty(String name, Matrix4 value, {
    Object defaultValue: kNoDefaultValue,
  }) : super(
    name,
    value,
    defaultValue: defaultValue,
  );

  @override
  String valueToString() => debugDescribeTransform(value).join('\n');
}

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
void _debugDrawDoubleRect(Canvas canvas, Rect outerRect, Rect innerRect, Color color) {
  final Path path = new Path()
    ..fillType = PathFillType.evenOdd
    ..addRect(outerRect)
    ..addRect(innerRect);
  final Paint paint = new Paint()
    ..color = color;
  canvas.drawPath(path, paint);
}

/// Paint padding using the [debugPaintPaddingColor],
/// [debugPaintPaddingInnerEdgeColor], and [debugPaintSpacingColor] colors.
///
/// Called by [RenderPadding.debugPaintSize] when [debugPaintSizeEnabled] is
/// true.
void debugPaintPadding(Canvas canvas, Rect outerRect, Rect innerRect, { double outlineWidth: 2.0 }) {
  assert(() {
    if (innerRect != null && !innerRect.isEmpty) {
      _debugDrawDoubleRect(canvas, outerRect, innerRect, debugPaintPaddingColor);
      _debugDrawDoubleRect(canvas, innerRect.inflate(outlineWidth).intersect(outerRect), innerRect, debugPaintPaddingInnerEdgeColor);
    } else {
      final Paint paint = new Paint()
        ..color = debugPaintSpacingColor;
      canvas.drawRect(outerRect, paint);
    }
    return true;
  });
}

213 214 215 216 217
/// Returns true if none of the rendering library debug variables have been changed.
///
/// This function is used by the test framework to ensure that debug variables
/// haven't been inadvertently changed.
///
218
/// See <https://docs.flutter.io/flutter/rendering/rendering-library.html> for
219
/// a complete list.
220 221 222 223 224
///
/// The `debugCheckIntrinsicSizesOverride` argument can be provided to override
/// the expected value for [debugCheckIntrinsicSizes]. (This exists because the
/// test framework itself overrides this value in some cases.)
bool debugAssertAllRenderVarsUnset(String reason, { bool debugCheckIntrinsicSizesOverride: false }) {
225 226 227 228 229 230
  assert(() {
    if (debugPaintSizeEnabled ||
        debugPaintBaselinesEnabled ||
        debugPaintLayerBordersEnabled ||
        debugPaintPointersEnabled ||
        debugRepaintRainbowEnabled ||
231
        debugRepaintTextRainbowEnabled ||
232
        debugPrintMarkNeedsLayoutStacks ||
233 234
        debugPrintMarkNeedsPaintStacks ||
        debugPrintLayouts ||
235
        debugCheckIntrinsicSizes != debugCheckIntrinsicSizesOverride ||
236 237 238 239 240
        debugProfilePaintsEnabled ||
        debugPaintSizeColor != _kDebugPaintSizeColor ||
        debugPaintSpacingColor != _kDebugPaintSpacingColor ||
        debugPaintPaddingColor != _kDebugPaintPaddingColor ||
        debugPaintPaddingInnerEdgeColor != _kDebugPaintPaddingInnerEdgeColor ||
Ian Hickson's avatar
Ian Hickson committed
241 242
        debugPaintBoxArrowColor != _kDebugPaintBoxArrowColor ||
        debugPaintSliverArrowColor != _kDebugPaintSliverArrowColor ||
243 244 245 246 247 248 249 250 251 252 253 254
        debugPaintAlphabeticBaselineColor != _kDebugPaintAlphabeticBaselineColor ||
        debugPaintIdeographicBaselineColor != _kDebugPaintIdeographicBaselineColor ||
        debugPaintLayerBordersColor != _kDebugPaintLayerBordersColor ||
        debugPaintPointersColorValue != _kDebugPaintPointersColorValue ||
        debugCurrentRepaintColor != _kDebugCurrentRepaintColor ||
        debugRepaintRainbowHueIncrement != _kDebugRepaintRainbowHueIncrement) {
      throw new FlutterError(reason);
    }
    return true;
  });
  return true;
}