Take DPR into account for image inversion (#88309)
This commit is contained in:
parent
a562b3cb3d
commit
c91a298249
@ -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.
|
||||
These tests will fail if run without this flag.
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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<String, Object?> toJson() {
|
||||
return <String, Object?>{
|
||||
'source': source,
|
||||
if (displaySize != null)
|
||||
'displaySize': <String, Object?>{
|
||||
'width': displaySize!.width,
|
||||
'height': displaySize!.height,
|
||||
},
|
||||
'displaySize': <String, Object?>{
|
||||
'width': displaySize.width,
|
||||
'height': displaySize.height,
|
||||
},
|
||||
'imageSize': <String, Object?>{
|
||||
'width': imageSize.width,
|
||||
'height': imageSize.height,
|
||||
|
@ -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 ?? '<Unknown Image(${image.width}×${image.height})>',
|
||||
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 '
|
||||
|
@ -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<String> messages = <String>[];
|
||||
@ -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, '<Unknown Image(300×200)>');
|
||||
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;
|
||||
});
|
||||
|
@ -1819,7 +1819,7 @@ void main() {
|
||||
const ImageSizeInfo(
|
||||
source: 'test.png',
|
||||
imageSize: Size(100, 100),
|
||||
displaySize: Size(50, 50),
|
||||
displaySize: Size(150, 150),
|
||||
),
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user