Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 12 additions & 18 deletions lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1905,8 +1905,6 @@ class Codec extends NativeFieldWrapperClass2 {
int get repetitionCount => _cachedRepetitionCount ??= _repetitionCount;
int get _repetitionCount native 'Codec_repetitionCount';

FrameInfo? _cachedFrame;

/// Fetches the next animation frame.
///
/// Wraps back to the first frame after returning the last frame.
Expand All @@ -1916,24 +1914,20 @@ class Codec extends NativeFieldWrapperClass2 {
/// The caller of this method is responsible for disposing the
/// [FrameInfo.image] on the returned object.
Future<FrameInfo> getNextFrame() async {
if (_cachedFrame == null || frameCount != 1) {
final Completer<void> completer = Completer<void>.sync();
final String? error = _getNextFrame((_Image? image, int durationMilliseconds) {
if (image == null) {
throw Exception('Codec failed to produce an image, possibly due to invalid image data.');
}
_cachedFrame = FrameInfo._(
image: Image._(image),
duration: Duration(milliseconds: durationMilliseconds),
);
completer.complete();
});
if (error != null) {
throw Exception(error);
final Completer<FrameInfo> completer = Completer<FrameInfo>.sync();
final String? error = _getNextFrame((_Image? image, int durationMilliseconds) {
if (image == null) {
throw Exception('Codec failed to produce an image, possibly due to invalid image data.');
}
await completer.future;
completer.complete(FrameInfo._(
image: Image._(image),
duration: Duration(milliseconds: durationMilliseconds),
));
});
if (error != null) {
throw Exception(error);
}
return _cachedFrame!;
return await completer.future;
}

/// Returns an error message on failure, null on success.
Expand Down
12 changes: 12 additions & 0 deletions testing/dart/image_dispose_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ void main() {

expect(frame2.image.isCloneOf(frame.image), false);
});

test('getNextFrame does not return a disposed image', () async {
final Uint8List bytes = await readFile('2x2.png');
final Codec codec = await instantiateImageCodec(bytes);
final FrameInfo frame = await codec.getNextFrame();

frame.image.dispose();

final FrameInfo frame2 = await codec.getNextFrame();
expect(frame2.image.clone()..dispose(), isNotNull);
frame2.image.dispose();
});
}

Future<Uint8List> readFile(String fileName) async {
Expand Down