From 3bf1aecd86865bba15a895b178db71ec127e9ecc Mon Sep 17 00:00:00 2001 From: Gustl22 Date: Thu, 12 Feb 2026 23:13:46 +0100 Subject: [PATCH 1/2] [vector_graphics] Respect BoxFit parameter with viewbox (closes #158496) --- packages/vector_graphics/CHANGELOG.md | 3 +- .../vector_graphics/lib/src/listener.dart | 2 +- .../lib/src/vector_graphics.dart | 57 ++-- packages/vector_graphics/pubspec.yaml | 2 +- .../goldens/boxfit_contain_with_viewbox.png | Bin 0 -> 6206 bytes .../goldens/boxfit_cover_with_viewbox.png | Bin 0 -> 9676 bytes .../test/goldens/boxfit_fill_with_viewbox.png | Bin 0 -> 11428 bytes .../test/goldens/boxfit_none_with_viewbox.png | Bin 0 -> 5216 bytes .../{ => goldens}/vg_with_image_blank.png | Bin .../test/{ => goldens}/vg_with_image_blue.png | Bin .../test/vector_graphics_test.dart | 258 +++++++++++++++++- 11 files changed, 284 insertions(+), 38 deletions(-) create mode 100644 packages/vector_graphics/test/goldens/boxfit_contain_with_viewbox.png create mode 100644 packages/vector_graphics/test/goldens/boxfit_cover_with_viewbox.png create mode 100644 packages/vector_graphics/test/goldens/boxfit_fill_with_viewbox.png create mode 100644 packages/vector_graphics/test/goldens/boxfit_none_with_viewbox.png rename packages/vector_graphics/test/{ => goldens}/vg_with_image_blank.png (100%) rename packages/vector_graphics/test/{ => goldens}/vg_with_image_blue.png (100%) diff --git a/packages/vector_graphics/CHANGELOG.md b/packages/vector_graphics/CHANGELOG.md index b01cb1ae3c24..a24016e6fa20 100644 --- a/packages/vector_graphics/CHANGELOG.md +++ b/packages/vector_graphics/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 1.1.20 * Updates minimum supported SDK version to Flutter 3.32/Dart 3.8. +* Respect BoxFit parameter when viewbox is specified. ## 1.1.19 diff --git a/packages/vector_graphics/lib/src/listener.dart b/packages/vector_graphics/lib/src/listener.dart index 7f5f2b8fd7ab..cc9e96af8376 100644 --- a/packages/vector_graphics/lib/src/listener.dart +++ b/packages/vector_graphics/lib/src/listener.dart @@ -20,7 +20,7 @@ import 'loader.dart'; const VectorGraphicsCodec _codec = VectorGraphicsCodec(); -/// The deocded result of a vector graphics asset. +/// The decoded result of a vector graphics asset. class PictureInfo { /// Construct a new [PictureInfo]. PictureInfo._(this.picture, this.size); diff --git a/packages/vector_graphics/lib/src/vector_graphics.dart b/packages/vector_graphics/lib/src/vector_graphics.dart index c5a550a6959d..d857b5793df6 100644 --- a/packages/vector_graphics/lib/src/vector_graphics.dart +++ b/packages/vector_graphics/lib/src/vector_graphics.dart @@ -309,7 +309,7 @@ class _PictureKey { } class _VectorGraphicWidgetState extends State { - _PictureData? _pictureInfo; + _PictureData? _pictureData; Object? _error; StackTrace? _stackTrace; Locale? locale; @@ -338,8 +338,8 @@ class _VectorGraphicWidgetState extends State { @override void dispose() { - _maybeReleasePicture(_pictureInfo); - _pictureInfo = null; + _maybeReleasePicture(_pictureData); + _pictureData = null; super.dispose(); } @@ -407,8 +407,8 @@ class _VectorGraphicWidgetState extends State { if (data != null) { data.count += 1; setState(() { - _maybeReleasePicture(_pictureInfo); - _pictureInfo = data; + _maybeReleasePicture(_pictureData); + _pictureData = data; }); return; } @@ -431,8 +431,8 @@ class _VectorGraphicWidgetState extends State { } setState(() { - _maybeReleasePicture(_pictureInfo); - _pictureInfo = data; + _maybeReleasePicture(_pictureData); + _pictureData = data; }); } catch (error, stackTrace) { _handleError(error, stackTrace); @@ -443,7 +443,7 @@ class _VectorGraphicWidgetState extends State { @override Widget build(BuildContext context) { - final PictureInfo? pictureInfo = _pictureInfo?.pictureInfo; + final PictureInfo? pictureInfo = this._pictureData?.pictureInfo; Widget child; if (pictureInfo != null) { @@ -454,34 +454,31 @@ class _VectorGraphicWidgetState extends State { double? width = widget.width; double? height = widget.height; - if (width == null && height == null) { - width = pictureInfo.size.width; - height = pictureInfo.size.height; - } else if (height != null && !pictureInfo.size.isEmpty) { + if (height != null && !pictureInfo.size.isEmpty) { width = height / pictureInfo.size.height * pictureInfo.size.width; } else if (width != null && !pictureInfo.size.isEmpty) { height = width / pictureInfo.size.width * pictureInfo.size.height; } - assert(width != null && height != null); - var scale = 1.0; - scale = math.min( - pictureInfo.size.width / width!, - pictureInfo.size.height / height!, - ); + if (width != null && height != null) { + scale = math.min( + pictureInfo.size.width / width, + pictureInfo.size.height / height, + ); + } if (_webRenderObject) { child = _RawWebVectorGraphicWidget( pictureInfo: pictureInfo, - assetKey: _pictureInfo!.key, + assetKey: this._pictureData!.key, colorFilter: widget.colorFilter, opacity: widget.opacity, ); } else if (widget.strategy == RenderingStrategy.raster) { child = _RawVectorGraphicWidget( pictureInfo: pictureInfo, - assetKey: _pictureInfo!.key, + assetKey: this._pictureData!.key, colorFilter: widget.colorFilter, opacity: widget.opacity, scale: scale, @@ -489,7 +486,7 @@ class _VectorGraphicWidgetState extends State { } else { child = _RawPictureVectorGraphicWidget( pictureInfo: pictureInfo, - assetKey: _pictureInfo!.key, + assetKey: this._pictureData!.key, colorFilter: widget.colorFilter, opacity: widget.opacity, ); @@ -507,16 +504,16 @@ class _VectorGraphicWidgetState extends State { } } - child = SizedBox( - width: width, - height: height, - child: FittedBox( - fit: widget.fit, - alignment: widget.alignment, - clipBehavior: widget.clipBehavior, - child: SizedBox.fromSize(size: pictureInfo.size, child: child), - ), + child = FittedBox( + fit: widget.fit, + alignment: widget.alignment, + clipBehavior: widget.clipBehavior, + child: SizedBox.fromSize(size: pictureInfo.size, child: child), ); + + if (width != null && height != null) { + child = SizedBox(width: width, height: height, child: child); + } } else if (_error != null && widget.errorBuilder != null) { child = widget.errorBuilder!( context, diff --git a/packages/vector_graphics/pubspec.yaml b/packages/vector_graphics/pubspec.yaml index 98bb911fdfa2..3bf9692ed6fa 100644 --- a/packages/vector_graphics/pubspec.yaml +++ b/packages/vector_graphics/pubspec.yaml @@ -2,7 +2,7 @@ name: vector_graphics description: A vector graphics rendering package for Flutter using a binary encoding. repository: https://github.com/flutter/packages/tree/main/packages/vector_graphics issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+vector_graphics%22 -version: 1.1.19 +version: 1.1.20 environment: sdk: ^3.8.0 diff --git a/packages/vector_graphics/test/goldens/boxfit_contain_with_viewbox.png b/packages/vector_graphics/test/goldens/boxfit_contain_with_viewbox.png new file mode 100644 index 0000000000000000000000000000000000000000..3a780ac379f421d87e496bd7aa593b42446fc98f GIT binary patch literal 6206 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

r?@3I{Jb4O*L;$IqF@joL1SdENZjKPL8 zP;T12Mi*Xr`vhi`>{I@xAsc45Rq|${^7z92Jx?RJHgor)iv?33+xlOuhGp2M02cdE z)bg3`viaI?eL(!P= z$sCy;f1-UTEq-o)j`i6VLEp=E@#M+=-4C_1Dv23ZA4TSuj&PJjuvz;;a2I&h#{*Rg zbw2r9ncLlk5o8-_MmTs(usr^w zqat-zhX}T&Cl&KTjhq{6LAovVq}s02>%(5f%B&LNW?FU_)TojIX2wC_5*PVZS=}UYS6FkwdcjUoX z^YN^=3~G~6Lh^F6nQe-p2wKE*{O_jtS6pbyycenK({*n5>=d*#an?TerpM@1p-O46 zX3B3;YIQsD8@+!Ar&{CbN$M@jwR5FQ1(ztLajvt-F#{4aJl0x&fnH;l+f%$=%DYff ztY#O&=_?XM%%(Y+mh8KG;Nh3(nwzV02YCrs5?(>PTK~oSwzB9BU!(p)7c7PcJ@kUk zmn3@B@`z%u!h&JvT2KBrv&y5l16R(OH9k9$(tl!%@4Y(rE{4BI!TN0>2gUJMGVDOd zv(|>?Fw^|7cmWP)l<=vgaXgg`dlMLfjUuw^X4J8Re_Z=QXLSeMH<lmM-x~})Oj<7mww^zp()@mU2ls(BlqqdkniY;SxG&EV zUQfwB0NQGB>^_4t{=RV$zFw}d0D=n2v!7LP!M&Z0ug_fy5R^NdALmAn4ve?mcFI>= zFjP2SLR@C8tN#3VK7#GG2xkKRdj(*t1{naP3$g-=jnN_iRImX2y7@n*!9UMG4E&!M c=gBC>*t+r}6)dsc3SZb%#{va*GOj|-Ume|_S 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 V%FLrF{&)ESF}!JZgRF;n{9oUJN4@|6 literal 0 HcmV?d00001 diff --git a/packages/vector_graphics/test/goldens/boxfit_fill_with_viewbox.png b/packages/vector_graphics/test/goldens/boxfit_fill_with_viewbox.png new file mode 100644 index 0000000000000000000000000000000000000000..67a2186b136534907e481259a62e5f4f46b7d5c2 GIT binary patch literal 11428 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 ZX=J>re{7t8D1^1(4K4jYORm{H{vUX_L>>SD literal 0 HcmV?d00001 diff --git a/packages/vector_graphics/test/goldens/boxfit_none_with_viewbox.png b/packages/vector_graphics/test/goldens/boxfit_none_with_viewbox.png new file mode 100644 index 0000000000000000000000000000000000000000..367b8a1ffa9dd764f4dcfc589b019d0a4a30c829 GIT binary patch literal 5216 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 literal 0 HcmV?d00001 diff --git a/packages/vector_graphics/test/vg_with_image_blank.png b/packages/vector_graphics/test/goldens/vg_with_image_blank.png similarity index 100% rename from packages/vector_graphics/test/vg_with_image_blank.png rename to packages/vector_graphics/test/goldens/vg_with_image_blank.png diff --git a/packages/vector_graphics/test/vg_with_image_blue.png b/packages/vector_graphics/test/goldens/vg_with_image_blue.png similarity index 100% rename from packages/vector_graphics/test/vg_with_image_blue.png rename to packages/vector_graphics/test/goldens/vg_with_image_blue.png diff --git a/packages/vector_graphics/test/vector_graphics_test.dart b/packages/vector_graphics/test/vector_graphics_test.dart index b046ad3a4955..e7d0933acfe2 100644 --- a/packages/vector_graphics/test/vector_graphics_test.dart +++ b/packages/vector_graphics/test/vector_graphics_test.dart @@ -12,6 +12,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:vector_graphics/src/listener.dart'; import 'package:vector_graphics/src/vector_graphics.dart'; import 'package:vector_graphics_codec/vector_graphics_codec.dart'; +import 'package:vector_graphics_compiler/vector_graphics_compiler.dart' + show encodeSvg; const VectorGraphicsCodec codec = VectorGraphicsCodec(); @@ -159,6 +161,229 @@ void main() { expect(fittedBox.clipBehavior, Clip.hardEdge); }); + group('BoxFit', () { + Future<(RenderBox, RenderBox)> setupBoxFitVectorGraphic( + WidgetTester tester, { + required BoxFit fit, + }) async { + final buffer = VectorGraphicsBuffer(); + codec.writeSize(buffer, 100, 50); + + await tester.pumpWidget( + RepaintBoundary( + child: Center( + child: SizedBox( + width: 200, + height: 200, + child: VectorGraphic( + fit: fit, + loader: TestBytesLoader(buffer.done()), + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + final RenderProxyBox outsideBox = tester.renderObject( + find.byType(VectorGraphic), + ); + expect(outsideBox.size, const Size(200, 200)); + + final RenderBox insideBox = tester.renderObject( + find.byType(SizedBox).last, + ); + expect(insideBox.size, const Size(100, 50)); + + return (outsideBox, insideBox); + } + + testWidgets( + 'Scale on BoxFit.contain without constraints, but with viewbox', + (WidgetTester tester) async { + final (RenderBox outsideBox, RenderBox insideBox) = + await setupBoxFitVectorGraphic(tester, fit: BoxFit.contain); + + // Top left point as offset in child space + final Offset insidePoint = insideBox.localToGlobal(Offset.zero); + // Top left point as offset in parent space + final Offset outsidePoint = outsideBox.localToGlobal( + const Offset(0, 50), + ); + + expect(insidePoint, equals(outsidePoint)); + }, + ); + + testWidgets('Scale on BoxFit.cover without constraints, but with viewbox', ( + WidgetTester tester, + ) async { + final (RenderBox outsideBox, RenderBox insideBox) = + await setupBoxFitVectorGraphic(tester, fit: BoxFit.cover); + + // Top left point as offset in child space + final Offset insidePoint = insideBox.localToGlobal(Offset.zero); + // Top left point as offset in parent space + final Offset outsidePoint = outsideBox.localToGlobal( + const Offset(-100, 0), + ); + + expect(insidePoint, equals(outsidePoint)); + }); + + testWidgets('Scale on BoxFit.fill without constraints, but with viewbox', ( + WidgetTester tester, + ) async { + final (RenderBox outsideBox, RenderBox insideBox) = + await setupBoxFitVectorGraphic(tester, fit: BoxFit.fill); + + // Top left point as offset in child space + final Offset insidePoint = insideBox.localToGlobal(Offset.zero); + // Top left point as offset in parent space + final Offset outsidePoint = outsideBox.localToGlobal(Offset.zero); + + expect(insidePoint, equals(outsidePoint)); + }); + }); + + // TODO(gustl22): can be removed if redundant + group('BoxFit Goldens', () { + late ByteData vectorGraphicBuffer; + + setUpAll(() async { + final Uint8List bytes = encodeSvg( + xml: svgString, + debugName: 'test', + enableClippingOptimizer: false, + enableMaskingOptimizer: false, + enableOverdrawOptimizer: false, + ); + vectorGraphicBuffer = bytes.buffer.asByteData(); + }); + + testWidgets( + 'Scale on BoxFit.contain without constraints, but with viewbox', + (WidgetTester tester) async { + final goldenKey = UniqueKey(); + final vectorGraphic = UniqueKey(); + await tester.pumpWidget( + RepaintBoundary( + key: goldenKey, + child: Center( + child: Container( + width: 400, + height: 200, + color: Colors.white, + child: VectorGraphic( + key: vectorGraphic, + loader: TestBytesLoader(vectorGraphicBuffer), + // ignore: avoid_redundant_argument_values + fit: BoxFit.contain, + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + await expectLater( + find.byKey(goldenKey), + matchesGoldenFile('goldens/boxfit_contain_with_viewbox.png'), + ); + }, + ); + + testWidgets('Scale on BoxFit.cover without constraints, but with viewbox', ( + WidgetTester tester, + ) async { + final goldenKey = UniqueKey(); + final vectorGraphic = UniqueKey(); + await tester.pumpWidget( + RepaintBoundary( + key: goldenKey, + child: Center( + child: Container( + width: 400, + height: 200, + color: Colors.white, + child: VectorGraphic( + key: vectorGraphic, + loader: TestBytesLoader(vectorGraphicBuffer), + fit: BoxFit.cover, + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + await expectLater( + find.byKey(goldenKey), + matchesGoldenFile('goldens/boxfit_cover_with_viewbox.png'), + ); + }); + + testWidgets('Scale on BoxFit.fill without constraints, but with viewbox', ( + WidgetTester tester, + ) async { + final goldenKey = UniqueKey(); + final vectorGraphic = UniqueKey(); + await tester.pumpWidget( + RepaintBoundary( + key: goldenKey, + child: Center( + child: Container( + width: 400, + height: 200, + color: Colors.white, + child: VectorGraphic( + key: vectorGraphic, + loader: TestBytesLoader(vectorGraphicBuffer), + fit: BoxFit.fill, + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + await expectLater( + find.byKey(goldenKey), + matchesGoldenFile('goldens/boxfit_fill_with_viewbox.png'), + ); + }); + + testWidgets('Scale on BoxFit.none without constraints, but with viewbox', ( + WidgetTester tester, + ) async { + final goldenKey = UniqueKey(); + final vectorGraphic = UniqueKey(); + await tester.pumpWidget( + RepaintBoundary( + key: goldenKey, + child: Center( + child: Container( + width: 400, + height: 400, + color: Colors.white, + child: VectorGraphic( + key: vectorGraphic, + loader: TestBytesLoader(vectorGraphicBuffer), + fit: BoxFit.none, + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + await expectLater( + find.byKey(goldenKey), + matchesGoldenFile('goldens/boxfit_none_with_viewbox.png'), + ); + }); + }); + group('ClipBehavior', () { testWidgets('Sets clipBehavior to hardEdge if not provided', ( WidgetTester tester, @@ -209,9 +434,9 @@ void main() { ); await tester.pumpAndSettle(); - expect(find.byType(SizedBox), findsNWidgets(2)); + expect(find.byType(SizedBox), findsNWidgets(1)); - final sizedBox = find.byType(SizedBox).evaluate().last.widget as SizedBox; + final sizedBox = find.byType(SizedBox).evaluate().single.widget as SizedBox; expect(sizedBox.width, 100); expect(sizedBox.height, 200); @@ -601,7 +826,7 @@ void main() { // A blank image, because the image hasn't loaded yet. await expectLater( find.byKey(key), - matchesGoldenFile('vg_with_image_blank.png'), + matchesGoldenFile('goldens/vg_with_image_blank.png'), ); expect(imageCache.currentSize, 1); @@ -615,10 +840,10 @@ void main() { expect(imageCache.statusForKey(imageKey).live, false); expect(imageCache.statusForKey(imageKey).keepAlive, true); - // A blue square, becuase the image is available now. + // A blue square, because the image is available now. await expectLater( find.byKey(key), - matchesGoldenFile('vg_with_image_blue.png'), + matchesGoldenFile('goldens/vg_with_image_blue.png'), ); }, skip: kIsWeb); @@ -787,3 +1012,26 @@ class ThrowingBytesLoader extends BytesLoader { throw UnimplementedError('Test exception'); } } + +const String svgString = ''' + + + + + + + + + + + + + + + + + + + + +'''; From baa096ad5a3695acd8f84d82535c1f25ac639eb4 Mon Sep 17 00:00:00 2001 From: Gustl22 Date: Thu, 12 Feb 2026 23:22:52 +0100 Subject: [PATCH 2/2] remove this param --- packages/vector_graphics/lib/src/vector_graphics.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vector_graphics/lib/src/vector_graphics.dart b/packages/vector_graphics/lib/src/vector_graphics.dart index d857b5793df6..c35cf0812dea 100644 --- a/packages/vector_graphics/lib/src/vector_graphics.dart +++ b/packages/vector_graphics/lib/src/vector_graphics.dart @@ -443,7 +443,7 @@ class _VectorGraphicWidgetState extends State { @override Widget build(BuildContext context) { - final PictureInfo? pictureInfo = this._pictureData?.pictureInfo; + final PictureInfo? pictureInfo = _pictureData?.pictureInfo; Widget child; if (pictureInfo != null) { @@ -471,14 +471,14 @@ class _VectorGraphicWidgetState extends State { if (_webRenderObject) { child = _RawWebVectorGraphicWidget( pictureInfo: pictureInfo, - assetKey: this._pictureData!.key, + assetKey: _pictureData!.key, colorFilter: widget.colorFilter, opacity: widget.opacity, ); } else if (widget.strategy == RenderingStrategy.raster) { child = _RawVectorGraphicWidget( pictureInfo: pictureInfo, - assetKey: this._pictureData!.key, + assetKey: _pictureData!.key, colorFilter: widget.colorFilter, opacity: widget.opacity, scale: scale, @@ -486,7 +486,7 @@ class _VectorGraphicWidgetState extends State { } else { child = _RawPictureVectorGraphicWidget( pictureInfo: pictureInfo, - assetKey: this._pictureData!.key, + assetKey: _pictureData!.key, colorFilter: widget.colorFilter, opacity: widget.opacity, );