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
_images
before 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 anull
check forimage
. Ifimage
isnull
, it means the image hasn't finished decoding by the timeonDrawImage
was called. Rather than throwing a type error, we now gracefully handle this case. You could choose to do nothing or callonError
to 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. TheonImage
callback initiates decoding, and a future is stored in_pendingImages
. By the timeonDrawImage
is 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 usesImmutableBuffer
andImageDescriptor
, which is the correct modern approach. The fix doesn't require reverting todecodeImageFromList
or 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.