diff --git a/third_party/packages/flutter_svg/CHANGELOG.md b/third_party/packages/flutter_svg/CHANGELOG.md
index a6e42f55cbf..45b68e2f4c9 100644
--- a/third_party/packages/flutter_svg/CHANGELOG.md
+++ b/third_party/packages/flutter_svg/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 2.3.0
+
+* Adds `SvgPicture.precompiled` for loading precompiled vector graphics
+ assets without manually constructing an `AssetBytesLoader`.
+
## 2.2.1
* Fixes message buffer access in SvgAssetLoader.
diff --git a/third_party/packages/flutter_svg/README.md b/third_party/packages/flutter_svg/README.md
index 15395077e6b..3f5d1a87a33 100644
--- a/third_party/packages/flutter_svg/README.md
+++ b/third_party/packages/flutter_svg/README.md
@@ -150,14 +150,12 @@ clipping, masking, and overdraw. The SVG compilation is provided by
dart run vector_graphics_compiler -i assets/foo.svg -o assets/foo.svg.vec
```
-The output `foo.svg.vec` can be loaded using the default constructor of
-`SvgPicture`.
+The output `foo.svg.vec` can be loaded using the `SvgPicture.precompiled`
+constructor.
```dart
-import 'package:vector_graphics/vector_graphics.dart';
-// ยทยทยท
- const Widget svg = SvgPicture(AssetBytesLoader('assets/foo.svg.vec'));
+final Widget svg = SvgPicture.precompiled('assets/foo.svg.vec');
```
### Check SVG compatibility
diff --git a/third_party/packages/flutter_svg/example/lib/readme_excerpts.dart b/third_party/packages/flutter_svg/example/lib/readme_excerpts.dart
index eaca7ab8788..e3823aa7e41 100644
--- a/third_party/packages/flutter_svg/example/lib/readme_excerpts.dart
+++ b/third_party/packages/flutter_svg/example/lib/readme_excerpts.dart
@@ -12,9 +12,6 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
-// #docregion PrecompiledAsset
-import 'package:vector_graphics/vector_graphics.dart';
-// #enddocregion PrecompiledAsset
/// Loads an SVG asset.
Widget loadAsset() {
@@ -73,7 +70,7 @@ Widget loadNetworkAssetWithPlaceholder() {
// to sanity-check the structure of the example code.
Widget loadPrecompiledAsset() {
// #docregion PrecompiledAsset
- const Widget svg = SvgPicture(AssetBytesLoader('assets/foo.svg.vec'));
+ final Widget svg = SvgPicture.precompiled('assets/foo.svg.vec');
// #enddocregion PrecompiledAsset
return svg;
}
diff --git a/third_party/packages/flutter_svg/example/pubspec.yaml b/third_party/packages/flutter_svg/example/pubspec.yaml
index ba5d03c85f0..226183aacf8 100644
--- a/third_party/packages/flutter_svg/example/pubspec.yaml
+++ b/third_party/packages/flutter_svg/example/pubspec.yaml
@@ -13,7 +13,6 @@ dependencies:
sdk: flutter
flutter_svg:
path: ../
- vector_graphics: ^1.1.13
dev_dependencies:
flutter_test:
diff --git a/third_party/packages/flutter_svg/lib/svg.dart b/third_party/packages/flutter_svg/lib/svg.dart
index 0e61acfe7d1..a52d7a10669 100644
--- a/third_party/packages/flutter_svg/lib/svg.dart
+++ b/third_party/packages/flutter_svg/lib/svg.dart
@@ -10,7 +10,7 @@ import 'src/loaders.dart';
import 'src/utilities/file.dart';
export 'package:vector_graphics/vector_graphics.dart'
- show BytesLoader, PictureInfo, VectorGraphicUtilities, vg;
+ show AssetBytesLoader, BytesLoader, PictureInfo, VectorGraphicUtilities, vg;
export 'src/cache.dart';
export 'src/default_theme.dart';
@@ -446,6 +446,117 @@ class SvgPicture extends StatelessWidget {
),
colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode);
+ /// Creates a widget that renders precompiled vector graphics bytes from an
+ /// [AssetBundle].
+ ///
+ /// This is a convenience wrapper around `SvgPicture(AssetBytesLoader(...))`,
+ /// allowing callers to pass the path to a `.vec` asset without importing
+ /// `package:vector_graphics/vector_graphics.dart` or manually constructing an
+ /// [AssetBytesLoader].
+ ///
+ /// The asset should be generated by `package:vector_graphics_compiler`. See
+ /// https://pub.dev/packages/flutter_svg#precompiling-and-optimizing-svgs for
+ /// more details on precompiling SVGs.
+ ///
+ /// The key for caching will be derived from the `assetName`, `package`, and
+ /// `bundle` arguments. When providing assets from another package, the
+ /// `package` argument must be non-null.
+ ///
+ /// Either the [width] and [height] arguments should be specified, or the
+ /// widget should be placed in a context that sets tight layout constraints.
+ /// Otherwise, the image dimensions will change as the image is loaded, which
+ /// will result in ugly layout changes.
+ ///
+ /// If `matchTextDirection` is set to true, the picture will be flipped
+ /// horizontally in [TextDirection.rtl] contexts.
+ ///
+ /// The `allowDrawingOutsideViewBox` parameter should be used with caution -
+ /// if set to true, it will not clip the canvas used internally to the view box,
+ /// meaning the picture may draw beyond the intended area and lead to undefined
+ /// behavior or additional memory overhead.
+ ///
+ /// A custom `placeholderBuilder` can be specified for cases where decoding or
+ /// acquiring data may take a noticeably long time.
+ ///
+ /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a
+ /// [ColorFilter] on any [Paint]s created for this drawing.
+ ///
+ /// ## Assets in packages
+ ///
+ /// To create the widget with an asset from a package, the [package] argument
+ /// must be provided. For instance, suppose a package called `my_icons` has
+ /// `icons/heart.svg.vec`.
+ ///
+ /// Then to display the image, use:
+ ///
+ /// ```dart
+ /// SvgPicture.precompiled('icons/heart.svg.vec', package: 'my_icons')
+ /// ```
+ ///
+ /// 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
+ /// is bundled automatically with the app. In particular, assets used by the
+ /// 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
+ /// bundled, the app has to specify which ones to include. For instance a
+ /// package named `fancy_backgrounds` could have:
+ ///
+ /// ```none
+ /// lib/backgrounds/background1.svg.vec
+ /// lib/backgrounds/background2.svg.vec
+ /// lib/backgrounds/background3.svg.vec
+ ///```
+ ///
+ /// To include, say the first image, the `pubspec.yaml` of the app should
+ /// specify it in the assets section:
+ ///
+ /// ```yaml
+ /// assets:
+ /// - packages/fancy_backgrounds/backgrounds/background1.svg.vec
+ /// ```
+ ///
+ /// The `lib/` is implied, so it should not be included in the asset path.
+ ///
+ ///
+ /// See also:
+ ///
+ /// * , an introduction to assets in
+ /// Flutter.
+ ///
+ /// If [excludeFromSemantics] is true, then [semanticsLabel] will be ignored.
+ SvgPicture.precompiled(
+ String assetName, {
+ super.key,
+ this.matchTextDirection = false,
+ AssetBundle? bundle,
+ String? package,
+ this.width,
+ this.height,
+ this.fit = BoxFit.contain,
+ this.alignment = Alignment.center,
+ this.allowDrawingOutsideViewBox = false,
+ this.placeholderBuilder,
+ this.semanticsLabel,
+ this.excludeFromSemantics = false,
+ this.clipBehavior = Clip.hardEdge,
+ this.errorBuilder,
+ ui.ColorFilter? colorFilter,
+ @Deprecated('Use colorFilter instead.') ui.Color? color,
+ @Deprecated('Use colorFilter instead.')
+ ui.BlendMode colorBlendMode = ui.BlendMode.srcIn,
+ @Deprecated('This no longer does anything.') bool cacheColorFilter = false,
+ this.renderingStrategy = RenderingStrategy.picture,
+ }) : bytesLoader = AssetBytesLoader(
+ assetName,
+ packageName: package,
+ assetBundle: bundle,
+ ),
+ colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode);
+
static ColorFilter? _getColorFilter(
ui.Color? color,
ui.BlendMode colorBlendMode,
diff --git a/third_party/packages/flutter_svg/pubspec.yaml b/third_party/packages/flutter_svg/pubspec.yaml
index 152ee9137ea..949d6b8cb6d 100644
--- a/third_party/packages/flutter_svg/pubspec.yaml
+++ b/third_party/packages/flutter_svg/pubspec.yaml
@@ -2,7 +2,7 @@ name: flutter_svg
description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files.
repository: https://github.com/flutter/packages/tree/main/third_party/packages/flutter_svg
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_svg%22
-version: 2.2.1
+version: 2.3.0
environment:
sdk: ^3.7.0
diff --git a/third_party/packages/flutter_svg/test/golden_widget/flutter_logo.precompiled.png b/third_party/packages/flutter_svg/test/golden_widget/flutter_logo.precompiled.png
new file mode 100644
index 00000000000..1aa01eccbbe
Binary files /dev/null and b/third_party/packages/flutter_svg/test/golden_widget/flutter_logo.precompiled.png differ
diff --git a/third_party/packages/flutter_svg/test/widget_svg_test.dart b/third_party/packages/flutter_svg/test/widget_svg_test.dart
index 9cb5e1bba97..cff446b0a5c 100644
--- a/third_party/packages/flutter_svg/test/widget_svg_test.dart
+++ b/third_party/packages/flutter_svg/test/widget_svg_test.dart
@@ -478,6 +478,28 @@ void main() {
await _checkWidgetAndGolden(key, 'flutter_logo.asset.color_mapper.png');
});
+ testWidgets('SvgPicture.precompiled', (WidgetTester tester) async {
+ final FakePrecompiledAssetBundle fakeAsset = FakePrecompiledAssetBundle();
+ final GlobalKey key = GlobalKey();
+ await tester.pumpWidget(
+ Directionality(
+ textDirection: TextDirection.ltr,
+ child: MediaQuery(
+ data: mediaQueryData,
+ child: DefaultAssetBundle(
+ bundle: fakeAsset,
+ child: RepaintBoundary(
+ key: key,
+ child: SvgPicture.precompiled('test.svg'),
+ ),
+ ),
+ ),
+ ),
+ );
+ await tester.pumpAndSettle();
+ await _checkWidgetAndGolden(key, 'flutter_logo.precompiled.png');
+ });
+
testWidgets('SvgPicture.network', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(
@@ -1098,6 +1120,13 @@ class FakeAssetBundle extends Fake implements AssetBundle {
}
}
+class FakePrecompiledAssetBundle extends Fake implements AssetBundle {
+ @override
+ Future load(String key) async {
+ return Uint8List.fromList(_precompiledSvgBytes).buffer.asByteData();
+ }
+}
+
class FakeHttpClient extends Fake implements http.Client {
FakeHttpClient([this.statusCode = 200]);
@@ -1120,6 +1149,18 @@ const String simpleSvg = '''
''';
+/// Precompiled SVG bytes for `svgStr` (Flutter logo).
+///
+/// How to regenerate:
+/// 1. Save `svgStr` to `test/flutter_logo.svg`.
+/// 2. Compile: `dart run vector_graphics_compiler:vector_graphics_compiler -i
+/// test/flutter_logo.svg -o test/flutter_logo.svg.vec`
+/// 3. Encode: `base64 -i test/flutter_logo.svg.vec` (macOS)
+/// 4. Paste the output below and delete the temporary files.
+final Uint8List _precompiledSvgBytes = base64Decode(
+ 'Yi2IAAEpAAAmQwAASkMnAADsCp9CGa0qQx3SpkKykC5DAgAAAAAAJmFhYQICAAAAzcxMPpqZWT8AJwEAAACfQs3MDkPNzPFCzcwOQwIAAAAAAACMYWFhAgIAAADNzEw+mplZPwAc9aVCzAMAAP//HKFHDf8DAQD//xz1pUL/AwIA//8c/////wMDAAAAHP////8DBAABABsBAAAEAAAAAAEBAQgAAAAAzcwWQmbmAEPNzBxBAADKQs3MyEJmZiZBMzMcQ2ZmJkEbAQEABAAAAAABAQEIAAAAMzMcQwAAvELNzMhCAAC8QgAAn0LNzOVCzczWQs3MDkMbAAIABQAAAAABAQEBCgAAAAAAAAAAn0IzsypDzczIQpqZP0MzMxxDmpk/QzMzHEOamT9DzczWQs3MDkMbAAMABQAAAAABAQEDCAAAAAAAAHilTkIC0Q5D7AqfQtPp5UIcw9ZCAtEOQ+wKn0IZrSpDGwAEAAUAAAAAAQEBAwgAAAAAAADsCp9CGa0qQxzD1kIC0Q5DTYreQpq0EkMd0qZCspAuQxsABQADAAAAAAEBBgAAAAAAAJ9CM7MqQ83M8UJmZhxDzczWQs3MDkMwHgAAAAD//x4BAAAA//8eAgABAP//HgMAAgD//x4EAAMA//8eBQAEAP//',
+);
+
const String svgStr = '''