shape_decoration_test.dart 6.9 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:ui' as ui;
6

7 8
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
9 10
import 'package:flutter_test/flutter_test.dart';

11
import '../rendering/rendering_tester.dart';
12

13
void main() {
14
  TestRenderingFlutterBinding.ensureInitialized();
15

16
  test('ShapeDecoration constructor', () {
17 18 19 20
    const Color colorR = Color(0xffff0000);
    const Color colorG = Color(0xff00ff00);
    const Gradient gradient = LinearGradient(colors: <Color>[colorR, colorG]);
    expect(const ShapeDecoration(shape: Border()), const ShapeDecoration(shape: Border()));
21
    expect(() => ShapeDecoration(color: colorR, gradient: nonconst(gradient), shape: const Border()), throwsAssertionError);
22
    expect(
23
      ShapeDecoration.fromBoxDecoration(const BoxDecoration(shape: BoxShape.circle)),
24
      const ShapeDecoration(shape: CircleBorder()),
25 26
    );
    expect(
27
      ShapeDecoration.fromBoxDecoration(BoxDecoration(borderRadius: BorderRadiusDirectional.circular(100.0))),
28
      ShapeDecoration(shape: RoundedRectangleBorder(borderRadius: BorderRadiusDirectional.circular(100.0))),
29 30
    );
    expect(
31
      ShapeDecoration.fromBoxDecoration(BoxDecoration(shape: BoxShape.circle, border: Border.all(color: colorG))),
32
      const ShapeDecoration(shape: CircleBorder(side: BorderSide(color: colorG))),
33 34
    );
    expect(
35
      ShapeDecoration.fromBoxDecoration(BoxDecoration(border: Border.all(color: colorR))),
36
      ShapeDecoration(shape: Border.all(color: colorR)),
37 38
    );
    expect(
39
      ShapeDecoration.fromBoxDecoration(const BoxDecoration(border: BorderDirectional(start: BorderSide()))),
40
      const ShapeDecoration(shape: BorderDirectional(start: BorderSide())),
41 42 43
    );
  });

44 45 46 47 48 49
  test('ShapeDecoration.lerp identical a,b', () {
    expect(ShapeDecoration.lerp(null, null, 0), null);
    const ShapeDecoration shape = ShapeDecoration(shape: CircleBorder());
    expect(identical(ShapeDecoration.lerp(shape, shape, 0.5), shape), true);
  });

50 51 52 53 54 55 56 57
  test('ShapeDecoration.lerp null a,b', () {
    const Decoration a = ShapeDecoration(shape: CircleBorder());
    const Decoration b = ShapeDecoration(shape: RoundedRectangleBorder());
    expect(Decoration.lerp(a, null, 0.0), a);
    expect(Decoration.lerp(null, b, 0.0), b);
    expect(Decoration.lerp(null, null, 0.0), null);
  });

58
  test('ShapeDecoration.lerp and hit test', () {
59 60
    const Decoration a = ShapeDecoration(shape: CircleBorder());
    const Decoration b = ShapeDecoration(shape: RoundedRectangleBorder());
61
    const Decoration c = ShapeDecoration(shape: OvalBorder());
62 63
    expect(Decoration.lerp(a, b, 0.0), a);
    expect(Decoration.lerp(a, b, 1.0), b);
64 65 66 67
    expect(Decoration.lerp(a, c, 0.0), a);
    expect(Decoration.lerp(a, c, 1.0), c);
    expect(Decoration.lerp(b, c, 0.0), b);
    expect(Decoration.lerp(b, c, 1.0), c);
68
    const Size size = Size(200.0, 100.0); // at t=0.5, width will be 150 (x=25 to x=175).
69
    expect(a.hitTest(size, const Offset(20.0, 50.0)), isFalse);
70 71
    expect(c.hitTest(size, const Offset(50, 5.0)), isFalse);
    expect(c.hitTest(size, const Offset(5, 30.0)), isFalse);
72 73 74
    expect(Decoration.lerp(a, b, 0.1)!.hitTest(size, const Offset(20.0, 50.0)), isFalse);
    expect(Decoration.lerp(a, b, 0.5)!.hitTest(size, const Offset(20.0, 50.0)), isFalse);
    expect(Decoration.lerp(a, b, 0.9)!.hitTest(size, const Offset(20.0, 50.0)), isTrue);
75 76 77 78 79 80
    expect(Decoration.lerp(a, c, 0.1)!.hitTest(size, const Offset(30.0, 50.0)), isFalse);
    expect(Decoration.lerp(a, c, 0.5)!.hitTest(size, const Offset(30.0, 50.0)), isTrue);
    expect(Decoration.lerp(a, c, 0.9)!.hitTest(size, const Offset(30.0, 50.0)), isTrue);
    expect(Decoration.lerp(b, c, 0.1)!.hitTest(size, const Offset(45.0, 10.0)), isTrue);
    expect(Decoration.lerp(b, c, 0.5)!.hitTest(size, const Offset(30.0, 10.0)), isTrue);
    expect(Decoration.lerp(b, c, 0.9)!.hitTest(size, const Offset(10.0, 30.0)), isTrue);
81 82
    expect(b.hitTest(size, const Offset(20.0, 50.0)), isTrue);
  });
83

84 85
  test('ShapeDecoration.image RTL test', () async {
    final ui.Image image = await createTestImage(width: 100, height: 200);
86
    final List<int> log = <int>[];
87
    final ShapeDecoration decoration = ShapeDecoration(
88
      shape: const CircleBorder(),
89
      image: DecorationImage(
90
        image: TestImageProvider(image),
91 92 93 94
        alignment: AlignmentDirectional.bottomEnd,
      ),
    );
    final BoxPainter painter = decoration.createBoxPainter(() { log.add(0); });
95
    expect((Canvas canvas) => painter.paint(canvas, Offset.zero, const ImageConfiguration(size: Size(100.0, 100.0))), paintsAssertion);
96 97 98 99 100 101
    expect(
      (Canvas canvas) {
        return painter.paint(
          canvas,
          const Offset(20.0, -40.0),
          const ImageConfiguration(
102
            size: Size(1000.0, 1000.0),
103 104 105 106 107
            textDirection: TextDirection.rtl,
          ),
        );
      },
      paints
Dan Field's avatar
Dan Field committed
108
        ..drawImageRect(source: const Rect.fromLTRB(0.0, 0.0, 100.0, 200.0), destination: const Rect.fromLTRB(20.0, 1000.0 - 40.0 - 200.0, 20.0 + 100.0, 1000.0 - 40.0)),
109 110 111 112 113 114 115
    );
    expect(
      (Canvas canvas) {
        return painter.paint(
          canvas,
          Offset.zero,
          const ImageConfiguration(
116
            size: Size(100.0, 200.0),
117 118 119 120
            textDirection: TextDirection.ltr,
          ),
        );
      },
121
      isNot(paints..image()), // we always use drawImageRect
122 123 124
    );
    expect(log, isEmpty);
  });
125 126

  test('ShapeDecoration.getClipPath', () {
127
    const ShapeDecoration decoration = ShapeDecoration(shape: CircleBorder());
128 129 130 131 132 133 134 135
    const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 20.0);
    final Path clipPath = decoration.getClipPath(rect, TextDirection.ltr);
    final Matcher isLookLikeExpectedPath = isPathThat(
      includes: const <Offset>[ Offset(50.0, 10.0), ],
      excludes: const <Offset>[ Offset(1.0, 1.0), Offset(30.0, 10.0), Offset(99.0, 19.0), ],
    );
    expect(clipPath, isLookLikeExpectedPath);
  });
136 137 138 139 140 141 142 143 144 145
  test('ShapeDecoration.getClipPath for oval', () {
    const ShapeDecoration decoration = ShapeDecoration(shape: OvalBorder());
    const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 50.0);
    final Path clipPath = decoration.getClipPath(rect, TextDirection.ltr);
    final Matcher isLookLikeExpectedPath = isPathThat(
      includes: const <Offset>[ Offset(50.0, 10.0), ],
      excludes: const <Offset>[ Offset(1.0, 1.0), Offset(15.0, 1.0), Offset(99.0, 19.0), ],
    );
    expect(clipPath, isLookLikeExpectedPath);
  });
146 147 148
}

class TestImageProvider extends ImageProvider<TestImageProvider> {
149 150 151 152
  TestImageProvider(this.image);

  final ui.Image image;

153 154
  @override
  Future<TestImageProvider> obtainKey(ImageConfiguration configuration) {
155
    return SynchronousFuture<TestImageProvider>(this);
156 157 158
  }

  @override
159
  ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) {
160
    return OneFrameImageStreamCompleter(
161
      SynchronousFuture<ImageInfo>(ImageInfo(image: image)),
162 163 164
    );
  }
}