// Copyright 2014 The Flutter 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/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; import 'rendering_tester.dart'; void main() { TestRenderingFlutterBinding.ensureInitialized(); test('RenderBaseline', () { RenderBaseline parent; RenderSizedBox child; final RenderBox root = RenderPositionedBox( alignment: Alignment.topLeft, child: parent = RenderBaseline( baseline: 0.0, baselineType: TextBaseline.alphabetic, child: child = RenderSizedBox(const Size(100.0, 100.0)), ), ); final childParentData = child.parentData! as BoxParentData; layout(root); expect(childParentData.offset.dx, equals(0.0)); expect(childParentData.offset.dy, equals(-100.0)); expect(parent.size, equals(const Size(100.0, 0.0))); parent.baseline = 25.0; pumpFrame(); expect(childParentData.offset.dx, equals(0.0)); expect(childParentData.offset.dy, equals(-75.0)); expect(parent.size, equals(const Size(100.0, 25.0))); parent.baseline = 90.0; pumpFrame(); expect(childParentData.offset.dx, equals(0.0)); expect(childParentData.offset.dy, equals(-10.0)); expect(parent.size, equals(const Size(100.0, 90.0))); parent.baseline = 100.0; pumpFrame(); expect(childParentData.offset.dx, equals(0.0)); expect(childParentData.offset.dy, equals(0.0)); expect(parent.size, equals(const Size(100.0, 100.0))); parent.baseline = 110.0; pumpFrame(); expect(childParentData.offset.dx, equals(0.0)); expect(childParentData.offset.dy, equals(10.0)); expect(parent.size, equals(const Size(100.0, 110.0))); }); test('RenderBaseline different baseline types', () { final child = _RenderBaselineTester() ..boxSize = const Size.square(100) ..alphabeticBaselineOffset = 50 ..ideographicBaselineOffset = 60; final renderBaseline = RenderBaseline( baseline: 1.0, baselineType: TextBaseline.alphabetic, child: child, ); layout(renderBaseline, phase: EnginePhase.paint); expect(renderBaseline.getDryBaseline(const BoxConstraints(), TextBaseline.alphabetic), 1.0); expect(renderBaseline.getDryBaseline(const BoxConstraints(), TextBaseline.ideographic), 11.0); child ..alphabeticBaselineOffset = null ..ideographicBaselineOffset = null ..markNeedsLayout(); // Clears baseline cache. renderBaseline.markNeedsLayout(); pumpFrame(phase: EnginePhase.paint); expect(renderBaseline.getDryBaseline(const BoxConstraints(), TextBaseline.alphabetic), isNull); expect(renderBaseline.getDryBaseline(const BoxConstraints(), TextBaseline.ideographic), isNull); }); test('RenderFlex and RenderIgnoreBaseline (control test -- with baseline)', () { final RenderBox a, b; final RenderBox root = RenderFlex( crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, textDirection: TextDirection.ltr, children: [ a = RenderParagraph( const TextSpan( text: 'a', style: TextStyle(fontSize: 128.0, fontFamily: 'FlutterTest'), ), // places baseline at y=96 textDirection: TextDirection.ltr, ), b = RenderParagraph( const TextSpan( text: 'b', style: TextStyle(fontSize: 32.0, fontFamily: 'FlutterTest'), ), // 24 above baseline, 8 below baseline textDirection: TextDirection.ltr, ), ], ); layout(root); final Offset aPos = a.localToGlobal(Offset.zero); final Offset bPos = b.localToGlobal(Offset.zero); expect(aPos.dy, 0.0); expect(bPos.dy, 96.0 - 24.0); }); test('RenderFlex and RenderIgnoreBaseline (with ignored baseline)', () { final RenderBox a, b; final RenderBox root = RenderFlex( crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, textDirection: TextDirection.ltr, children: [ RenderIgnoreBaseline( child: a = RenderParagraph( const TextSpan( text: 'a', style: TextStyle(fontSize: 128.0, fontFamily: 'FlutterTest'), ), textDirection: TextDirection.ltr, ), ), b = RenderParagraph( const TextSpan( text: 'b', style: TextStyle(fontSize: 32.0, fontFamily: 'FlutterTest'), ), textDirection: TextDirection.ltr, ), ], ); layout(root); final Offset aPos = a.localToGlobal(Offset.zero); final Offset bPos = b.localToGlobal(Offset.zero); expect(aPos.dy, 0.0); expect(bPos.dy, 0.0); }); } class _RenderBaselineTester extends RenderBox { Size boxSize = Size.zero; double? alphabeticBaselineOffset; double? ideographicBaselineOffset; @override double? computeDistanceToActualBaseline(TextBaseline baseline) { return switch (baseline) { TextBaseline.alphabetic => alphabeticBaselineOffset, TextBaseline.ideographic => ideographicBaselineOffset, }; } @override double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) { return switch (baseline) { TextBaseline.alphabetic => alphabeticBaselineOffset, TextBaseline.ideographic => ideographicBaselineOffset, }; } @override Size computeDryLayout(covariant BoxConstraints constraints) => constraints.constrain(boxSize); @override void performLayout() { size = computeDryLayout(constraints); } }