未验证 提交 7c8f57c0 编写于 作者: H Harry Terkelsen 提交者: GitHub

Report error when instantiating CanvasKit network image (#22159)

上级 67d55ed4
......@@ -15,24 +15,33 @@ void skiaInstantiateImageCodec(Uint8List list, Callback<ui.Codec> callback,
callback(codec);
}
/// Instantiates a [ui.Codec] backed by an `SkAnimatedImage` from Skia after requesting from URI.
void skiaInstantiateWebImageCodec(String src, Callback<ui.Codec> callback,
WebOnlyImageCodecChunkCallback? chunkCallback) {
chunkCallback?.call(0, 100);
/// Instantiates a [ui.Codec] backed by an `SkAnimatedImage` from Skia after
/// requesting from URI.
Future<ui.Codec> skiaInstantiateWebImageCodec(
String src, WebOnlyImageCodecChunkCallback? chunkCallback) {
Completer<ui.Codec> completer = Completer<ui.Codec>();
//TODO: Switch to using MakeImageFromCanvasImageSource when animated images are supported.
html.HttpRequest.request(
src,
responseType: "arraybuffer",
).then((html.HttpRequest response) {
chunkCallback?.call(100, 100);
html.HttpRequest.request(src, responseType: "arraybuffer",
onProgress: (html.ProgressEvent event) {
if (event.lengthComputable) {
chunkCallback?.call(event.loaded!, event.total!);
}
}).then((html.HttpRequest response) {
if (response.status != 200) {
completer.completeError(Exception(
'Network image request failed with status: ${response.status}'));
}
final Uint8List list =
new Uint8List.view((response.response as ByteBuffer));
final SkAnimatedImage skAnimatedImage =
canvasKit.MakeAnimatedImageFromEncoded(list);
final CkAnimatedImage animatedImage = CkAnimatedImage(skAnimatedImage);
final CkAnimatedImageCodec codec = CkAnimatedImageCodec(animatedImage);
callback(codec);
completer.complete(codec);
}, onError: (dynamic error) {
completer.completeError(error);
});
return completer.future;
}
/// A wrapper for `SkAnimatedImage`.
......@@ -43,7 +52,8 @@ class CkAnimatedImage implements ui.Image {
// being garbage-collected, or by an explicit call to [delete].
late final SkiaObjectBox box;
CkAnimatedImage(SkAnimatedImage skAnimatedImage) : this._(skAnimatedImage, null);
CkAnimatedImage(SkAnimatedImage skAnimatedImage)
: this._(skAnimatedImage, null);
CkAnimatedImage._(this._skAnimatedImage, SkiaObjectBox? boxToClone) {
if (boxToClone != null) {
......@@ -66,19 +76,21 @@ class CkAnimatedImage implements ui.Image {
if (assertionsEnabled) {
return _disposed;
}
throw StateError('Image.debugDisposed is only available when asserts are enabled.');
throw StateError(
'Image.debugDisposed is only available when asserts are enabled.');
}
ui.Image clone() => CkAnimatedImage._(_skAnimatedImage, box);
@override
bool isCloneOf(ui.Image other) {
return other is CkAnimatedImage
&& other._skAnimatedImage.isAliasOf(_skAnimatedImage);
return other is CkAnimatedImage &&
other._skAnimatedImage.isAliasOf(_skAnimatedImage);
}
@override
List<StackTrace>? debugGetOpenHandleStackTraces() => box.debugGetStackTraces();
List<StackTrace>? debugGetOpenHandleStackTraces() =>
box.debugGetStackTraces();
int get frameCount => _skAnimatedImage.getFrameCount();
......@@ -115,8 +127,9 @@ class CkAnimatedImage implements ui.Image {
);
bytes = _skAnimatedImage.readPixels(imageInfo, 0, 0);
} else {
final SkData skData = _skAnimatedImage.encodeToData(); //defaults to PNG 100%
// make a copy that we can return
// Defaults to PNG 100%.
final SkData skData = _skAnimatedImage.encodeToData();
// Make a copy that we can return.
bytes = Uint8List.fromList(canvasKit.getSkDataBytes(skData));
}
......@@ -162,7 +175,8 @@ class CkImage implements ui.Image {
if (assertionsEnabled) {
return _disposed;
}
throw StateError('Image.debugDisposed is only available when asserts are enabled.');
throw StateError(
'Image.debugDisposed is only available when asserts are enabled.');
}
@override
......@@ -170,12 +184,12 @@ class CkImage implements ui.Image {
@override
bool isCloneOf(ui.Image other) {
return other is CkImage
&& other.skImage.isAliasOf(skImage);
return other is CkImage && other.skImage.isAliasOf(skImage);
}
@override
List<StackTrace>? debugGetOpenHandleStackTraces() => box.debugGetStackTraces();
List<StackTrace>? debugGetOpenHandleStackTraces() =>
box.debugGetStackTraces();
@override
int get width => skImage.width();
......
......@@ -462,9 +462,14 @@ String? _instantiateImageCodec(Uint8List list, engine.Callback<Codec> callback)
}
Future<Codec> webOnlyInstantiateImageCodecFromUrl(Uri uri,
{engine.WebOnlyImageCodecChunkCallback? chunkCallback}) {
return _futurize<Codec>((engine.Callback<Codec> callback) =>
{engine.WebOnlyImageCodecChunkCallback? chunkCallback}) {
if (engine.useCanvasKit) {
return engine.skiaInstantiateWebImageCodec(
uri.toString(), chunkCallback);
} else {
return _futurize<Codec>((engine.Callback<Codec> callback) =>
_instantiateImageCodecFromUrl(uri, chunkCallback, callback));
}
}
String? _instantiateImageCodecFromUrl(
......@@ -472,13 +477,8 @@ String? _instantiateImageCodecFromUrl(
engine.WebOnlyImageCodecChunkCallback? chunkCallback,
engine.Callback<Codec> callback,
) {
if (engine.useCanvasKit) {
engine.skiaInstantiateWebImageCodec(uri.toString(), callback, chunkCallback);
return null;
} else {
callback(engine.HtmlCodec(uri.toString(), chunkCallback: chunkCallback));
return null;
}
callback(engine.HtmlCodec(uri.toString(), chunkCallback: chunkCallback));
return null;
}
void decodeImageFromList(Uint8List list, ImageDecoderCallback callback) {
......
......@@ -3,6 +3,8 @@
// found in the LICENSE file.
// @dart = 2.6
import 'dart:html' show ProgressEvent;
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
......@@ -22,14 +24,16 @@ void testMain() {
});
test('CkAnimatedImage toString', () {
final SkAnimatedImage skAnimatedImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final SkAnimatedImage skAnimatedImage =
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final CkAnimatedImage image = CkAnimatedImage(skAnimatedImage);
expect(image.toString(), '[1×1]');
image.dispose();
});
test('CkAnimatedImage can be explicitly disposed of', () {
final SkAnimatedImage skAnimatedImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final SkAnimatedImage skAnimatedImage =
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final CkAnimatedImage image = CkAnimatedImage(skAnimatedImage);
expect(image.box.isDeleted, false);
expect(image.debugDisposed, false);
......@@ -42,7 +46,8 @@ void testMain() {
});
test('CkAnimatedImage can be cloned and explicitly disposed of', () async {
final SkAnimatedImage skAnimatedImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final SkAnimatedImage skAnimatedImage =
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final CkAnimatedImage image = CkAnimatedImage(skAnimatedImage);
final CkAnimatedImage imageClone = image.clone();
......@@ -63,14 +68,18 @@ void testMain() {
});
test('CkImage toString', () {
final SkImage skImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage).getCurrentFrame();
final SkImage skImage =
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage)
.getCurrentFrame();
final CkImage image = CkImage(skImage);
expect(image.toString(), '[1×1]');
image.dispose();
});
test('CkImage can be explicitly disposed of', () {
final SkImage skImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage).getCurrentFrame();
final SkImage skImage =
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage)
.getCurrentFrame();
final CkImage image = CkImage(skImage);
expect(image.debugDisposed, false);
expect(image.box.isDeleted, false);
......@@ -83,7 +92,9 @@ void testMain() {
});
test('CkImage can be explicitly disposed of when cloned', () async {
final SkImage skImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage).getCurrentFrame();
final SkImage skImage =
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage)
.getCurrentFrame();
final CkImage image = CkImage(skImage);
final CkImage imageClone = image.clone();
......@@ -102,6 +113,12 @@ void testMain() {
await Future<void>.delayed(Duration.zero);
expect(skImage.isDeleted(), true);
});
// TODO: https://github.com/flutter/flutter/issues/60040
test('skiaInstantiateWebImageCodec throws exception if given invalid URL',
() async {
expect(skiaInstantiateWebImageCodec('invalid-url', null),
throwsA(isA<ProgressEvent>()));
});
// TODO: https://github.com/flutter/flutter/issues/60040
}, skip: isIosSafari);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册