diff --git a/dev/tracing_tests/README.md b/dev/tracing_tests/README.md index 73d37f569f..9801c10592 100644 --- a/dev/tracing_tests/README.md +++ b/dev/tracing_tests/README.md @@ -4,4 +4,4 @@ The tests in this folder must be run with `flutter test --enable-vmservice`, since they test that trace data is written to the timeline by connecting to the observatory. -These tests will fail if run without this flag. \ No newline at end of file +These tests will fail if run without this flag. diff --git a/dev/tracing_tests/test/image_painting_event_test.dart b/dev/tracing_tests/test/image_painting_event_test.dart index 3a6df60a68..6be6d54371 100644 --- a/dev/tracing_tests/test/image_painting_event_test.dart +++ b/dev/tracing_tests/test/image_painting_event_test.dart @@ -72,7 +72,7 @@ void main() { expect(event.extensionKind, 'Flutter.ImageSizesForFrame'); expect( jsonEncode(event.extensionData!.data), - '{"test.png":{"source":"test.png","displaySize":{"width":200.0,"height":100.0},"imageSize":{"width":300.0,"height":300.0},"displaySizeInBytes":106666,"decodedSizeInBytes":480000}}', + '{"test.png":{"source":"test.png","displaySize":{"width":600.0,"height":300.0},"imageSize":{"width":300.0,"height":300.0},"displaySizeInBytes":960000,"decodedSizeInBytes":480000}}', ); }, skip: isBrowser); // [intended] uses dart:isolate and io. @@ -104,7 +104,7 @@ void main() { expect(event.extensionKind, 'Flutter.ImageSizesForFrame'); expect( jsonEncode(event.extensionData!.data), - '{"test.png":{"source":"test.png","displaySize":{"width":300.0,"height":300.0},"imageSize":{"width":300.0,"height":300.0},"displaySizeInBytes":480000,"decodedSizeInBytes":480000}}', + '{"test.png":{"source":"test.png","displaySize":{"width":900.0,"height":900.0},"imageSize":{"width":300.0,"height":300.0},"displaySizeInBytes":4320000,"decodedSizeInBytes":480000}}', ); }, skip: isBrowser); // [intended] uses dart:isolate and io. } diff --git a/packages/flutter/lib/src/painting/debug.dart b/packages/flutter/lib/src/painting/debug.dart index c8fbcbba9a..d8eba7ece5 100644 --- a/packages/flutter/lib/src/painting/debug.dart +++ b/packages/flutter/lib/src/painting/debug.dart @@ -54,20 +54,20 @@ class ImageSizeInfo { /// This class is used by the framework when it paints an image to a canvas /// to report to `dart:developer`'s [postEvent], as well as to the /// [debugOnPaintImage] callback if it is set. - const ImageSizeInfo({this.source, this.displaySize, required this.imageSize}); + const ImageSizeInfo({this.source, required this.displaySize, required this.imageSize}); /// A unique identifier for this image, for example its asset path or network /// URL. final String? source; /// The size of the area the image will be rendered in. - final Size? displaySize; + final Size displaySize; /// The size the image has been decoded to. final Size imageSize; /// The number of bytes needed to render the image without scaling it. - int get displaySizeInBytes => _sizeToBytes(displaySize!); + int get displaySizeInBytes => _sizeToBytes(displaySize); /// The number of bytes used by the image in memory. int get decodedSizeInBytes => _sizeToBytes(imageSize); @@ -82,11 +82,10 @@ class ImageSizeInfo { Map toJson() { return { 'source': source, - if (displaySize != null) - 'displaySize': { - 'width': displaySize!.width, - 'height': displaySize!.height, - }, + 'displaySize': { + 'width': displaySize.width, + 'height': displaySize.height, + }, 'imageSize': { 'width': imageSize.width, 'height': imageSize.height, diff --git a/packages/flutter/lib/src/painting/decoration_image.dart b/packages/flutter/lib/src/painting/decoration_image.dart index a7b1600071..56a356290c 100644 --- a/packages/flutter/lib/src/painting/decoration_image.dart +++ b/packages/flutter/lib/src/painting/decoration_image.dart @@ -11,6 +11,7 @@ import 'package:flutter/scheduler.dart'; import 'alignment.dart'; import 'basic_types.dart'; +import 'binding.dart'; import 'borders.dart'; import 'box_fit.dart'; import 'debug.dart'; @@ -494,14 +495,16 @@ void paintImage({ // Some ImageProvider implementations may not have given this. source: debugImageLabel ?? '', imageSize: Size(image.width.toDouble(), image.height.toDouble()), - displaySize: outputSize, + // It's ok to use this instead of a MediaQuery because if this changes, + // whatever is aware of the MediaQuery will be repainting the image anyway. + displaySize: outputSize * PaintingBinding.instance!.window.devicePixelRatio, ); assert(() { if (debugInvertOversizedImages && sizeInfo.decodedSizeInBytes > sizeInfo.displaySizeInBytes + debugImageOverheadAllowance) { final int overheadInKilobytes = (sizeInfo.decodedSizeInBytes - sizeInfo.displaySizeInBytes) ~/ 1024; - final int outputWidth = outputSize.width.toInt(); - final int outputHeight = outputSize.height.toInt(); + final int outputWidth = sizeInfo.displaySize.width.toInt(); + final int outputHeight = sizeInfo.displaySize.height.toInt(); FlutterError.reportError(FlutterErrorDetails( exception: 'Image $debugImageLabel has a display size of ' '$outputWidth×$outputHeight but a decode size of ' diff --git a/packages/flutter/test/painting/paint_image_test.dart b/packages/flutter/test/painting/paint_image_test.dart index f28ebc1ef9..7dde91751a 100644 --- a/packages/flutter/test/painting/paint_image_test.dart +++ b/packages/flutter/test/painting/paint_image_test.dart @@ -5,6 +5,7 @@ import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -52,6 +53,7 @@ void main() { test('debugInvertOversizedImages', () async { debugInvertOversizedImages = true; + expect(PaintingBinding.instance!.window.devicePixelRatio != 1.0, true); final FlutterExceptionHandler? oldFlutterError = FlutterError.onError; final List messages = []; @@ -60,7 +62,7 @@ void main() { }; final TestCanvas canvas = TestCanvas(); - const Rect rect = Rect.fromLTWH(50.0, 50.0, 200.0, 100.0); + const Rect rect = Rect.fromLTWH(50.0, 50.0, 100.0, 50.0); paintImage( canvas: canvas, @@ -88,7 +90,7 @@ void main() { ); expect(commands[1].memberName, #translate); expect(commands[1].positionalArguments[0], 0.0); - expect(commands[1].positionalArguments[1], 100.0); + expect(commands[1].positionalArguments[1], 75.0); expect(commands[2].memberName, #scale); expect(commands[2].positionalArguments[0], 1.0); @@ -97,12 +99,12 @@ void main() { expect(commands[3].memberName, #translate); expect(commands[3].positionalArguments[0], 0.0); - expect(commands[3].positionalArguments[1], -100.0); + expect(commands[3].positionalArguments[1], -75.0); expect( messages.single, - 'Image TestImage has a display size of 200×100 but a decode size of 300×300, which uses an additional 364KB.\n\n' - 'Consider resizing the asset ahead of time, supplying a cacheWidth parameter of 200, a cacheHeight parameter of 100, or using a ResizeImage.', + 'Image TestImage has a display size of 300×150 but a decode size of 300×300, which uses an additional 234KB.\n\n' + 'Consider resizing the asset ahead of time, supplying a cacheWidth parameter of 300, a cacheHeight parameter of 150, or using a ResizeImage.', ); debugInvertOversizedImages = false; @@ -179,7 +181,7 @@ void main() { expect(imageSizeInfo, isNotNull); expect(imageSizeInfo.source, 'test.png'); expect(imageSizeInfo.imageSize, const Size(300, 300)); - expect(imageSizeInfo.displaySize, const Size(200, 100)); + expect(imageSizeInfo.displaySize, const Size(200, 100) * PaintingBinding.instance!.window.devicePixelRatio); // Make sure that we don't report an identical image size info if we // redraw in the next frame. @@ -218,7 +220,7 @@ void main() { expect(imageSizeInfo, isNotNull); expect(imageSizeInfo.source, 'test.png'); expect(imageSizeInfo.imageSize, const Size(300, 300)); - expect(imageSizeInfo.displaySize, const Size(200, 100)); + expect(imageSizeInfo.displaySize, const Size(200, 100) * PaintingBinding.instance!.window.devicePixelRatio); // Make sure that we don't report an identical image size info if we // redraw in the next frame. @@ -236,7 +238,7 @@ void main() { expect(imageSizeInfo, isNotNull); expect(imageSizeInfo.source, 'test.png'); expect(imageSizeInfo.imageSize, const Size(300, 300)); - expect(imageSizeInfo.displaySize, const Size(200, 150)); + expect(imageSizeInfo.displaySize, const Size(200, 150) * PaintingBinding.instance!.window.devicePixelRatio); debugOnPaintImage = null; }); @@ -260,7 +262,7 @@ void main() { expect(imageSizeInfo, isNotNull); expect(imageSizeInfo.source, ''); expect(imageSizeInfo.imageSize, const Size(300, 200)); - expect(imageSizeInfo.displaySize, const Size(200, 100)); + expect(imageSizeInfo.displaySize, const Size(200, 100) * PaintingBinding.instance!.window.devicePixelRatio); debugOnPaintImage = null; }); diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index c53e5f9b82..b033eca026 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -1819,7 +1819,7 @@ void main() { const ImageSizeInfo( source: 'test.png', imageSize: Size(100, 100), - displaySize: Size(50, 50), + displaySize: Size(150, 150), ), );