Skip to content
Open
5 changes: 5 additions & 0 deletions third_party/packages/flutter_svg/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
8 changes: 3 additions & 5 deletions third_party/packages/flutter_svg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<?code-excerpt "example/lib/readme_excerpts.dart (PrecompiledAsset)"?>
```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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 0 additions & 1 deletion third_party/packages/flutter_svg/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ dependencies:
sdk: flutter
flutter_svg:
path: ../
vector_graphics: ^1.1.13
Copy link
Contributor Author

@nilsreichardt nilsreichardt Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Not needed anymore


dev_dependencies:
flutter_test:
Expand Down
113 changes: 112 additions & 1 deletion third_party/packages/flutter_svg/lib/svg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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:
///
/// * <https://flutter.io/assets-and-images/>, an introduction to assets in
/// Flutter.
///
/// If [excludeFromSemantics] is true, then [semanticsLabel] will be ignored.
Comment on lines +465 to +530
Copy link
Contributor Author

@nilsreichardt nilsreichardt Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Copied this part from SvgPicture.asset (only changed file names from NAME.svg to NAME.svg.vec).

SvgPicture.precompiled(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you fine with the name precompiled? Or should we choose a different name?

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.')
Comment on lines +548 to +549
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add the @Deprecated parameters to the new constructor, or leave them out?

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,
Expand Down
2 changes: 1 addition & 1 deletion third_party/packages/flutter_svg/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions third_party/packages/flutter_svg/test/widget_svg_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -1098,6 +1120,13 @@ class FakeAssetBundle extends Fake implements AssetBundle {
}
}

class FakePrecompiledAssetBundle extends Fake implements AssetBundle {
@override
Future<ByteData> load(String key) async {
return Uint8List.fromList(_precompiledSvgBytes).buffer.asByteData();
}
}

class FakeHttpClient extends Fake implements http.Client {
FakeHttpClient([this.statusCode = 200]);

Expand All @@ -1120,6 +1149,18 @@ const String simpleSvg = '''
</svg>
''';

/// 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 = '''
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 166 202">
<defs>
Expand Down