Skip to content

Instantly share code, notes, and snippets.

@jezell
Created December 6, 2024 08:06
Show Gist options
  • Save jezell/b2db8c13cb6922c80b73a8adba5e759d to your computer and use it in GitHub Desktop.
Save jezell/b2db8c13cb6922c80b73a8adba5e759d to your computer and use it in GitHub Desktop.
bug updated

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:

  1. Check if the image is available in _images before drawing.
  2. 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 a null check for image. If image is null, it means the image hasn't finished decoding by the time onDrawImage was called. Rather than throwing a type error, we now gracefully handle this case. You could choose to do nothing or call onError 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. The onImage callback initiates decoding, and a future is stored in _pendingImages. By the time onDrawImage 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 uses ImmutableBuffer and ImageDescriptor, which is the correct modern approach. The fix doesn't require reverting to decodeImageFromList 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment