Baseline Aligned Row (#30746)

Text in a baseline aligned row now works, and the height of the row is properly calculated.
diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart
index 3208563..d34d84f 100644
--- a/packages/flutter/lib/src/material/input_decorator.dart
+++ b/packages/flutter/lib/src/material/input_decorator.dart
@@ -1058,8 +1058,7 @@
 
   @override
   double computeDistanceToActualBaseline(TextBaseline baseline) {
-    assert(false, 'not implemented');
-    return 0.0;
+    return _boxParentData(input).offset.dy + input.computeDistanceToActualBaseline(baseline);
   }
 
   // Records where the label was painted.
diff --git a/packages/flutter/lib/src/rendering/flex.dart b/packages/flutter/lib/src/rendering/flex.dart
index 908d0a4..3208df7 100644
--- a/packages/flutter/lib/src/rendering/flex.dart
+++ b/packages/flutter/lib/src/rendering/flex.dart
@@ -508,7 +508,6 @@
       // Intrinsic cross size is the max of the intrinsic cross sizes of the
       // children, after the flexible children are fit into the available space,
       // with the children sized using their max intrinsic dimensions.
-      // TODO(ianh): Support baseline alignment.
 
       // Get inflexible space using the max intrinsic dimensions of fixed children in the main direction.
       final double availableMainSpace = extent;
@@ -750,6 +749,8 @@
     if (totalFlex > 0 || crossAxisAlignment == CrossAxisAlignment.baseline) {
       final double spacePerFlex = canFlex && totalFlex > 0 ? (freeSpace / totalFlex) : double.nan;
       child = firstChild;
+      double maxSizeAboveBaseline = 0;
+      double maxSizeBelowBaseline = 0;
       while (child != null) {
         final int flex = _getFlex(child);
         if (flex > 0) {
@@ -809,8 +810,18 @@
             return true;
           }());
           final double distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
-          if (distance != null)
+          if (distance != null) {
             maxBaselineDistance = math.max(maxBaselineDistance, distance);
+            maxSizeAboveBaseline = math.max(
+              distance,
+              maxSizeAboveBaseline,
+            );
+            maxSizeBelowBaseline = math.max(
+              child.size.height - distance,
+              maxSizeBelowBaseline,
+            );
+            crossSize = maxSizeAboveBaseline + maxSizeBelowBaseline;
+          }
         }
         final FlexParentData childParentData = child.parentData;
         child = childParentData.nextSibling;
diff --git a/packages/flutter/test/widgets/basic_test.dart b/packages/flutter/test/widgets/basic_test.dart
index a1d6b91..41e218c 100644
--- a/packages/flutter/test/widgets/basic_test.dart
+++ b/packages/flutter/test/widgets/basic_test.dart
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:math' as math;
 import 'package:flutter_test/flutter_test.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter/rendering.dart';
 
@@ -146,6 +148,64 @@
     });
   });
 
+  group('Row', () {
+    testWidgets('multiple baseline aligned children', (WidgetTester tester) async {
+      final UniqueKey key1 = UniqueKey();
+      final UniqueKey key2 = UniqueKey();
+      const double fontSize1 = 54;
+      const double fontSize2 = 14;
+
+      await tester.pumpWidget(
+        MaterialApp(
+          home: Scaffold(
+            body: Container(
+              child: Row(
+                crossAxisAlignment: CrossAxisAlignment.baseline,
+                textBaseline: TextBaseline.alphabetic,
+                children: <Widget>[
+                  Text('big text',
+                    key: key1,
+                    style: const TextStyle(fontSize: fontSize1),
+                  ),
+                  Text('one\ntwo\nthree\nfour\nfive\nsix\nseven',
+                    key: key2,
+                    style: const TextStyle(fontSize: fontSize2)
+                  ),
+                ],
+              ),
+            ),
+          ),
+        ),
+      );
+
+      final RenderBox textBox1 = tester.renderObject(find.byKey(key1));
+      final RenderBox textBox2 = tester.renderObject(find.byKey(key2));
+      final RenderBox rowBox = tester.renderObject(find.byType(Row));
+
+      // The two Texts are baseline aligned, so some portion of them extends
+      // both above and below the baseline. The first has a huge font size, so
+      // it extends higher above the baseline than usual. The second has many
+      // lines, but being aligned by the first line's baseline, they hang far
+      // below the baseline. The size of the parent row is just enough to
+      // contain both of them.
+      const double ahemBaselineLocation = 0.8; // https://web-platform-tests.org/writing-tests/ahem.html
+      const double aboveBaseline1 = fontSize1 * ahemBaselineLocation;
+      const double belowBaseline1 = fontSize1 * (1 - ahemBaselineLocation);
+      const double aboveBaseline2 = fontSize2 * ahemBaselineLocation;
+      const double belowBaseline2 = fontSize2 * (1 - ahemBaselineLocation) + fontSize2 * 6;
+      final double aboveBaseline = math.max(aboveBaseline1, aboveBaseline2);
+      final double belowBaseline = math.max(belowBaseline1, belowBaseline2);
+      expect(rowBox.size.height, greaterThan(textBox1.size.height));
+      expect(rowBox.size.height, greaterThan(textBox2.size.height));
+      expect(rowBox.size.height, closeTo(aboveBaseline + belowBaseline, .001));
+      expect(tester.getTopLeft(find.byKey(key1)).dy, 0);
+      expect(
+        tester.getTopLeft(find.byKey(key2)).dy,
+        closeTo(aboveBaseline1 - aboveBaseline2, .001),
+      );
+    });
+  });
+
   test('UnconstrainedBox toString', () {
     expect(
       const UnconstrainedBox(constrainedAxis: Axis.vertical,).toString(),