remove single-view assumption from paintImage (#118721)

* remove single-view assumption from paintImage

* dpr

* fix test for web
This commit is contained in:
Michael Goderbauer 2023-01-18 13:22:36 -08:00 committed by GitHub
parent 374f09e1a6
commit ae1cc18c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 6 deletions

View File

@ -3,7 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:developer' as developer; import 'dart:developer' as developer;
import 'dart:ui' as ui show Image; import 'dart:math' as math;
import 'dart:ui' as ui show FlutterView, Image;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
@ -558,13 +559,22 @@ void paintImage({
bool invertedCanvas = false; bool invertedCanvas = false;
// Output size and destination rect are fully calculated. // Output size and destination rect are fully calculated.
if (!kReleaseMode) { if (!kReleaseMode) {
// We can use the devicePixelRatio of the views directly here (instead of
// going through a MediaQuery) because if it changes, whatever is aware of
// the MediaQuery will be repainting the image anyways.
// Furthermore, for the memory check below we just assume that all images
// are decoded for the view with the highest device pixel ratio and use that
// as an upper bound for the display size of the image.
final double maxDevicePixelRatio = PaintingBinding.instance.platformDispatcher.views.fold(
0.0,
(double previousValue, ui.FlutterView view) => math.max(previousValue, view.devicePixelRatio),
);
final ImageSizeInfo sizeInfo = ImageSizeInfo( final ImageSizeInfo sizeInfo = ImageSizeInfo(
// Some ImageProvider implementations may not have given this. // Some ImageProvider implementations may not have given this.
source: debugImageLabel ?? '<Unknown Image(${image.width}×${image.height})>', source: debugImageLabel ?? '<Unknown Image(${image.width}×${image.height})>',
imageSize: Size(image.width.toDouble(), image.height.toDouble()), imageSize: Size(image.width.toDouble(), image.height.toDouble()),
// It's ok to use this instead of a MediaQuery because if this changes, displaySize: outputSize * maxDevicePixelRatio,
// whatever is aware of the MediaQuery will be repainting the image anyway.
displaySize: outputSize * PaintingBinding.instance.window.devicePixelRatio,
); );
assert(() { assert(() {
if (debugInvertOversizedImages && if (debugInvertOversizedImages &&
@ -576,7 +586,8 @@ void paintImage({
exception: 'Image $debugImageLabel has a display size of ' exception: 'Image $debugImageLabel has a display size of '
'$outputWidth×$outputHeight but a decode size of ' '$outputWidth×$outputHeight but a decode size of '
'${image.width}×${image.height}, which uses an additional ' '${image.width}×${image.height}, which uses an additional '
'${overheadInKilobytes}KB.\n\n' '${overheadInKilobytes}KB (assuming a device pixel ratio of '
'$maxDevicePixelRatio).\n\n'
'Consider resizing the asset ahead of time, supplying a cacheWidth ' 'Consider resizing the asset ahead of time, supplying a cacheWidth '
'parameter of $outputWidth, a cacheHeight parameter of ' 'parameter of $outputWidth, a cacheHeight parameter of '
'$outputHeight, or using a ResizeImage.', '$outputHeight, or using a ResizeImage.',

View File

@ -102,7 +102,7 @@ void main() {
expect( expect(
messages.single, messages.single,
'Image TestImage has a display size of 300×150 but a decode size of 300×300, which uses an additional 234KB.\n\n' 'Image TestImage has a display size of 300×150 but a decode size of 300×300, which uses an additional 234KB (assuming a device pixel ratio of ${3.0}).\n\n'
'Consider resizing the asset ahead of time, supplying a cacheWidth parameter of 300, a cacheHeight parameter of 150, or using a ResizeImage.', 'Consider resizing the asset ahead of time, supplying a cacheWidth parameter of 300, a cacheHeight parameter of 150, or using a ResizeImage.',
); );