Skip to content

Commit

Permalink
Add debugDisposed to Image (flutter#21547)
Browse files Browse the repository at this point in the history
  • Loading branch information
dnfield committed Oct 23, 2020
1 parent 0b26570 commit b952024
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 0 deletions.
13 changes: 13 additions & 0 deletions lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1632,6 +1632,19 @@ class Image {
}
}

/// Whether this reference to the underlying image is [dispose]d.
///
/// This only returns a valid value if asserts are enabled, and must not be
/// used otherwise.
bool get debugDisposed {
bool? disposed;
assert(() {
disposed = _disposed;
return true;
}());
return disposed ?? (throw StateError('Image.debugDisposed is only available when asserts are enabled.'));
}

/// Converts the [Image] object into a byte array.
///
/// The [format] argument specifies the format in which the bytes will be
Expand Down
22 changes: 22 additions & 0 deletions lib/web_ui/lib/src/engine/canvaskit/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,21 @@ class CkAnimatedImage implements ui.Image {
}
}

bool _disposed = false;
@override
void dispose() {
box.delete();
_disposed = true;
}

@override
bool get debugDisposed {
if (assertionsEnabled) {
return _disposed;
}
throw StateError('Image.debugDisposed is only available when asserts are enabled.');
}

ui.Image clone() => CkAnimatedImage._(_skAnimatedImage, box);

@override
Expand Down Expand Up @@ -138,9 +147,22 @@ class CkImage implements ui.Image {
}
}

bool _disposed = false;
@override
void dispose() {
box.delete();
assert(() {
_disposed = true;
return true;
}());
}

@override
bool get debugDisposed {
if (assertionsEnabled) {
return _disposed;
}
throw StateError('Image.debugDisposed is only available when asserts are enabled.');
}

@override
Expand Down
13 changes: 13 additions & 0 deletions lib/web_ui/lib/src/engine/html_image_codec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,25 @@ class HtmlImage implements ui.Image {
bool _requiresClone = false;
HtmlImage(this.imgElement, this.width, this.height);

bool _disposed = false;
@override
void dispose() {
// Do nothing. The codec that owns this image should take care of
// releasing the object url.
if (assertionsEnabled) {
_disposed = true;
}
}

@override
bool get debugDisposed {
if (assertionsEnabled) {
return _disposed;
}
return throw StateError('Image.debugDisposed is only available when asserts are enabled.');
}


@override
ui.Image clone() => this;

Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ abstract class Image {
int get height;
Future<ByteData?> toByteData({ImageByteFormat format = ImageByteFormat.rawRgba});
void dispose();
bool get debugDisposed;

Image clone() => this;

Expand Down
6 changes: 6 additions & 0 deletions lib/web_ui/test/canvaskit/image_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ void testMain() {
final SkAnimatedImage skAnimatedImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
final CkAnimatedImage image = CkAnimatedImage(skAnimatedImage);
expect(image.box.isDeleted, false);
expect(image.debugDisposed, false);
image.dispose();
expect(image.box.isDeleted, true);
expect(image.debugDisposed, true);
image.dispose();
expect(image.box.isDeleted, true);
expect(image.debugDisposed, true);
});

test('CkAnimatedImage can be cloned and explicitly disposed of', () async {
Expand Down Expand Up @@ -69,10 +72,13 @@ void testMain() {
test('CkImage can be explicitly disposed of', () {
final SkImage skImage = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage).getCurrentFrame();
final CkImage image = CkImage(skImage);
expect(image.debugDisposed, false);
expect(image.box.isDeleted, false);
image.dispose();
expect(image.debugDisposed, true);
expect(image.box.isDeleted, true);
image.dispose();
expect(image.debugDisposed, true);
expect(image.box.isDeleted, true);
});

Expand Down
8 changes: 8 additions & 0 deletions lib/web_ui/test/engine/image/html_image_codec_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ void testMain() async {
expect(frameInfo.image.width, 100);
expect(frameInfo.image.toString(), '[100×100]');
});
test('dispose image image', () async {
final HtmlCodec codec = HtmlCodec('sample_image1.png');
final ui.FrameInfo frameInfo = await codec.getNextFrame();
expect(frameInfo.image, isNotNull);
expect(frameInfo.image.debugDisposed, false);
frameInfo.image.dispose();
expect(frameInfo.image.debugDisposed, true);
});
test('provides image loading progress', () async {
StringBuffer buffer = new StringBuffer();
final HtmlCodec codec = HtmlCodec('sample_image1.png',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,9 @@ class TestImage implements Image {
@override
void dispose() {}

@override
bool get debugDisposed => false;

@override
Image clone() => this;

Expand Down
19 changes: 19 additions & 0 deletions testing/dart/image_dispose_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ void main() {
expect(frame2.image.clone()..dispose(), isNotNull);
frame2.image.dispose();
});

test('debugDisposed works', () async {
final Uint8List bytes = await readFile('2x2.png');
final Codec codec = await instantiateImageCodec(bytes);
final FrameInfo frame = await codec.getNextFrame();

if (assertsEnabled) {
expect(frame.image.debugDisposed, false);
} else {
expect(() => frame.image.debugDisposed, throwsStateError);
}

frame.image.dispose();
if (assertsEnabled) {
expect(frame.image.debugDisposed, true);
} else {
expect(() => frame.image.debugDisposed, throwsStateError);
}
});
}

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

0 comments on commit b952024

Please sign in to comment.