Move toImage() impl from RepaintRenderBoundary to OffsetLayer (#17060)
https://github.com/flutter/flutter/issues/16859
This commit is contained in:
parent
f0c4bc30c6
commit
a5a33325ef
@ -2,8 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:ui' as ui show ImageFilter, Picture, SceneBuilder;
|
||||
import 'dart:ui' as ui show Image, ImageFilter, Picture, Scene, SceneBuilder;
|
||||
import 'dart:ui' show Offset;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -515,6 +516,41 @@ class OffsetLayer extends ContainerLayer {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(new DiagnosticsProperty<Offset>('offset', offset));
|
||||
}
|
||||
|
||||
/// Capture an image of the current state of this layer and its children.
|
||||
///
|
||||
/// The returned [ui.Image] has uncompressed raw RGBA bytes, in the
|
||||
/// dimensions [logicalSize] multiplied by the [pixelRatio].
|
||||
///
|
||||
/// The [pixelRatio] describes the scale between the logical pixels and the
|
||||
/// size of the output image. It is independent of the
|
||||
/// [window.devicePixelRatio] for the device, so specifying 1.0 (the default)
|
||||
/// will give you a 1:1 mapping between logical pixels and the output pixels
|
||||
/// in the image.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [RenderRepaintBoundary.toImage] for a similar API at the render object level.
|
||||
/// * [dart:ui.Scene.toImage] for more information about the image returned.
|
||||
Future<ui.Image> toImage(Size logicalSize, {double pixelRatio: 1.0}) async {
|
||||
assert(pixelRatio != null);
|
||||
final ui.SceneBuilder builder = new ui.SceneBuilder();
|
||||
final Matrix4 transform = new Matrix4.diagonal3Values(pixelRatio, pixelRatio, 1.0);
|
||||
transform.translate(-offset.dx, -offset.dy, 0.0);
|
||||
builder.pushTransform(transform.storage);
|
||||
addToScene(builder, Offset.zero);
|
||||
final ui.Scene scene = builder.build();
|
||||
try {
|
||||
// Size is rounded up to the next pixel to make sure we don't clip off
|
||||
// anything.
|
||||
return await scene.toImage(
|
||||
(pixelRatio * logicalSize.width).ceil(),
|
||||
(pixelRatio * logicalSize.height).ceil(),
|
||||
);
|
||||
} finally {
|
||||
scene.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A composite layer that clips its children using a rectangle.
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'dart:ui' as ui show ImageFilter, Gradient, SceneBuilder, Scene, Image;
|
||||
import 'dart:ui' as ui show ImageFilter, Gradient, Image;
|
||||
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -2470,27 +2470,52 @@ class RenderRepaintBoundary extends RenderProxyBox {
|
||||
/// will give you a 1:1 mapping between logical pixels and the output pixels
|
||||
/// in the image.
|
||||
///
|
||||
/// ## Sample code
|
||||
///
|
||||
/// The following is an example of how to go from a `GlobalKey` on a
|
||||
/// `RepaintBoundary` to a PNG:
|
||||
///
|
||||
/// ```dart
|
||||
/// class PngHome extends StatefulWidget {
|
||||
/// PngHome({Key key}) : super(key: key);
|
||||
///
|
||||
/// @override
|
||||
/// _PngHomeState createState() => new _PngHomeState();
|
||||
/// }
|
||||
///
|
||||
/// class _PngHomeState extends State<PngHome> {
|
||||
/// GlobalKey globalKey = new GlobalKey();
|
||||
///
|
||||
/// Future<void> _capturePng() async {
|
||||
/// RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
|
||||
/// ui.Image image = await boundary.toImage();
|
||||
/// ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
/// Uint8List pngBytes = byteData.buffer.asUint8List();
|
||||
/// print(pngBytes);
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return RepaintBoundary(
|
||||
/// key: globalKey,
|
||||
/// child: Center(
|
||||
/// child: FlatButton(
|
||||
/// child: Text('Hello World', textDirection: TextDirection.ltr),
|
||||
/// onPressed: _capturePng,
|
||||
/// ),
|
||||
/// ),
|
||||
/// );
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [OffsetLayer.toImage] for a similar API at the layer level.
|
||||
/// * [dart:ui.Scene.toImage] for more information about the image returned.
|
||||
Future<ui.Image> toImage({double pixelRatio: 1.0}) async {
|
||||
Future<ui.Image> toImage({double pixelRatio: 1.0}) {
|
||||
assert(!debugNeedsPaint);
|
||||
final ui.SceneBuilder builder = new ui.SceneBuilder();
|
||||
final Matrix4 transform = new Matrix4.diagonal3Values(pixelRatio, pixelRatio, 1.0);
|
||||
transform.translate(-layer.offset.dx, -layer.offset.dy, 0.0);
|
||||
builder.pushTransform(transform.storage);
|
||||
layer.addToScene(builder, Offset.zero);
|
||||
final ui.Scene scene = builder.build();
|
||||
try {
|
||||
// Size is rounded up to the next pixel to make sure we don't clip off
|
||||
// anything.
|
||||
return await scene.toImage(
|
||||
(pixelRatio * size.width).ceil(),
|
||||
(pixelRatio * size.height).ceil(),
|
||||
);
|
||||
} finally {
|
||||
scene.dispose();
|
||||
}
|
||||
return layer.toImage(size, pixelRatio: pixelRatio);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user