cached_intrinsics_test.dart 4.85 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5
// 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';
6
import 'package:flutter_test/flutter_test.dart';
7

8 9
import 'rendering_tester.dart';

10
class RenderTestBox extends RenderBox {
11 12
  late Size boxSize;
  int calls = 0;
13
  double value = 0.0;
14 15 16 17
  double next() {
    value += 1.0;
    return value;
  }
18 19 20 21 22 23 24 25
  @override
  double computeMinIntrinsicWidth(double height) => next();
  @override
  double computeMaxIntrinsicWidth(double height) => next();
  @override
  double computeMinIntrinsicHeight(double width) => next();
  @override
  double computeMaxIntrinsicHeight(double width) => next();
26 27 28 29 30 31 32 33 34 35 36 37

  @override
  void performLayout() {
    size = constraints.biggest;
    boxSize = size;
  }

  @override
  double? computeDistanceToActualBaseline(TextBaseline baseline) {
    calls += 1;
    return boxSize.height / 2.0;
  }
38 39 40
}

void main() {
41 42
  TestRenderingFlutterBinding.ensureInitialized();

43
  test('Intrinsics cache', () {
44
    final RenderBox test = RenderTestBox();
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

    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));

  });
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

  // 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.

121
    final RenderObject parent = test.parent! as RenderObject;
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    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.
  });
137
}