use toFixedAsString and DoubleProperty in diagnosticProperties (#33488)

diff --git a/packages/flutter/lib/src/foundation/debug.dart b/packages/flutter/lib/src/foundation/debug.dart
index c445e97..a83c1d9 100644
--- a/packages/flutter/lib/src/foundation/debug.dart
+++ b/packages/flutter/lib/src/foundation/debug.dart
@@ -24,7 +24,8 @@
 bool debugAssertAllFoundationVarsUnset(String reason, { DebugPrintCallback debugPrintOverride = debugPrintThrottled }) {
   assert(() {
     if (debugPrint != debugPrintOverride ||
-        debugDefaultTargetPlatformOverride != null)
+        debugDefaultTargetPlatformOverride != null ||
+        debugDoublePrecision != null)
       throw FlutterError(reason);
     return true;
   }());
@@ -73,3 +74,21 @@
 const Map<String, String> timelineWhitelistArguments = <String, String>{
   'mode': 'basic',
 };
+
+/// Configure [debugFormatDouble] using [num.toStringAsPrecision].
+///
+/// Defaults to null, which uses the default logic of [debugFormatDouble].
+int debugDoublePrecision;
+
+/// Formats a double to have standard formatting.
+///
+/// This behavior can be overriden by [debugDoublePrecision].
+String debugFormatDouble(double value) {
+  if (value == null) {
+    return 'null';
+  }
+  if (debugDoublePrecision != null) {
+    return value.toStringAsPrecision(debugDoublePrecision);
+  }
+  return value.toStringAsFixed(1);
+}
diff --git a/packages/flutter/lib/src/foundation/diagnostics.dart b/packages/flutter/lib/src/foundation/diagnostics.dart
index 294192a..9a07e20 100644
--- a/packages/flutter/lib/src/foundation/diagnostics.dart
+++ b/packages/flutter/lib/src/foundation/diagnostics.dart
@@ -7,6 +7,7 @@
 import 'package:meta/meta.dart';
 
 import 'assertions.dart';
+import 'debug.dart';
 
 // Examples can assume:
 // int rows, columns;
@@ -1911,7 +1912,7 @@
   );
 
   @override
-  String numberToString() => value?.toStringAsFixed(1);
+  String numberToString() => debugFormatDouble(value);
 }
 
 /// An int valued property with an optional unit the value is measured in.
diff --git a/packages/flutter/lib/src/material/bottom_sheet_theme.dart b/packages/flutter/lib/src/material/bottom_sheet_theme.dart
index 0ba47ea..6fd046a 100644
--- a/packages/flutter/lib/src/material/bottom_sheet_theme.dart
+++ b/packages/flutter/lib/src/material/bottom_sheet_theme.dart
@@ -105,7 +105,7 @@
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     super.debugFillProperties(properties);
     properties.add(DiagnosticsProperty<Color>('backgroundColor', backgroundColor, defaultValue: null));
-    properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
+    properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
     properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
   }
 }
diff --git a/packages/flutter/lib/src/material/dialog_theme.dart b/packages/flutter/lib/src/material/dialog_theme.dart
index 3fd0b79..8b9ca5f 100644
--- a/packages/flutter/lib/src/material/dialog_theme.dart
+++ b/packages/flutter/lib/src/material/dialog_theme.dart
@@ -122,7 +122,7 @@
     super.debugFillProperties(properties);
     properties.add(DiagnosticsProperty<Color>('backgroundColor', backgroundColor));
     properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
-    properties.add(DiagnosticsProperty<double>('elevation', elevation));
+    properties.add(DoubleProperty('elevation', elevation));
     properties.add(DiagnosticsProperty<TextStyle>('titleTextStyle', titleTextStyle, defaultValue: null));
     properties.add(DiagnosticsProperty<TextStyle>('contentTextStyle', contentTextStyle, defaultValue: null));
   }
diff --git a/packages/flutter/lib/src/material/floating_action_button_theme.dart b/packages/flutter/lib/src/material/floating_action_button_theme.dart
index 606aa2d..919207d 100644
--- a/packages/flutter/lib/src/material/floating_action_button_theme.dart
+++ b/packages/flutter/lib/src/material/floating_action_button_theme.dart
@@ -179,11 +179,11 @@
     properties.add(DiagnosticsProperty<Color>('backgroundColor', backgroundColor, defaultValue: defaultData.backgroundColor));
     properties.add(DiagnosticsProperty<Color>('focusColor', focusColor, defaultValue: defaultData.focusColor));
     properties.add(DiagnosticsProperty<Color>('hoverColor', hoverColor, defaultValue: defaultData.hoverColor));
-    properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: defaultData.elevation));
-    properties.add(DiagnosticsProperty<double>('focusElevation', focusElevation, defaultValue: defaultData.focusElevation));
-    properties.add(DiagnosticsProperty<double>('hoverElevation', hoverElevation, defaultValue: defaultData.hoverElevation));
-    properties.add(DiagnosticsProperty<double>('disabledElevation', disabledElevation, defaultValue: defaultData.disabledElevation));
-    properties.add(DiagnosticsProperty<double>('highlightElevation', highlightElevation, defaultValue: defaultData.highlightElevation));
+    properties.add(DoubleProperty('elevation', elevation, defaultValue: defaultData.elevation));
+    properties.add(DoubleProperty('focusElevation', focusElevation, defaultValue: defaultData.focusElevation));
+    properties.add(DoubleProperty('hoverElevation', hoverElevation, defaultValue: defaultData.hoverElevation));
+    properties.add(DoubleProperty('disabledElevation', disabledElevation, defaultValue: defaultData.disabledElevation));
+    properties.add(DoubleProperty('highlightElevation', highlightElevation, defaultValue: defaultData.highlightElevation));
     properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: defaultData.shape));
   }
 }
diff --git a/packages/flutter/lib/src/material/snack_bar_theme.dart b/packages/flutter/lib/src/material/snack_bar_theme.dart
index 01e3fce..39aeb1e 100644
--- a/packages/flutter/lib/src/material/snack_bar_theme.dart
+++ b/packages/flutter/lib/src/material/snack_bar_theme.dart
@@ -166,7 +166,7 @@
     properties.add(DiagnosticsProperty<Color>('backgroundColor', backgroundColor, defaultValue: null));
     properties.add(DiagnosticsProperty<Color>('actionTextColor', actionTextColor, defaultValue: null));
     properties.add(DiagnosticsProperty<Color>('disabledActionTextColor', disabledActionTextColor, defaultValue: null));
-    properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
+    properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
     properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
     properties.add(DiagnosticsProperty<SnackBarBehavior>('behavior', behavior, defaultValue: null));
   }
diff --git a/packages/flutter/lib/src/painting/flutter_logo.dart b/packages/flutter/lib/src/painting/flutter_logo.dart
index 7c9e208..b4de45f 100644
--- a/packages/flutter/lib/src/painting/flutter_logo.dart
+++ b/packages/flutter/lib/src/painting/flutter_logo.dart
@@ -238,7 +238,7 @@
     properties.add(DiagnosticsNode.message('$lightColor/$darkColor on $textColor'));
     properties.add(EnumProperty<FlutterLogoStyle>('style', style));
     if (_inTransition)
-      properties.add(DiagnosticsNode.message('transition $_position:$_opacity'));
+      properties.add(DiagnosticsNode.message('transition ${debugFormatDouble(_position)}:${debugFormatDouble(_opacity)}'));
   }
 }
 
diff --git a/packages/flutter/lib/src/painting/image_stream.dart b/packages/flutter/lib/src/painting/image_stream.dart
index 6280c01..a6af101 100644
--- a/packages/flutter/lib/src/painting/image_stream.dart
+++ b/packages/flutter/lib/src/painting/image_stream.dart
@@ -41,7 +41,7 @@
   final double scale;
 
   @override
-  String toString() => '$image @ ${scale}x';
+  String toString() => '$image @ ${debugFormatDouble(scale)}x';
 
   @override
   int get hashCode => hashValues(image, scale);
diff --git a/packages/flutter/lib/src/painting/matrix_utils.dart b/packages/flutter/lib/src/painting/matrix_utils.dart
index c1f478c..4d0b5fb 100644
--- a/packages/flutter/lib/src/painting/matrix_utils.dart
+++ b/packages/flutter/lib/src/painting/matrix_utils.dart
@@ -265,9 +265,12 @@
 List<String> debugDescribeTransform(Matrix4 transform) {
   if (transform == null)
     return const <String>['null'];
-  final List<String> matrix = transform.toString().split('\n').toList();
-  matrix.removeLast();
-  return matrix;
+  return <String>[
+    '[0] ${debugFormatDouble(transform.entry(0, 0))},${debugFormatDouble(transform.entry(0, 1))},${debugFormatDouble(transform.entry(0, 2))},${debugFormatDouble(transform.entry(0, 3))}',
+    '[1] ${debugFormatDouble(transform.entry(1, 0))},${debugFormatDouble(transform.entry(1, 1))},${debugFormatDouble(transform.entry(1, 2))},${debugFormatDouble(transform.entry(1, 3))}',
+    '[2] ${debugFormatDouble(transform.entry(2, 0))},${debugFormatDouble(transform.entry(2, 1))},${debugFormatDouble(transform.entry(2, 2))},${debugFormatDouble(transform.entry(2, 3))}',
+    '[3] ${debugFormatDouble(transform.entry(3, 0))},${debugFormatDouble(transform.entry(3, 1))},${debugFormatDouble(transform.entry(3, 2))},${debugFormatDouble(transform.entry(3, 3))}',
+  ];
 }
 
 /// Property which handles [Matrix4] that represent transforms.
@@ -296,13 +299,13 @@
     if (parentConfiguration != null && !parentConfiguration.lineBreakProperties) {
       // Format the value on a single line to be compatible with the parent's
       // style.
-      final List<Vector4> rows = <Vector4>[
-        value.getRow(0),
-        value.getRow(1),
-        value.getRow(2),
-        value.getRow(3),
+      final List<String> values = <String>[
+        '${debugFormatDouble(value.entry(0, 0))},${debugFormatDouble(value.entry(0, 1))},${debugFormatDouble(value.entry(0, 2))},${debugFormatDouble(value.entry(0, 3))}',
+        '${debugFormatDouble(value.entry(1, 0))},${debugFormatDouble(value.entry(1, 1))},${debugFormatDouble(value.entry(1, 2))},${debugFormatDouble(value.entry(1, 3))}',
+        '${debugFormatDouble(value.entry(2, 0))},${debugFormatDouble(value.entry(2, 1))},${debugFormatDouble(value.entry(2, 2))},${debugFormatDouble(value.entry(2, 3))}',
+        '${debugFormatDouble(value.entry(3, 0))},${debugFormatDouble(value.entry(3, 1))},${debugFormatDouble(value.entry(3, 2))},${debugFormatDouble(value.entry(3, 3))}',
       ];
-      return '[${rows.join("; ")}]';
+      return '[${values.join('; ')}]';
     }
     return debugDescribeTransform(value).join('\n');
   }
diff --git a/packages/flutter/lib/src/rendering/stack.dart b/packages/flutter/lib/src/rendering/stack.dart
index ff69afb..5404395 100644
--- a/packages/flutter/lib/src/rendering/stack.dart
+++ b/packages/flutter/lib/src/rendering/stack.dart
@@ -215,17 +215,17 @@
   String toString() {
     final List<String> values = <String>[];
     if (top != null)
-      values.add('top=$top');
+      values.add('top=${debugFormatDouble(top)}');
     if (right != null)
-      values.add('right=$right');
+      values.add('right=${debugFormatDouble(right)}');
     if (bottom != null)
-      values.add('bottom=$bottom');
+      values.add('bottom=${debugFormatDouble(bottom)}');
     if (left != null)
-      values.add('left=$left');
+      values.add('left=${debugFormatDouble(left)}');
     if (width != null)
-      values.add('width=$width');
+      values.add('width=${debugFormatDouble(width)}');
     if (height != null)
-      values.add('height=$height');
+      values.add('height=${debugFormatDouble(height)}');
     if (values.isEmpty)
       values.add('not positioned');
     values.add(super.toString());
diff --git a/packages/flutter/lib/src/rendering/table.dart b/packages/flutter/lib/src/rendering/table.dart
index 1e15b26..49e19aa 100644
--- a/packages/flutter/lib/src/rendering/table.dart
+++ b/packages/flutter/lib/src/rendering/table.dart
@@ -141,7 +141,7 @@
   }
 
   @override
-  String toString() => '$runtimeType($value)';
+  String toString() => '$runtimeType(${debugFormatDouble(value)})';
 }
 
 /// Sizes the column to a fraction of the table's constraints' maxWidth.
@@ -210,7 +210,7 @@
   }
 
   @override
-  String toString() => '$runtimeType($value)';
+  String toString() => '$runtimeType(${debugFormatDouble(value)})';
 }
 
 /// Sizes the column such that it is the size that is the maximum of
@@ -1178,8 +1178,8 @@
     properties.add(DiagnosticsProperty<Map<int, TableColumnWidth>>('specified column widths', _columnWidths, level: _columnWidths.isEmpty ? DiagnosticLevel.hidden : DiagnosticLevel.info));
     properties.add(DiagnosticsProperty<TableColumnWidth>('default column width', defaultColumnWidth));
     properties.add(MessageProperty('table size', '$columns\u00D7$rows'));
-    properties.add(IterableProperty<double>('column offsets', _columnLefts, ifNull: 'unknown'));
-    properties.add(IterableProperty<double>('row offsets', _rowTops, ifNull: 'unknown'));
+    properties.add(IterableProperty<String>('column offsets', _columnLefts?.map(debugFormatDouble), ifNull: 'unknown'));
+    properties.add(IterableProperty<String>('row offsets', _rowTops?.map(debugFormatDouble), ifNull: 'unknown'));
   }
 
   @override
diff --git a/packages/flutter/test/foundation/double_precision_test.dart b/packages/flutter/test/foundation/double_precision_test.dart
new file mode 100644
index 0000000..4af84df
--- /dev/null
+++ b/packages/flutter/test/foundation/double_precision_test.dart
@@ -0,0 +1,20 @@
+// Copyright 2019 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.
+
+import 'package:flutter/foundation.dart';
+import '../flutter_test_alternative.dart';
+
+void main() {
+  test('debugFormatDouble formats doubles', () {
+    expect(debugFormatDouble(1), '1.0');
+    expect(debugFormatDouble(1.1), '1.1');
+    expect(debugFormatDouble(null), 'null');
+  });
+
+  test('debugDoublePrecision can control double precision', () {
+    debugDoublePrecision = 3;
+    expect(debugFormatDouble(1), '1.00');
+    debugDoublePrecision = null;
+  });
+}