mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Correct handling of assets when no main asset is present (#11564)
This commit is contained in:
parent
5ee8390e9c
commit
680d581db7
@ -150,7 +150,6 @@ class AssetImage extends AssetBundleImageProvider {
|
||||
final SplayTreeMap<double, String> mapping = new SplayTreeMap<double, String>();
|
||||
for (String candidate in candidates)
|
||||
mapping[_parseScale(candidate)] = candidate;
|
||||
mapping[_naturalResolution] = main;
|
||||
// TODO(ianh): implement support for config.locale, config.size, config.platform
|
||||
// (then document this over in the Image.asset docs)
|
||||
return _findNearest(mapping, config.devicePixelRatio);
|
||||
|
||||
@ -34,9 +34,10 @@ class TestByteData implements ByteData {
|
||||
dynamic noSuchMethod(Invocation invocation) => null;
|
||||
}
|
||||
|
||||
String testManifest = '''
|
||||
const String testManifest = '''
|
||||
{
|
||||
"assets/image.png" : [
|
||||
"assets/image.png",
|
||||
"assets/1.5x/image.png",
|
||||
"assets/2.0x/image.png",
|
||||
"assets/3.0x/image.png",
|
||||
@ -46,6 +47,10 @@ String testManifest = '''
|
||||
''';
|
||||
|
||||
class TestAssetBundle extends CachingAssetBundle {
|
||||
TestAssetBundle({ this.manifest: testManifest });
|
||||
|
||||
final String manifest;
|
||||
|
||||
@override
|
||||
Future<ByteData> load(String key) {
|
||||
ByteData data;
|
||||
@ -53,6 +58,9 @@ class TestAssetBundle extends CachingAssetBundle {
|
||||
case 'assets/image.png':
|
||||
data = new TestByteData(1.0);
|
||||
break;
|
||||
case 'assets/1.0x/image.png':
|
||||
data = new TestByteData(10.0); // see "...with a main asset and a 1.0x asset"
|
||||
break;
|
||||
case 'assets/1.5x/image.png':
|
||||
data = new TestByteData(1.5);
|
||||
break;
|
||||
@ -72,7 +80,7 @@ class TestAssetBundle extends CachingAssetBundle {
|
||||
@override
|
||||
Future<String> loadString(String key, { bool cache: true }) {
|
||||
if (key == 'AssetManifest.json')
|
||||
return new SynchronousFuture<String>(testManifest);
|
||||
return new SynchronousFuture<String>(manifest);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -101,7 +109,7 @@ class TestAssetImage extends AssetImage {
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildImageAtRatio(String image, Key key, double ratio, bool inferSize) {
|
||||
Widget buildImageAtRatio(String image, Key key, double ratio, bool inferSize, [AssetBundle bundle]) {
|
||||
const double windowSize = 500.0; // 500 logical pixels
|
||||
const double imageSize = 200.0; // 200 logical pixels
|
||||
|
||||
@ -112,7 +120,7 @@ Widget buildImageAtRatio(String image, Key key, double ratio, bool inferSize) {
|
||||
padding: const EdgeInsets.all(0.0)
|
||||
),
|
||||
child: new DefaultAssetBundle(
|
||||
bundle: new TestAssetBundle(),
|
||||
bundle: bundle ?? new TestAssetBundle(),
|
||||
child: new Center(
|
||||
child: inferSize ?
|
||||
new Image(
|
||||
@ -231,4 +239,57 @@ void main() {
|
||||
expect(getTestImage(tester, key).scale, 4.0);
|
||||
});
|
||||
|
||||
testWidgets('Image for device pixel ratio 1.0, with no main asset', (WidgetTester tester) async {
|
||||
const String manifest = '''
|
||||
{
|
||||
"assets/image.png" : [
|
||||
"assets/1.5x/image.png",
|
||||
"assets/2.0x/image.png",
|
||||
"assets/3.0x/image.png",
|
||||
"assets/4.0x/image.png"
|
||||
]
|
||||
}
|
||||
''';
|
||||
final AssetBundle bundle = new TestAssetBundle(manifest: manifest);
|
||||
|
||||
const double ratio = 1.0;
|
||||
Key key = new GlobalKey();
|
||||
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, bundle));
|
||||
expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
|
||||
expect(getTestImage(tester, key).scale, 1.5);
|
||||
key = new GlobalKey();
|
||||
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, bundle));
|
||||
expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
|
||||
expect(getTestImage(tester, key).scale, 1.5);
|
||||
});
|
||||
|
||||
testWidgets('Image for device pixel ratio 1.0, with a main asset and a 1.0x asset', (WidgetTester tester) async {
|
||||
// If both a main asset and a 1.0x asset are specified, then prefer
|
||||
// the 1.0x asset.
|
||||
|
||||
const String manifest = '''
|
||||
{
|
||||
"assets/image.png" : [
|
||||
"assets/image.png",
|
||||
"assets/1.0x/image.png",
|
||||
"assets/1.5x/image.png",
|
||||
"assets/2.0x/image.png",
|
||||
"assets/3.0x/image.png",
|
||||
"assets/4.0x/image.png"
|
||||
]
|
||||
}
|
||||
''';
|
||||
final AssetBundle bundle = new TestAssetBundle(manifest: manifest);
|
||||
|
||||
const double ratio = 1.0;
|
||||
Key key = new GlobalKey();
|
||||
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, bundle));
|
||||
expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
|
||||
expect(getTestImage(tester, key).scale, 10.0);
|
||||
key = new GlobalKey();
|
||||
await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, bundle));
|
||||
expect(getRenderImage(tester, key).size, const Size(480.0, 480.0));
|
||||
expect(getTestImage(tester, key).scale, 10.0);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -98,6 +98,10 @@ class AssetBundle {
|
||||
|
||||
final PackageMap packageMap = new PackageMap(packagesPath);
|
||||
|
||||
// The _assetVariants map contains an entry for each asset listed
|
||||
// in the pubspec.yaml file's assets and font and sections. The
|
||||
// value of each image asset is a list of resolution-specific "variants",
|
||||
// see _AssetDirectoryCache.
|
||||
final Map<_Asset, List<_Asset>> assetVariants = _parseAssets(
|
||||
packageMap,
|
||||
manifestDescriptor,
|
||||
@ -112,14 +116,24 @@ class AssetBundle {
|
||||
manifestDescriptor.containsKey('uses-material-design') &&
|
||||
manifestDescriptor['uses-material-design'];
|
||||
|
||||
// Save the contents of each image, image variant, and font
|
||||
// asset in entries.
|
||||
for (_Asset asset in assetVariants.keys) {
|
||||
if (!asset.assetFileExists && assetVariants[asset].isEmpty) {
|
||||
printStatus('Error detected in pubspec.yaml:', emphasis: true);
|
||||
printError('No file or variants found for $asset.\n');
|
||||
return 1;
|
||||
}
|
||||
if (asset.assetFileExists)
|
||||
entries[asset.assetEntry] = new DevFSFileContent(asset.assetFile);
|
||||
// The file name for an asset's "main" entry is whatever appears in
|
||||
// the pubspec.yaml file. The main entry's file must always exist for
|
||||
// font assets. It need not exist for an image if resolution-specific
|
||||
// variant files exist. An image's main entry is treated the same as a
|
||||
// "1x" resolution variant and if both exist then the explicit 1x
|
||||
// variant is preferred.
|
||||
if (asset.assetFileExists) {
|
||||
assert(!assetVariants[asset].contains(asset));
|
||||
assetVariants[asset].insert(0, asset);
|
||||
}
|
||||
for (_Asset variant in assetVariants[asset]) {
|
||||
assert(variant.assetFileExists);
|
||||
entries[variant.assetEntry] = new DevFSFileContent(variant.assetFile);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user