screenshot method

  1. @protected
Future<Image> screenshot (Object object, { @required double width, @required double height, double margin: 0.0, double maxPixelRatio: 1.0, bool debugPaint: false })
@protected

Captures an image of the current state of an object that is a RenderObject or Element.

The returned ui.Image has uncompressed raw RGBA bytes and will be scaled to be at most width pixels wide and height pixels tall. The returned image will never have a scale between logical pixels and the size of the output image larger than maxPixelRatio. margin indicates the number of pixels relative to the unscaled size of the object to include as a margin to include around the bounds of the object in the screenshot. Including a margin can be useful to capture areas that are slightly outside of the normal bounds of an object such as some debug paint information.

Implementation

@protected
Future<ui.Image> screenshot(
  Object object, {
  @required double width,
  @required double height,
  double margin = 0.0,
  double maxPixelRatio = 1.0,
  bool debugPaint = false,
}) async {
  if (object is! Element && object is! RenderObject) {
    return null;
  }
  final RenderObject renderObject = object is Element ? object.renderObject : object;
  if (renderObject == null || !renderObject.attached) {
    return null;
  }

  if (renderObject.debugNeedsLayout) {
    final PipelineOwner owner = renderObject.owner;
    assert(owner != null);
    assert(!owner.debugDoingLayout);
    owner
      ..flushLayout()
      ..flushCompositingBits()
      ..flushPaint();

    // If we still need layout, then that means that renderObject was skipped
    // in the layout phase and therefore can't be painted. It is clearer to
    // return null indicating that a screenshot is unavailable than to return
    // an empty image.
    if (renderObject.debugNeedsLayout) {
      return null;
    }
  }

  Rect renderBounds = _calculateSubtreeBounds(renderObject);
  if (margin != 0.0) {
    renderBounds = renderBounds.inflate(margin);
  }
  if (renderBounds.isEmpty) {
    return null;
  }

  final double pixelRatio = math.min(
    maxPixelRatio,
    math.min(
      width / renderBounds.width,
      height / renderBounds.height,
    ),
  );

  return _ScreenshotPaintingContext.toImage(
    renderObject,
    renderBounds,
    pixelRatio: pixelRatio,
    debugPaint: debugPaint,
  );
}