capture method

  1. @override
Future<RawFrame> capture({
  1. required GlobalKey<State<StatefulWidget>> boundaryKey,
  2. required int frameIndex,
  3. required int width,
  4. required int height,
})
override

Captures the boundary's pixels for frameIndex; the toImage() call relies on the implicit pixelRatio default of 1.0, which is load-bearing for the exact-dimension contract pinned by the spike and service tests (the fatal avoid_redundant_argument_values lint forbids spelling it).

Implementation

@override
Future<RawFrame> capture({
  required GlobalKey boundaryKey,
  required int frameIndex,
  required int width,
  required int height,
}) async {
  final boundary = _findBoundary(boundaryKey);
  final image = await boundary.toImage();
  try {
    if (image.width != width || image.height != height) {
      throw FluvieRenderException(
        'Capture size mismatch: expected ${width}x$height but the boundary '
        'painted ${image.width}x${image.height}. Set the view physical size '
        'to the target resolution with devicePixelRatio 1.0 before pumping.',
      );
    }
    // rawRgba is toByteData's default format; relied on
    // here, and asserted byte-for-byte by the spike + acceptance tests.
    final data = await image.toByteData();
    if (data == null) {
      // coverage:ignore-start defensive engine failure guard toByteData returns data for a valid RepaintBoundary so this never fires in tests
      throw FluvieRenderException(
        'The engine returned no byte data for frame $frameIndex '
        '(${width}x$height rawRgba read-back failed).',
      );
      // coverage:ignore-end
    }
    final rgba = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    return RawFrame(frameIndex: frameIndex, width: width, height: height, rgba: rgba);
  } finally {
    image.dispose();
  }
}