Skip to content

Bug: Sprite.rasterize() doesn't reset srcPosition to (0,0), causing drawImageRect assertion failure #3902

@erickzanardo

Description

@erickzanardo

Bug Description

The Sprite.rasterize() method creates a new sprite with a rasterized copy of just the sprite region, but it doesn't reset srcPosition to (0, 0). This causes the source rectangle to have coordinates that are completely outside the bounds of the new smaller image, leading to a drawImageRect assertion failure when the sprite is rendered.

Reproduction Steps

// 1. Create a sprite from an atlas at position (8, 7) with tileSize 16
final originalSprite = Sprite(
  atlasImage, // e.g., 336x160 pixels
  srcPosition: Vector2(128, 112), // 8 * 16, 7 * 16
  srcSize: Vector2(16, 16),
);

// 2. Rasterize it - this creates a 16x16 image
final rasterized = await originalSprite.rasterize();

// 3. The rasterized sprite now has:
//    - image: 16x16 (just the sprite region)
//    - src: Rect(128, 112, 144, 128)  <-- PROBLEM!
//    
// The src rect is OUTSIDE the 16x16 image bounds!

// 4. Render it - this will crash:
// Failed assertion: line 7471 pos 12: '<optimized out>': is not true.
// (Canvas.drawImageRect with out-of-bounds src rect)

Root Cause

In packages/flame/lib/src/sprite.dart lines 93-96:

Future<Sprite> rasterize({String? cacheKey, Images? images}) async {
  // ... creates rasterizedImage ...
  
  return Sprite(
    rasterizedImage,
    srcSize: srcSize,  // <-- Only srcSize is passed
    // srcPosition is NOT passed, so it defaults to null
    // and the original srcPosition is retained
  );
}

The Sprite constructor at lines 23-30 only updates srcSize, but srcPosition defaults to null, which means the old position is used via the src Rect calculation.

Expected Behavior

After rasterize(), the sprite should have srcPosition reset to (0, 0) since the new image contains only the sprite region starting at the origin.

Fix

return Sprite(
  rasterizedImage,
  srcPosition: Vector2.zero(),  // Reset to origin
  srcSize: srcSize,
);

Environment

  • Flame version: 1.35.1 (also affects earlier versions)
  • Flutter version: 3.x
  • Platform: All (macOS, iOS, Android, Web, Windows, Linux)

Impact

This bug affects:

  • SpriteWidget with rasterize: true parameter
  • Any custom code that calls Sprite.rasterize() and then renders the result
  • Causes hard-to-debug dart:ui assertion failures

Workaround

Until fixed, users can manually create the rasterized sprite:

final composition = ImageComposition()
  ..add(originalSprite.image, Vector2.zero(), source: originalSprite.src);
final rasterizedImage = await composition.compose();

final fixedSprite = Sprite(
  rasterizedImage,
  srcPosition: Vector2.zero(),  // Explicitly set to origin
  srcSize: originalSprite.srcSize,
);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions