Unverified Commit 1970bc91 authored by alanwutang11's avatar alanwutang11 Committed by GitHub

cacheWidth cacheHeight support for canvaskit on web (#117423)

* cacheWidth cacheHeight support for web canvaskit

* comments

* clarifying comment for loadTestImageProvider class
Co-authored-by: 's avataralanwutang11 <alpwu@google.com>
parent 2a502363
...@@ -1182,6 +1182,11 @@ Future<void> _runWebLongRunningTests() async { ...@@ -1182,6 +1182,11 @@ Future<void> _runWebLongRunningTests() async {
() => _runWebE2eTest('capabilities_integration_canvaskit', buildMode: 'profile', renderer: 'canvaskit'), () => _runWebE2eTest('capabilities_integration_canvaskit', buildMode: 'profile', renderer: 'canvaskit'),
() => _runWebE2eTest('capabilities_integration_html', buildMode: 'release', renderer: 'html'), () => _runWebE2eTest('capabilities_integration_html', buildMode: 'release', renderer: 'html'),
// This test doesn't do anything interesting w.r.t. rendering, so we don't run the full build mode x renderer matrix.
// CacheWidth and CacheHeight are only currently supported in CanvasKit mode, so we don't run the test in HTML mode.
() => _runWebE2eTest('cache_width_cache_height_integration', buildMode: 'debug', renderer: 'auto'),
() => _runWebE2eTest('cache_width_cache_height_integration', buildMode: 'profile', renderer: 'canvaskit'),
() => _runWebTreeshakeTest(), () => _runWebTreeshakeTest(),
() => _runFlutterDriverWebTest( () => _runFlutterDriverWebTest(
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
// This class allows loadBuffer, a protected method, to be called with a custom
// DecoderBufferCallback function.
class LoadTestImageProvider extends ImageProvider<Object> {
LoadTestImageProvider(this.provider);
final ImageProvider provider;
ImageStreamCompleter testLoad(Object key, DecoderBufferCallback decode) {
return provider.loadBuffer(key, decode);
}
@override
Future<Object> obtainKey(ImageConfiguration configuration) {
throw UnimplementedError();
}
@override
ImageStreamCompleter loadBuffer(Object key, DecoderBufferCallback decode) {
throw UnimplementedError();
}
}
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Image.network uses cacheWidth and cacheHeight', (WidgetTester tester) async {
const int expectedCacheHeight = 9;
const int expectedCacheWidth = 11;
await tester.pumpAndSettle();
final Image image = Image.network(
'assets/packages/flutter_gallery_assets/assets/icons/material/material.png',
cacheHeight: 9,
cacheWidth: 11,
);
bool called = false;
Future<ui.Codec> decode(ui.ImmutableBuffer buffer, {int? cacheWidth, int? cacheHeight, bool allowUpscaling = false}) {
expect(cacheHeight, expectedCacheHeight);
expect(cacheWidth, expectedCacheWidth);
expect(allowUpscaling, false);
called = true;
return PaintingBinding.instance.instantiateImageCodecFromBuffer(buffer, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling);
}
final ImageProvider resizeImage = image.image;
expect(image.image, isA<ResizeImage>());
final LoadTestImageProvider testProvider = LoadTestImageProvider(image.image);
final ImageStreamCompleter streamCompleter = testProvider.testLoad(await resizeImage.obtainKey(ImageConfiguration.empty), decode);
final Completer<void> completer = Completer<void>();
int? imageInfoCachedWidth;
int? imageInfoCachedHeight;
streamCompleter.addListener(ImageStreamListener((ImageInfo imageInfo, bool syncCall) {
imageInfoCachedWidth = imageInfo.image.width;
imageInfoCachedHeight = imageInfo.image.height;
completer.complete();
}));
await completer.future;
expect(imageInfoCachedHeight, isNotNull);
expect(imageInfoCachedHeight, expectedCacheHeight);
expect(imageInfoCachedWidth, isNotNull);
expect(imageInfoCachedWidth, expectedCacheWidth);
expect(called, true);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:integration_test/integration_test_driver.dart' as test;
Future<void> main() async => test.integrationDriver();
...@@ -103,10 +103,7 @@ class NetworkImage ...@@ -103,10 +103,7 @@ class NetworkImage
return collector; return collector;
} }
// TODO(garyq): We should eventually support custom decoding of network images on Web as // Html renderer does not support decoding network images to a specified size. The decode parameter
// well, see https://github.com/flutter/flutter/issues/42789.
//
// Web does not support decoding network images to a specified size. The decode parameter
// here is ignored and the web-only `ui.webOnlyInstantiateImageCodecFromUrl` will be used // here is ignored and the web-only `ui.webOnlyInstantiateImageCodecFromUrl` will be used
// directly in place of the typical `instantiateImageCodec` method. // directly in place of the typical `instantiateImageCodec` method.
Future<ui.Codec> _loadAsync( Future<ui.Codec> _loadAsync(
...@@ -119,18 +116,22 @@ class NetworkImage ...@@ -119,18 +116,22 @@ class NetworkImage
final Uri resolved = Uri.base.resolve(key.url); final Uri resolved = Uri.base.resolve(key.url);
final bool containsNetworkImageHeaders = key.headers?.isNotEmpty ?? false;
// We use a different method when headers are set because the // We use a different method when headers are set because the
// `ui.webOnlyInstantiateImageCodecFromUrl` method is not capable of handling headers. // `ui.webOnlyInstantiateImageCodecFromUrl` method is not capable of handling headers.
if (key.headers?.isNotEmpty ?? false) { if (isCanvasKit || containsNetworkImageHeaders) {
final Completer<DomXMLHttpRequest> completer = final Completer<DomXMLHttpRequest> completer =
Completer<DomXMLHttpRequest>(); Completer<DomXMLHttpRequest>();
final DomXMLHttpRequest request = httpRequestFactory(); final DomXMLHttpRequest request = httpRequestFactory();
request.open('GET', key.url, true); request.open('GET', key.url, true);
request.responseType = 'arraybuffer'; request.responseType = 'arraybuffer';
key.headers!.forEach((String header, String value) { if (containsNetworkImageHeaders) {
request.setRequestHeader(header, value); key.headers!.forEach((String header, String value) {
}); request.setRequestHeader(header, value);
});
}
request.addEventListener('load', allowInterop((DomEvent e) { request.addEventListener('load', allowInterop((DomEvent e) {
final int? status = request.status; final int? status = request.status;
......
...@@ -901,9 +901,10 @@ class ResizeImage extends ImageProvider<ResizeImageKey> { ...@@ -901,9 +901,10 @@ class ResizeImage extends ImageProvider<ResizeImageKey> {
/// The image will be cached regardless of cache headers from the server. /// The image will be cached regardless of cache headers from the server.
/// ///
/// When a network image is used on the Web platform, the `cacheWidth` and /// When a network image is used on the Web platform, the `cacheWidth` and
/// `cacheHeight` parameters of the [DecoderCallback] are ignored as the Web /// `cacheHeight` parameters of the [DecoderCallback] are only supported when the
/// engine delegates image decoding of network images to the Web, which does /// application is running with the CanvasKit renderer. When the application is using
/// not support custom decode sizes. /// the HTML renderer, the web engine delegates image decoding of network images to the Web,
/// which does not support custom decode sizes.
/// ///
/// See also: /// See also:
/// ///
......
...@@ -288,8 +288,9 @@ typedef ImageErrorWidgetBuilder = Widget Function( ...@@ -288,8 +288,9 @@ typedef ImageErrorWidgetBuilder = Widget Function(
/// memory usage of [ImageCache]. /// memory usage of [ImageCache].
/// ///
/// In the case where a network image is used on the Web platform, the /// In the case where a network image is used on the Web platform, the
/// `cacheWidth` and `cacheHeight` parameters are ignored as the Web engine /// `cacheWidth` and `cacheHeight` parameters are only supported when the application is
/// delegates image decoding of network images to the Web, which does not support /// running with the CanvasKit renderer. When the application is using the HTML renderer,
/// the web engine delegates image decoding of network images to the Web, which does not support
/// custom decode sizes. /// custom decode sizes.
/// ///
/// See also: /// See also:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment