// 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'; class RenderTestBox extends RenderBox { late Size boxSize; int calls = 0; double value = 0.0; double next() { value += 1.0; return value; } @override double computeMinIntrinsicWidth(double height) => next(); @override double computeMaxIntrinsicWidth(double height) => next(); @override double computeMinIntrinsicHeight(double width) => next(); @override double computeMaxIntrinsicHeight(double width) => next(); @override void performLayout() { size = constraints.biggest; boxSize = size; } @override double? computeDistanceToActualBaseline(TextBaseline baseline) { calls += 1; return boxSize.height / 2.0; } } void main() { TestRenderingFlutterBinding.ensureInitialized(); test('Intrinsics cache', () { final RenderBox test = RenderTestBox(); expect(test.getMinIntrinsicWidth(0.0), equals(1.0)); expect(test.getMinIntrinsicWidth(100.0), equals(2.0)); expect(test.getMinIntrinsicWidth(200.0), equals(3.0)); expect(test.getMinIntrinsicWidth(0.0), equals(1.0)); expect(test.getMinIntrinsicWidth(100.0), equals(2.0)); expect(test.getMinIntrinsicWidth(200.0), equals(3.0)); expect(test.getMaxIntrinsicWidth(0.0), equals(4.0)); expect(test.getMaxIntrinsicWidth(100.0), equals(5.0)); expect(test.getMaxIntrinsicWidth(200.0), equals(6.0)); expect(test.getMaxIntrinsicWidth(0.0), equals(4.0)); expect(test.getMaxIntrinsicWidth(100.0), equals(5.0)); expect(test.getMaxIntrinsicWidth(200.0), equals(6.0)); expect(test.getMinIntrinsicHeight(0.0), equals(7.0)); expect(test.getMinIntrinsicHeight(100.0), equals(8.0)); expect(test.getMinIntrinsicHeight(200.0), equals(9.0)); expect(test.getMinIntrinsicHeight(0.0), equals(7.0)); expect(test.getMinIntrinsicHeight(100.0), equals(8.0)); expect(test.getMinIntrinsicHeight(200.0), equals(9.0)); expect(test.getMaxIntrinsicHeight(0.0), equals(10.0)); expect(test.getMaxIntrinsicHeight(100.0), equals(11.0)); expect(test.getMaxIntrinsicHeight(200.0), equals(12.0)); expect(test.getMaxIntrinsicHeight(0.0), equals(10.0)); expect(test.getMaxIntrinsicHeight(100.0), equals(11.0)); expect(test.getMaxIntrinsicHeight(200.0), equals(12.0)); // now read them all again backwards expect(test.getMaxIntrinsicHeight(200.0), equals(12.0)); expect(test.getMaxIntrinsicHeight(100.0), equals(11.0)); expect(test.getMaxIntrinsicHeight(0.0), equals(10.0)); expect(test.getMinIntrinsicHeight(200.0), equals(9.0)); expect(test.getMinIntrinsicHeight(100.0), equals(8.0)); expect(test.getMinIntrinsicHeight(0.0), equals(7.0)); expect(test.getMaxIntrinsicWidth(200.0), equals(6.0)); expect(test.getMaxIntrinsicWidth(100.0), equals(5.0)); expect(test.getMaxIntrinsicWidth(0.0), equals(4.0)); expect(test.getMinIntrinsicWidth(200.0), equals(3.0)); expect(test.getMinIntrinsicWidth(100.0), equals(2.0)); expect(test.getMinIntrinsicWidth(0.0), equals(1.0)); }); // Regression test for https://github.com/flutter/flutter/issues/101179 test('Cached baselines should be cleared if its parent re-layout', () { double viewHeight = 200.0; final RenderTestBox test = RenderTestBox(); final RenderBox baseline = RenderBaseline( baseline: 0.0, baselineType: TextBaseline.alphabetic, child: test, ); final RenderConstrainedBox root = RenderConstrainedBox( additionalConstraints: BoxConstraints.tightFor(width: 200.0, height: viewHeight), child: baseline, ); layout(RenderPositionedBox( child: root, )); BoxParentData? parentData = test.parentData as BoxParentData?; expect(parentData!.offset.dy, -(viewHeight / 2.0)); expect(test.calls, 1); // Trigger the root render re-layout. viewHeight = 300.0; root.additionalConstraints = BoxConstraints.tightFor(width: 200.0, height: viewHeight); pumpFrame(); parentData = test.parentData as BoxParentData?; expect(parentData!.offset.dy, -(viewHeight / 2.0)); expect(test.calls, 2); // The layout constraints change will clear the cached data. final RenderObject parent = test.parent!; expect(parent.debugNeedsLayout, false); // Do not forget notify parent dirty after the cached data be cleared by `layout()` test.markNeedsLayout(); expect(parent.debugNeedsLayout, true); pumpFrame(); expect(parent.debugNeedsLayout, false); expect(test.calls, 3); // Self dirty will clear the cached data. parent.markNeedsLayout(); pumpFrame(); expect(test.calls, 3); // Use the cached data if the layout constraints do not change. }); }