Below is an updated fix that aligns with the current version of the vector_graphics source code you provided. The original issue involved a runtime crash (_TypeError) occurring when attempting to draw <image> elements. With the newer code that uses ImmutableBuffer and ImageDescriptor, the decoding pipeline is already correct. The likely cause of the crash is that onDrawImage may be invoked before the image has finished decoding or if the image failed to decode, resulting in a null lookup from the _images map.
To address this safely, we should:
- Check if the image is available in
_imagesbefore drawing. - If the image is not yet ready or failed to load, handle the scenario gracefully (e.g., skip drawing or report an error).
Updated onDrawImage method:
@override
void onDrawImage(
int imageId,
double x,
double y,
double width,
double height,
Float64List? transform,
) {
final ui.Image? image = _images[imageId];
// If the image is not yet decoded or failed to load, it may be null.
if (image == null) {
// Optionally log or report this scenario. For example:
if (onError != null) {
onError(
'Image with ID $imageId could not be drawn because it is not yet available.',
null,
);
}
return;
}
if (transform != null) {
_canvas.save();
_canvas.transform(transform);
}
_canvas.drawImageRect(
image,
Rect.fromLTRB(0, 0, image.width.toDouble(), image.height.toDouble()),
Rect.fromLTWH(x, y, width, height),
Paint(),
);
if (transform != null) {
_canvas.restore();
}
}Explanation:
-
Null Check for Images:
The key change is adding anullcheck forimage. Ifimageisnull, it means the image hasn't finished decoding by the timeonDrawImagewas called. Rather than throwing a type error, we now gracefully handle this case. You could choose to do nothing or callonErrorto log the issue. -
Safe Drawing:
If the image is available, we proceed as normal and draw the image. Transformations are still applied and restored as before.
Why This Fix Works:
-
Asynchronous Decoding:
Image decoding is asynchronous. TheonImagecallback initiates decoding, and a future is stored in_pendingImages. By the timeonDrawImageis called, the decoding may not be complete. Checking for null ensures we don't try to draw a non-existent resource. -
Consistency with Decoding Pipeline:
The current code already usesImmutableBufferandImageDescriptor, which is the correct modern approach. The fix doesn't require reverting todecodeImageFromListor changing the decode pipeline, it only adds robustness around the usage of the decoded images.
With these changes in place, you should no longer encounter _TypeError crashes related to image drawing.