image_resolution_test.dart 7.78 KB
Newer Older
1 2 3 4 5
// Copyright 2016 The Chromium 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 'dart:async';
6
import 'dart:typed_data';
7
import 'dart:ui' as ui show Image;
8

9
import 'package:flutter/foundation.dart';
10 11 12
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
13
import 'package:flutter_test/flutter_test.dart';
Adam Barth's avatar
Adam Barth committed
14
import 'package:meta/meta.dart';
15 16 17 18

class TestImage extends ui.Image {
  TestImage(this.scale);
  final double scale;
19 20

  @override
21
  int get width => (48*scale).floor();
22 23

  @override
24
  int get height => (48*scale).floor();
25 26

  @override
27 28 29
  void dispose() { }
}

30 31
class TestByteData implements ByteData {
  TestByteData(this.scale);
32
  final double scale;
33 34 35

  @override
  dynamic noSuchMethod(Invocation invocation) => null;
36 37 38 39 40 41 42 43 44 45 46 47 48
}

String testManifest = '''
{
  "assets/image.png" : [
    "assets/1.5x/image.png",
    "assets/2.0x/image.png",
    "assets/3.0x/image.png",
    "assets/4.0x/image.png"
  ]
}
''';

49
class TestAssetBundle extends CachingAssetBundle {
50
  @override
51 52
  Future<ByteData> load(String key) {
    ByteData data;
53 54
    switch (key) {
      case 'assets/image.png':
55
        data = new TestByteData(1.0);
56 57
        break;
      case 'assets/1.5x/image.png':
58
        data = new TestByteData(1.5);
59 60
        break;
      case 'assets/2.0x/image.png':
61
        data = new TestByteData(2.0);
62 63
        break;
      case 'assets/3.0x/image.png':
64
        data = new TestByteData(3.0);
65 66
        break;
      case 'assets/4.0x/image.png':
67
        data = new TestByteData(4.0);
68 69
        break;
    }
70
    return new SynchronousFuture<ByteData>(data);
71 72 73 74 75 76 77
  }

  @override
  Future<String> loadString(String key, { bool cache: true }) {
    if (key == 'AssetManifest.json')
      return new SynchronousFuture<String>(testManifest);
    return null;
78
  }
79 80

  @override
81 82 83
  String toString() => '$runtimeType@$hashCode()';
}

84 85 86
class TestAssetImage extends AssetImage {
  TestAssetImage(String name) : super(name);

87 88 89
  @override
  Future<ImageInfo> loadAsync(AssetBundleImageKey key) {
    ImageInfo result;
90 91
    key.bundle.load(key.name).then<Null>((ByteData data) {
      decodeImage(data).then<Null>((ui.Image image) {
92
        result = new ImageInfo(image: image, scale: key.scale);
93 94 95 96 97 98
      });
    });
    assert(result != null);
    return new SynchronousFuture<ImageInfo>(result);
  }

99
  @override
100 101
  Future<ui.Image> decodeImage(@checked TestByteData data) {
    return new SynchronousFuture<ui.Image>(new TestImage(data.scale));
102
  }
103 104 105 106 107 108 109 110 111 112
}

Widget buildImageAtRatio(String image, Key key, double ratio, bool inferSize) {
  const double windowSize = 500.0; // 500 logical pixels
  const double imageSize = 200.0; // 200 logical pixels

  return new MediaQuery(
    data: new MediaQueryData(
      size: const Size(windowSize, windowSize),
      devicePixelRatio: ratio,
113
      padding: const EdgeInsets.all(0.0)
114
    ),
115
    child: new DefaultAssetBundle(
116 117 118
      bundle: new TestAssetBundle(),
      child: new Center(
        child: inferSize ?
119
          new Image(
120
            key: key,
121
            image: new TestAssetImage(image)
122
          ) :
123
          new Image(
124
            key: key,
125
            image: new TestAssetImage(image),
126 127 128 129 130 131 132 133 134
            height: imageSize,
            width: imageSize,
            fit: ImageFit.fill
          )
      )
    )
  );
}

135
RenderImage getRenderImage(WidgetTester tester, Key key) {
136
  return tester.renderObject<RenderImage>(find.byKey(key));
137
}
138
TestImage getTestImage(WidgetTester tester, Key key) {
139
  return tester.renderObject<RenderImage>(find.byKey(key)).image;
140 141
}

142
Future<Null> pumpTreeToLayout(WidgetTester tester, Widget widget) {
143 144
  Duration pumpDuration = const Duration(milliseconds: 0);
  EnginePhase pumpPhase = EnginePhase.layout;
145
  return tester.pumpWidget(widget, pumpDuration, pumpPhase);
146 147 148 149 150
}

void main() {
  String image = 'assets/image.png';

151
  testWidgets('Image for device pixel ratio 1.0', (WidgetTester tester) async {
152
    const double ratio = 1.0;
153
    Key key = new GlobalKey();
154
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
155 156 157
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 1.0);
    key = new GlobalKey();
158
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
159 160
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 1.0);
161 162
  });

163
  testWidgets('Image for device pixel ratio 0.5', (WidgetTester tester) async {
164
    const double ratio = 0.5;
165
    Key key = new GlobalKey();
166
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
167 168 169
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 1.0);
    key = new GlobalKey();
170
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
171 172
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 1.0);
173 174
  });

175
  testWidgets('Image for device pixel ratio 1.5', (WidgetTester tester) async {
176
    const double ratio = 1.5;
177
    Key key = new GlobalKey();
178
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
179 180 181
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 1.5);
    key = new GlobalKey();
182
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
183 184
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 1.5);
185 186
  });

187
  testWidgets('Image for device pixel ratio 1.75', (WidgetTester tester) async {
188
    const double ratio = 1.75;
189
    Key key = new GlobalKey();
190
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
191 192 193
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 1.5);
    key = new GlobalKey();
194
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
195 196
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 1.5);
197 198
  });

199
  testWidgets('Image for device pixel ratio 2.3', (WidgetTester tester) async {
200
    const double ratio = 2.3;
201
    Key key = new GlobalKey();
202
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
203 204 205
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 2.0);
    key = new GlobalKey();
206
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
207 208
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 2.0);
209 210
  });

211
  testWidgets('Image for device pixel ratio 3.7', (WidgetTester tester) async {
212
    const double ratio = 3.7;
213
    Key key = new GlobalKey();
214
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
215 216 217
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 4.0);
    key = new GlobalKey();
218
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
219 220
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 4.0);
221 222
  });

223
  testWidgets('Image for device pixel ratio 5.1', (WidgetTester tester) async {
224
    const double ratio = 5.1;
225
    Key key = new GlobalKey();
226
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
227 228 229
    expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
    expect(getTestImage(tester, key).scale, 4.0);
    key = new GlobalKey();
230
    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
231 232
    expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
    expect(getTestImage(tester, key).scale, 4.0);
233 234 235
  });

}