From ec2d1c9116e2592593c5f17365bf0ba33f91134c Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 19 Sep 2017 14:04:51 +0200 Subject: [PATCH] Add support for shared fonts in packages. (#12142) --- .../flutter/lib/src/painting/text_style.dart | 81 ++++- .../lib/src/services/image_provider.dart | 8 +- .../lib/src/services/image_resolution.dart | 10 +- packages/flutter/lib/src/widgets/image.dart | 8 +- .../test/painting/text_style_test.dart | 14 + packages/flutter_tools/lib/src/asset.dart | 99 +++++- .../test/asset_bundle_package_fonts_test.dart | 296 ++++++++++++++++++ .../test/asset_bundle_package_test.dart | 6 +- 8 files changed, 491 insertions(+), 31 deletions(-) create mode 100644 packages/flutter_tools/test/asset_bundle_package_fonts_test.dart diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index f05820f1663..15058c8af7e 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -122,6 +122,76 @@ import 'basic_types.dart'; /// ) /// ``` /// +/// ### Custom Fonts +/// +/// Custom fonts can be declared in the `pubspec.yaml` file as shown below: +/// +///```yaml +/// flutter: +/// fonts: +/// - family: Raleway +/// fonts: +/// - asset: fonts/Raleway-Regular.ttf +/// - asset: fonts/Raleway-Medium.ttf +/// weight: 500 +/// - asset: assets/fonts/Raleway-SemiBold.ttf +/// weight: 600 +/// - family: Schyler +/// fonts: +/// - asset: fonts/Schyler-Regular.ttf +/// - asset: fonts/Schyler-Italic.ttf +/// style: italic +///``` +/// +/// The `family` property determines the name of the font, which you can use in +/// the [fontFamily] argument. The `asset` property is a path to the font file, +/// relative to the [pubspec.yaml] file. The `weight` property specifies the +/// weight of the glyph outlines in the file as an integer multiple of 100 +/// between 100 and 900. This corresponds to the [FontWeight] class and can be +/// used in the [fontWeight] argument. The `style` property specfies whether the +/// outlines in the file are `italic` or `normal`. These values correspond to +/// the [FontStyle] class and can be used in the [fontStyle] argument. +/// +/// To select a custom font, create [TextStyle] using the [fontFamily] +/// argument as shown in the example below: +/// +/// ```dart +/// const TextStyle(fontFamily: 'Raleway') +/// ``` +/// +/// To use a font family defined in a package, the [package] argument must be +/// provided. For instance, suppose the font declaration above is in the +/// `pubspec.yaml` of a package named `my_package` which the app depends on. +/// Then creating the TextStyle is done as follows: +/// +/// ```dart +/// const TextStyle(fontFamily: 'Raleway', package: 'my_package') +/// ``` +/// +/// This is also how the package itself should create the style. +/// +/// A package can also provide font files in its `lib/` folder which will not +/// automatically be included in the app. Instead the app can use these +/// selectively when declaring a font. Suppose a package named `my_package` has: +/// +/// ``` +/// lib/fonts/Raleway-Medium.ttf +/// ``` +/// +/// Then the app can declare a font like in the example below: +/// +///```yaml +/// flutter: +/// fonts: +/// - family: Raleway +/// fonts: +/// - asset: assets/fonts/Raleway-Regular.ttf +/// - asset: packages/my_package/fonts/Raleway-Medium.ttf +/// weight: 500 +///``` +/// +/// The `lib/` is implied, so it should not be included in the asset path. +/// /// See also: /// /// * [Text], the widget for showing text in a single style. @@ -136,7 +206,7 @@ class TextStyle extends Diagnosticable { const TextStyle({ this.inherit: true, this.color, - this.fontFamily, + String fontFamily, this.fontSize, this.fontWeight, this.fontStyle, @@ -147,7 +217,10 @@ class TextStyle extends Diagnosticable { this.decoration, this.decorationColor, this.decorationStyle, - }) : assert(inherit != null); + this.package, + }) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily', + assert(inherit != null); + /// Whether null values are replaced with their value in an ancestor text /// style (e.g., in a [TextSpan] tree). @@ -163,6 +236,10 @@ class TextStyle extends Diagnosticable { /// The name of the font to use when painting the text (e.g., Roboto). final String fontFamily; + /// The name of the package from which the font is included. See the + /// documentation for the [TextStyle] class itself for details. + final String package; + /// The size of glyphs (in logical pixels) to use when painting the text. /// /// During painting, the [fontSize] is multiplied by the current diff --git a/packages/flutter/lib/src/services/image_provider.dart b/packages/flutter/lib/src/services/image_provider.dart index c29b52a1b74..bd463112161 100644 --- a/packages/flutter/lib/src/services/image_provider.dart +++ b/packages/flutter/lib/src/services/image_provider.dart @@ -627,12 +627,12 @@ class MemoryImage extends ImageProvider { /// Assets used by the package itself should also be fetched using the [package] /// argument as above. /// -/// If the desired asset is specified in the [pubspec.yaml] of the package, it +/// If the desired asset is specified in the `pubspec.yaml` of the package, it /// is bundled automatically with the app. In particular, assets used by the -/// package itself must be specified in its [pubspec.yaml]. +/// package itself must be specified in its `pubspec.yaml`. /// /// A package can also choose to have assets in its 'lib/' folder that are not -/// specified in its [pubspec.yaml]. In this case for those images to be +/// specified in its `pubspec.yaml`. In this case for those images to be /// bundled, the app has to specify which ones to include. For instance a /// package named `fancy_backgrounds` could have: /// @@ -642,7 +642,7 @@ class MemoryImage extends ImageProvider { /// lib/backgrounds/background3.png ///``` /// -/// To include, say the first image, the [pubspec.yaml] of the app should specify +/// To include, say the first image, the `pubspec.yaml` of the app should specify /// it in the `assets` section: /// /// ```yaml diff --git a/packages/flutter/lib/src/services/image_resolution.dart b/packages/flutter/lib/src/services/image_resolution.dart index 0f6b1e8e1d5..656401150bf 100644 --- a/packages/flutter/lib/src/services/image_resolution.dart +++ b/packages/flutter/lib/src/services/image_resolution.dart @@ -60,7 +60,7 @@ const String _kAssetManifestFileName = 'AssetManifest.json'; /// /// When fetching an image provided by the app itself, use the [assetName] /// argument to name the asset to choose. For instance, consider the structure -/// above. First, the [pubspec.yaml] of the project should specify its assets in +/// above. First, the `pubspec.yaml` of the project should specify its assets in /// the `flutter` section: /// /// ```yaml @@ -87,12 +87,12 @@ const String _kAssetManifestFileName = 'AssetManifest.json'; /// Assets used by the package itself should also be fetched using the [package] /// argument as above. /// -/// If the desired asset is specified in the [pubspec.yaml] of the package, it +/// If the desired asset is specified in the `pubspec.yaml` of the package, it /// is bundled automatically with the app. In particular, assets used by the -/// package itself must be specified in its [pubspec.yaml]. +/// package itself must be specified in its `pubspec.yaml`. /// /// A package can also choose to have assets in its 'lib/' folder that are not -/// specified in its [pubspec.yaml]. In this case for those images to be +/// specified in its `pubspec.yaml`. In this case for those images to be /// bundled, the app has to specify which ones to include. For instance a /// package named `fancy_backgrounds` could have: /// @@ -102,7 +102,7 @@ const String _kAssetManifestFileName = 'AssetManifest.json'; /// lib/backgrounds/background3.png ///``` /// -/// To include, say the first image, the [pubspec.yaml] of the app should specify +/// To include, say the first image, the `pubspec.yaml` of the app should specify /// it in the `assets` section: /// /// ```yaml diff --git a/packages/flutter/lib/src/widgets/image.dart b/packages/flutter/lib/src/widgets/image.dart index d8c5f97d42d..f9cdd51ac60 100644 --- a/packages/flutter/lib/src/widgets/image.dart +++ b/packages/flutter/lib/src/widgets/image.dart @@ -233,12 +233,12 @@ class Image extends StatefulWidget { /// Assets used by the package itself should also be displayed using the /// [package] argument as above. /// - /// If the desired asset is specified in the [pubspec.yaml] of the package, it + /// If the desired asset is specified in the `pubspec.yaml` of the package, it /// is bundled automatically with the app. In particular, assets used by the - /// package itself must be specified in its [pubspec.yaml]. + /// package itself must be specified in its `pubspec.yaml`. /// /// A package can also choose to have assets in its 'lib/' folder that are not - /// specified in its [pubspec.yaml]. In this case for those images to be + /// specified in its `pubspec.yaml`. In this case for those images to be /// bundled, the app has to specify which ones to include. For instance a /// package named `fancy_backgrounds` could have: /// @@ -248,7 +248,7 @@ class Image extends StatefulWidget { /// lib/backgrounds/background3.png ///``` /// - /// To include, say the first image, the [pubspec.yaml] of the app should + /// To include, say the first image, the `pubspec.yaml` of the app should /// specify it in the assets section: /// /// ```yaml diff --git a/packages/flutter/test/painting/text_style_test.dart b/packages/flutter/test/painting/text_style_test.dart index 438c4f358bc..a9d3d3705c3 100644 --- a/packages/flutter/test/painting/text_style_test.dart +++ b/packages/flutter/test/painting/text_style_test.dart @@ -121,7 +121,9 @@ void main() { final ui.ParagraphStyle ps5 = s5.getParagraphStyle(); expect(ps5, equals(new ui.ParagraphStyle(fontWeight: FontWeight.w700, fontSize: 12.0, lineHeight: 123.0))); expect(ps5.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: unspecified, fontWeight: FontWeight.w700, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 12.0, lineHeight: 123.0x, ellipsis: unspecified)'); + }); + test('TextStyle with text direction', () { final ui.ParagraphStyle ps6 = const TextStyle().getParagraphStyle(textDirection: TextDirection.ltr); expect(ps6, equals(new ui.ParagraphStyle(textDirection: TextDirection.ltr))); expect(ps6.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.ltr, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: unspecified, lineHeight: unspecified, ellipsis: unspecified)'); @@ -130,4 +132,16 @@ void main() { expect(ps7, equals(new ui.ParagraphStyle(textDirection: TextDirection.rtl))); expect(ps7.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.rtl, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: unspecified, lineHeight: unspecified, ellipsis: unspecified)'); }); + + test('TextStyle using package font', () { + final TextStyle s6 = const TextStyle(fontFamily: 'test'); + expect(s6.fontFamily, 'test'); + expect(s6.package, isNull); + expect(s6.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified)'); + + final TextStyle s7 = const TextStyle(fontFamily: 'test', package: 'p'); + expect(s7.fontFamily, 'packages/p/test'); + expect(s7.package, 'p'); + expect(s7.getTextStyle().toString(), 'TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: packages/p/test, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified)'); + }); } diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart index 7e23de4200e..8c89be9a6d1 100644 --- a/packages/flutter_tools/lib/src/asset.dart +++ b/packages/flutter_tools/lib/src/asset.dart @@ -118,6 +118,7 @@ class AssetBundle { manifestDescriptor['uses-material-design']; // Add assets from packages. + final List> fonts = >[]; for (String packageName in packageMap.map.keys) { final Uri package = packageMap.map[packageName]; if (package != null && package.scheme == 'file') { @@ -127,18 +128,30 @@ class AssetBundle { continue; final int result = await _validateFlutterManifest(packageManifest); if (result == 0) { - final Map packageManifestDescriptor = packageManifest; + Map packageManifestDescriptor = packageManifest; // Skip the app itself. if (packageManifestDescriptor['name'] == appName) continue; if (packageManifestDescriptor.containsKey('flutter')) { + packageManifestDescriptor = packageManifestDescriptor['flutter']; final String packageBasePath = fs.path.dirname(packageManifestPath); assetVariants.addAll(_parseAssets( packageMap, - packageManifestDescriptor['flutter'], + packageManifestDescriptor, packageBasePath, packageName: packageName, )); + + final bool packageUsesMaterialDesign = + packageManifestDescriptor.containsKey('uses-material-design') && + packageManifestDescriptor['uses-material-design']; + fonts.addAll(_parseFonts( + packageManifestDescriptor, + packageUsesMaterialDesign, + includeDefaultFonts, + packageMap, + packageName: packageName, + )); } } } @@ -179,10 +192,15 @@ class AssetBundle { entries[_kAssetManifestJson] = _createAssetManifest(assetVariants); - final DevFSContent fontManifest = - _createFontManifest(manifestDescriptor, usesMaterialDesign, includeDefaultFonts); - if (fontManifest != null) - entries[_kFontManifestJson] = fontManifest; + fonts.addAll(_parseFonts( + manifestDescriptor, + usesMaterialDesign, + includeDefaultFonts, + packageMap, + )); + + if (fonts.isNotEmpty) + entries[_kFontManifestJson] = new DevFSStringContent(JSON.encode(fonts)); // TODO(ianh): Only do the following line if we've changed packages or if our LICENSE file changed entries[_kLICENSE] = await _obtainLicenses(packageMap, assetBasePath, reportPackages: reportLicensedPackages); @@ -367,18 +385,73 @@ DevFSContent _createAssetManifest(Map<_Asset, List<_Asset>> assetVariants) { return new DevFSStringContent(JSON.encode(json)); } -DevFSContent _createFontManifest(Map manifestDescriptor, - bool usesMaterialDesign, - bool includeDefaultFonts) { +List> _parseFonts( + Map manifestDescriptor, + bool usesMaterialDesign, + bool includeDefaultFonts, + PackageMap packageMap, { + String packageName +}) { final List> fonts = >[]; if (usesMaterialDesign && includeDefaultFonts) { fonts.addAll(_getMaterialFonts(AssetBundle._kFontSetMaterial)); } if (manifestDescriptor != null && manifestDescriptor.containsKey('fonts')) - fonts.addAll(manifestDescriptor['fonts']); - if (fonts.isEmpty) - return null; - return new DevFSStringContent(JSON.encode(fonts)); + if (packageName == null) { + fonts.addAll(manifestDescriptor['fonts']); + } else { + fonts.addAll(_parsePackageFonts( + manifestDescriptor['fonts'], + packageName, + packageMap, + )); + } + return fonts; +} + +/// Prefixes family names and asset paths of fonts included from packages with +/// 'packages/ +/// +/// (e.g., replace {"fonts":[{"asset":"a/bar"}],"family":"bar"} by +/// {"fonts":[{"asset":"packages/foo/a/bar"}],"family":"packages/foo/bar"}) +List> _parsePackageFonts( + List> manifestDescriptor, + String packageName, + PackageMap packageMap, +) { + final List> parsedFonts = >[]; + for (Map fontFamily in manifestDescriptor) { + final Map parsedFontFamily = {}; + for (String key in fontFamily.keys) { + if (key == 'family') { + parsedFontFamily[key] = 'packages/$packageName/${fontFamily[key]}'; + } else { + assert(key == 'fonts'); + final List> parsedAssets = >[]; + for (Map assetProperties in fontFamily[key]) { + final Map parsedAssetProperties = {}; + for (String property in assetProperties.keys) { + if (property == 'asset') { + final String assetPath = assetProperties[property]; + if (assetPath.startsWith('packages') && + !fs.isFileSync(packageMap.map[packageName].resolve('../$assetPath').path)) + parsedAssetProperties[property] = assetProperties[property]; + else + parsedAssetProperties[property] = 'packages/$packageName/${assetProperties[property]}'; + } else { + assert(property == 'style' || property == 'weight'); + parsedAssetProperties[property] = assetProperties[property]; + } + } + parsedAssets.add(parsedAssetProperties); + } + parsedFontFamily[key] = parsedAssets; + } + } + parsedFonts.add(parsedFontFamily); + } + + return parsedFonts; } // Given an assets directory like this: diff --git a/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart b/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart new file mode 100644 index 00000000000..839126008cc --- /dev/null +++ b/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart @@ -0,0 +1,296 @@ +// Copyright 2017 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'; +import 'dart:convert'; + +import 'package:file/file.dart'; +import 'package:file/memory.dart'; + +import 'package:flutter_tools/src/asset.dart'; +import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/cache.dart'; + +import 'package:test/test.dart'; + +import 'src/common.dart'; +import 'src/context.dart'; + +void main() { + void writePubspecFile(String path, String name, {String fontsSection}) { + if (fontsSection == null) { + fontsSection = ''; + } else { + fontsSection = ''' +flutter: + fonts: +$fontsSection +'''; + } + + fs.file(path) + ..createSync(recursive: true) + ..writeAsStringSync(''' +name: $name +dependencies: + flutter: + sdk: flutter +$fontsSection +'''); + } + + void establishFlutterRoot() { + // Setting flutterRoot here so that it picks up the MemoryFileSystem's + // path separator. + Cache.flutterRoot = getFlutterRoot(); + } + + void writePackagesFile(String packages) { + fs.file(".packages") + ..createSync() + ..writeAsStringSync(packages); + } + + Future buildAndVerifyFonts( + List localFonts, + List packageFonts, + List packages, + String expectedAssetManifest, + ) async { + final AssetBundle bundle = new AssetBundle(); + await bundle.build(manifestPath: 'pubspec.yaml'); + + for (String packageName in packages) { + for (String packageFont in packageFonts) { + final String entryKey = 'packages/$packageName/$packageFont'; + expect(bundle.entries.containsKey(entryKey), true); + expect( + UTF8.decode(await bundle.entries[entryKey].contentsAsBytes()), + packageFont, + ); + } + + for (String localFont in localFonts) { + expect(bundle.entries.containsKey(localFont), true); + expect( + UTF8.decode(await bundle.entries[localFont].contentsAsBytes()), + localFont, + ); + } + } + + expect( + UTF8.decode(await bundle.entries['FontManifest.json'].contentsAsBytes()), + expectedAssetManifest, + ); + } + + void writeFontAsset(String path, String font) { + fs.file('$path$font') + ..createSync(recursive: true) + ..writeAsStringSync(font); + } + + group('AssetBundle fonts from packages', () { + testUsingContext('App includes neither font manifest nor fonts when no defines fonts', () async { + establishFlutterRoot(); + + writePubspecFile('pubspec.yaml', 'test'); + writePackagesFile('test_package:p/p/lib/'); + writePubspecFile('p/p/pubspec.yaml', 'test_package'); + + final AssetBundle bundle = new AssetBundle(); + await bundle.build(manifestPath: 'pubspec.yaml'); + expect(bundle.entries.length, 2); // LICENSE, AssetManifest + expect(bundle.entries.containsKey('FontManifest.json'), false); + }, overrides: contextOverrides); + + testUsingContext('App font uses font file from package', () async { + establishFlutterRoot(); + + final String fontsSection = ''' + - family: foo + fonts: + - asset: packages/test_package/bar +'''; + writePubspecFile('pubspec.yaml', 'test', fontsSection: fontsSection); + writePackagesFile('test_package:p/p/lib/'); + writePubspecFile('p/p/pubspec.yaml', 'test_package'); + + final String font = 'bar'; + writeFontAsset('p/p/lib/', font); + + final String expectedFontManifest = + '[{"fonts":[{"asset":"packages/test_package/bar"}],"family":"foo"}]'; + await buildAndVerifyFonts( + [], + [font], + ['test_package'], + expectedFontManifest, + ); + }, overrides: contextOverrides); + + testUsingContext('App font uses local font file and package font file', () async { + establishFlutterRoot(); + + final String fontsSection = ''' + - family: foo + fonts: + - asset: packages/test_package/bar + - asset: a/bar +'''; + writePubspecFile('pubspec.yaml', 'test', fontsSection: fontsSection); + writePackagesFile('test_package:p/p/lib/'); + writePubspecFile('p/p/pubspec.yaml', 'test_package'); + + final String packageFont = 'bar'; + writeFontAsset('p/p/lib/', packageFont); + final String localFont = 'a/bar'; + writeFontAsset('', localFont); + + final String expectedFontManifest = + '[{"fonts":[{"asset":"packages/test_package/bar"},{"asset":"a/bar"}],' + '"family":"foo"}]'; + await buildAndVerifyFonts( + [localFont], + [packageFont], + ['test_package'], + expectedFontManifest, + ); + }, overrides: contextOverrides); + + testUsingContext('App uses package font with own font file', () async { + establishFlutterRoot(); + + writePubspecFile('pubspec.yaml', 'test'); + writePackagesFile('test_package:p/p/lib/'); + final String fontsSection = ''' + - family: foo + fonts: + - asset: a/bar +'''; + writePubspecFile( + 'p/p/pubspec.yaml', + 'test_package', + fontsSection: fontsSection, + ); + + final String font = 'a/bar'; + writeFontAsset('p/p/', font); + + final String expectedFontManifest = + '[{"fonts":[{"asset":"packages/test_package/a/bar"}],' + '"family":"packages/test_package/foo"}]'; + await buildAndVerifyFonts( + [], + [font], + ['test_package'], + expectedFontManifest, + ); + }, overrides: contextOverrides); + + testUsingContext('App uses package font with font file from another package', () async { + establishFlutterRoot(); + + writePubspecFile('pubspec.yaml', 'test'); + writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/'); + final String fontsSection = ''' + - family: foo + fonts: + - asset: packages/test_package2/bar +'''; + writePubspecFile( + 'p/p/pubspec.yaml', + 'test_package', + fontsSection: fontsSection, + ); + writePubspecFile('p2/p/pubspec.yaml', 'test_package2'); + + final String font = 'bar'; + writeFontAsset('p2/p/lib/', font); + + final String expectedFontManifest = + '[{"fonts":[{"asset":"packages/test_package2/bar"}],' + '"family":"packages/test_package/foo"}]'; + await buildAndVerifyFonts( + [], + [font], + ['test_package2'], + expectedFontManifest, + ); + }, overrides: contextOverrides); + + testUsingContext('App uses package font with properties and own font file', () async { + establishFlutterRoot(); + + writePubspecFile('pubspec.yaml', 'test'); + writePackagesFile('test_package:p/p/lib/'); + + final String pubspec = ''' + - family: foo + fonts: + - style: italic + weight: 400 + asset: a/bar +'''; + writePubspecFile( + 'p/p/pubspec.yaml', + 'test_package', + fontsSection: pubspec, + ); + final String font = 'a/bar'; + writeFontAsset('p/p/', font); + + final String expectedFontManifest = + '[{"fonts":[{"weight":400,"style":"italic","asset":"packages/test_package/a/bar"}],' + '"family":"packages/test_package/foo"}]'; + await buildAndVerifyFonts( + [], + [font], + ['test_package'], + expectedFontManifest, + ); + }, overrides: contextOverrides); + + testUsingContext('App uses local font and package font with own font file.', () async { + establishFlutterRoot(); + + final String fontsSection = ''' + - family: foo + fonts: + - asset: a/bar +'''; + writePubspecFile( + 'pubspec.yaml', + 'test', + fontsSection: fontsSection, + ); + writePackagesFile('test_package:p/p/lib/'); + writePubspecFile( + 'p/p/pubspec.yaml', + 'test_package', + fontsSection: fontsSection, + ); + + final String font = 'a/bar'; + writeFontAsset('', font); + writeFontAsset('p/p/', font); + + final String expectedFontManifest = + '[{"fonts":[{"asset":"packages/test_package/a/bar"}],' + '"family":"packages/test_package/foo"},' + '{"fonts":[{"asset":"a/bar"}],"family":"foo"}]'; + await buildAndVerifyFonts( + [font], + [font], + ['test_package'], + expectedFontManifest, + ); + }, overrides: contextOverrides); + }); +} + +Map get contextOverrides { + return {FileSystem: () => new MemoryFileSystem()}; +} diff --git a/packages/flutter_tools/test/asset_bundle_package_test.dart b/packages/flutter_tools/test/asset_bundle_package_test.dart index ddebb1e3fde..4ba3cafaa60 100644 --- a/packages/flutter_tools/test/asset_bundle_package_test.dart +++ b/packages/flutter_tools/test/asset_bundle_package_test.dart @@ -396,6 +396,6 @@ $assetsSection }); } -Map get contextOverrides => { - FileSystem: () => new MemoryFileSystem() -}; +Map get contextOverrides { + return {FileSystem: () => new MemoryFileSystem()}; +}