Skip to content

Commit f0da9b2

Browse files
committed
[flutter_svg] Add rendering strategy to flutter_svg used to balance flexibility and performance.
1 parent 2bac766 commit f0da9b2

File tree

5 files changed

+134
-5
lines changed

5 files changed

+134
-5
lines changed

third_party/packages/flutter_svg/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6.
44

5+
## 2.2.0
6+
7+
* Exposes `renderingStrategy` in `SvgPicture` constructors.
8+
59
## 2.1.0
610

711
* Exposes `colorMapper` in `SvgPicture` constructors.

third_party/packages/flutter_svg/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,12 @@ import 'dart:ui' as ui;
130130
```
131131

132132
The `SvgPicture` helps to automate this logic, and it provides some convenience
133-
wrappers for getting assets from multiple sources. Unlike the `vector_graphics`
134-
package, this package _does not render the data to an `Image` at any point_.
135-
This carries a performance penalty for some common use cases, but also allows
136-
for more flexibility around scaling.
133+
wrappers for getting assets from multiple sources.
134+
135+
This package now supports a render strategy setting, allowing certain applications to achieve better performance when needed.
136+
By default, the rendering uses the original `picture` mode, which retains full flexibility in scaling.
137+
Alternatively, when using the `raster` strategy, the SVG data is rendered into an `Image`, which is then drawn using drawImage.
138+
This approach may sacrifice some flexibility—especially around resolution scaling—but can significantly improve rendering performance in specific use cases.
137139

138140
## Precompiling and Optimizing SVGs
139141

third_party/packages/flutter_svg/lib/svg.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class SvgPicture extends StatelessWidget {
100100
'The SVG theme must be set on the bytesLoader.')
101101
SvgTheme? theme,
102102
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
103+
this.renderingStrategy = RenderingStrategy.picture,
103104
});
104105

105106
/// Instantiates a widget that renders an SVG picture from an [AssetBundle].
@@ -201,6 +202,7 @@ class SvgPicture extends StatelessWidget {
201202
@Deprecated('Use colorFilter instead.')
202203
ui.BlendMode colorBlendMode = ui.BlendMode.srcIn,
203204
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
205+
this.renderingStrategy = RenderingStrategy.picture,
204206
}) : bytesLoader = SvgAssetLoader(
205207
assetName,
206208
packageName: package,
@@ -265,6 +267,7 @@ class SvgPicture extends StatelessWidget {
265267
SvgTheme? theme,
266268
ColorMapper? colorMapper,
267269
http.Client? httpClient,
270+
this.renderingStrategy = RenderingStrategy.picture,
268271
}) : bytesLoader = SvgNetworkLoader(
269272
url,
270273
headers: headers,
@@ -325,6 +328,7 @@ class SvgPicture extends StatelessWidget {
325328
SvgTheme? theme,
326329
ColorMapper? colorMapper,
327330
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
331+
this.renderingStrategy = RenderingStrategy.picture,
328332
}) : bytesLoader = SvgFileLoader(
329333
file,
330334
theme: theme,
@@ -380,6 +384,7 @@ class SvgPicture extends StatelessWidget {
380384
SvgTheme? theme,
381385
ColorMapper? colorMapper,
382386
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
387+
this.renderingStrategy = RenderingStrategy.picture,
383388
}) : bytesLoader = SvgBytesLoader(
384389
bytes,
385390
theme: theme,
@@ -435,6 +440,7 @@ class SvgPicture extends StatelessWidget {
435440
SvgTheme? theme,
436441
ColorMapper? colorMapper,
437442
@Deprecated('This no longer does anything.') bool cacheColorFilter = false,
443+
this.renderingStrategy = RenderingStrategy.picture,
438444
}) : bytesLoader = SvgStringLoader(
439445
string,
440446
theme: theme,
@@ -526,6 +532,14 @@ class SvgPicture extends StatelessWidget {
526532
/// The color filter, if any, to apply to this widget.
527533
final ColorFilter? colorFilter;
528534

535+
/// Widget rendering strategy used to balance flexibility and performance.
536+
///
537+
/// See the enum [RenderingStrategy] for details of all possible options and their common
538+
/// use cases.
539+
///
540+
/// Defaults to [RenderingStrategy.picture].
541+
final RenderingStrategy renderingStrategy;
542+
529543
@override
530544
Widget build(BuildContext context) {
531545
return createCompatVectorGraphic(
@@ -540,6 +554,7 @@ class SvgPicture extends StatelessWidget {
540554
errorBuilder: errorBuilder,
541555
colorFilter: colorFilter,
542556
placeholderBuilder: placeholderBuilder,
557+
strategy: renderingStrategy,
543558
clipViewbox: !allowDrawingOutsideViewBox,
544559
matchTextDirection: matchTextDirection,
545560
);

third_party/packages/flutter_svg/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: flutter_svg
22
description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files.
33
repository: https://github.com/flutter/packages/tree/main/third_party/packages/flutter_svg
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_svg%22
5-
version: 2.1.0
5+
version: 2.2.0
66

77
environment:
88
sdk: ^3.6.0

third_party/packages/flutter_svg/test/widget_svg_test.dart

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:flutter_svg/flutter_svg.dart';
77

88
import 'package:flutter_test/flutter_test.dart';
99
import 'package:http/http.dart' as http;
10+
import 'package:vector_graphics/vector_graphics_compat.dart';
1011

1112
class _TolerantComparator extends LocalFileComparator {
1213
_TolerantComparator(super.testFile);
@@ -139,6 +140,28 @@ void main() {
139140
await _checkWidgetAndGolden(key, 'flutter_logo.string.png');
140141
});
141142

143+
testWidgets('SvgPicture.string with renderingStrategy',
144+
(WidgetTester tester) async {
145+
final GlobalKey key = GlobalKey();
146+
await tester.pumpWidget(
147+
MediaQuery(
148+
data: mediaQueryData,
149+
child: RepaintBoundary(
150+
key: key,
151+
child: SvgPicture.string(
152+
svgStr,
153+
width: 100.0,
154+
height: 100.0,
155+
renderingStrategy: RenderingStrategy.raster,
156+
),
157+
),
158+
),
159+
);
160+
161+
await tester.pumpAndSettle();
162+
await _checkWidgetAndGolden(key, 'flutter_logo.string.png');
163+
});
164+
142165
testWidgets('SvgPicture.string with colorMapper',
143166
(WidgetTester tester) async {
144167
final GlobalKey key = GlobalKey();
@@ -295,6 +318,25 @@ void main() {
295318
await _checkWidgetAndGolden(key, 'flutter_logo.memory.png');
296319
});
297320

321+
testWidgets('SvgPicture.memory with strategy', (WidgetTester tester) async {
322+
final GlobalKey key = GlobalKey();
323+
await tester.pumpWidget(
324+
MediaQuery(
325+
data: mediaQueryData,
326+
child: RepaintBoundary(
327+
key: key,
328+
child: SvgPicture.memory(
329+
svgBytes,
330+
renderingStrategy: RenderingStrategy.raster,
331+
),
332+
),
333+
),
334+
);
335+
await tester.pumpAndSettle();
336+
337+
await _checkWidgetAndGolden(key, 'flutter_logo.memory.png');
338+
});
339+
298340
testWidgets('SvgPicture.memory with colorMapper',
299341
(WidgetTester tester) async {
300342
final GlobalKey key = GlobalKey();
@@ -334,6 +376,26 @@ void main() {
334376
await _checkWidgetAndGolden(key, 'flutter_logo.asset.png');
335377
});
336378

379+
testWidgets('SvgPicture.asset with strategy', (WidgetTester tester) async {
380+
final FakeAssetBundle fakeAsset = FakeAssetBundle();
381+
final GlobalKey key = GlobalKey();
382+
await tester.pumpWidget(
383+
MediaQuery(
384+
data: mediaQueryData,
385+
child: RepaintBoundary(
386+
key: key,
387+
child: SvgPicture.asset(
388+
'test.svg',
389+
bundle: fakeAsset,
390+
renderingStrategy: RenderingStrategy.raster,
391+
),
392+
),
393+
),
394+
);
395+
await tester.pumpAndSettle();
396+
await _checkWidgetAndGolden(key, 'flutter_logo.asset.png');
397+
});
398+
337399
testWidgets('SvgPicture.asset with colorMapper', (WidgetTester tester) async {
338400
final FakeAssetBundle fakeAsset = FakeAssetBundle();
339401
final GlobalKey key = GlobalKey();
@@ -380,6 +442,33 @@ void main() {
380442
await _checkWidgetAndGolden(key, 'flutter_logo.asset.png');
381443
});
382444

445+
testWidgets('SvgPicture.asset DefaultAssetBundle with strategy',
446+
(WidgetTester tester) async {
447+
final FakeAssetBundle fakeAsset = FakeAssetBundle();
448+
final GlobalKey key = GlobalKey();
449+
await tester.pumpWidget(
450+
Directionality(
451+
textDirection: TextDirection.ltr,
452+
child: MediaQuery(
453+
data: mediaQueryData,
454+
child: DefaultAssetBundle(
455+
bundle: fakeAsset,
456+
child: RepaintBoundary(
457+
key: key,
458+
child: SvgPicture.asset(
459+
'test.svg',
460+
semanticsLabel: 'Test SVG',
461+
renderingStrategy: RenderingStrategy.raster,
462+
),
463+
),
464+
),
465+
),
466+
),
467+
);
468+
await tester.pumpAndSettle();
469+
await _checkWidgetAndGolden(key, 'flutter_logo.asset.png');
470+
});
471+
383472
testWidgets('SvgPicture.asset DefaultAssetBundle with colorMapper',
384473
(WidgetTester tester) async {
385474
final FakeAssetBundle fakeAsset = FakeAssetBundle();
@@ -425,6 +514,25 @@ void main() {
425514
await _checkWidgetAndGolden(key, 'flutter_logo.network.png');
426515
});
427516

517+
testWidgets('SvgPicture.network with strategy', (WidgetTester tester) async {
518+
final GlobalKey key = GlobalKey();
519+
await tester.pumpWidget(
520+
MediaQuery(
521+
data: mediaQueryData,
522+
child: RepaintBoundary(
523+
key: key,
524+
child: SvgPicture.network(
525+
'test.svg',
526+
httpClient: FakeHttpClient(),
527+
renderingStrategy: RenderingStrategy.raster,
528+
),
529+
),
530+
),
531+
);
532+
await tester.pumpAndSettle();
533+
await _checkWidgetAndGolden(key, 'flutter_logo.network.png');
534+
});
535+
428536
testWidgets('SvgPicture.network with colorMapper',
429537
(WidgetTester tester) async {
430538
final GlobalKey key = GlobalKey();

0 commit comments

Comments
 (0)