diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart index 7af291079a6..79ccea38287 100644 --- a/packages/flutter/lib/src/material/input_decorator.dart +++ b/packages/flutter/lib/src/material/input_decorator.dart @@ -907,7 +907,13 @@ class _RenderDecoration extends RenderBox { return 0.0; } box.layout(constraints, parentUsesSize: true); - final double baseline = box.getDistanceToBaseline(textBaseline); + // Since internally, all layout is performed against the alphabetic baseline, + // (eg, ascents/descents are all relative to alphabetic, even if the font is + // an ideographic or hanging font), we should always obtain the reference + // baseline from the alphabetic baseline. The ideographic baseline is for + // use post-layout and is derived from the alphabetic baseline combined with + // the font metrics. + final double baseline = box.getDistanceToBaseline(TextBaseline.alphabetic); assert(baseline != null && baseline >= 0.0); return baseline; } diff --git a/packages/flutter/test/material/input_decorator_test.dart b/packages/flutter/test/material/input_decorator_test.dart index c704192e3d4..87d81b29616 100644 --- a/packages/flutter/test/material/input_decorator_test.dart +++ b/packages/flutter/test/material/input_decorator_test.dart @@ -3551,4 +3551,47 @@ void main() { 'alignLabelWithHint: true', ]); }); + + testWidgets('uses alphabetic baseline for CJK layout', (WidgetTester tester) async { + await tester.binding.setLocale('zh', 'CN'); + final Typography typography = Typography(); + + final FocusNode focusNode = FocusNode(); + final TextEditingController controller = TextEditingController(); + // The dense theme uses ideographic baselines + Widget buildFrame(bool alignLabelWithHint) { + return MaterialApp( + theme: ThemeData( + textTheme: typography.dense, + ), + home: Material( + child: Directionality( + textDirection: TextDirection.ltr, + child: TextField( + controller: controller, + focusNode: focusNode, + decoration: InputDecoration( + labelText: 'label', + alignLabelWithHint: alignLabelWithHint, + hintText: 'hint', + hintStyle: const TextStyle( + fontFamily: 'Cough', + ), + ), + ), + ), + ), + ); + } + + await tester.pumpWidget(buildFrame(true)); + await tester.pumpAndSettle(); + + // These numbers should be the values from using alphabetic baselines: + // Ideographic (incorrect) value is 31.299999713897705 + expect(tester.getTopLeft(find.text('hint')).dy, 28.75); + + // Ideographic (incorrect) value is 50.299999713897705 + expect(tester.getBottomLeft(find.text('hint')).dy, 47.75); + }); }