Unverified Commit 5b5a5b82 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Revert "Enable taking screenshots of arbitrary RenderObjects from a running a… (#20637)" (#21395)

This reverts commit 3306fc10.
parent 3306fc10
da615501c1032cb803b2a5623b07d7f4834d9640 1a999092d10a22bc700214b257cd4890c5800078
...@@ -50,8 +50,6 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin { ...@@ -50,8 +50,6 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
Layer _previousSibling; Layer _previousSibling;
/// Removes this layer from its parent layer's child list. /// Removes this layer from its parent layer's child list.
///
/// This has no effect if the layer's parent is already null.
@mustCallSuper @mustCallSuper
void remove() { void remove() {
parent?._removeChild(this); parent?._removeChild(this);
...@@ -590,11 +588,7 @@ class OffsetLayer extends ContainerLayer { ...@@ -590,11 +588,7 @@ class OffsetLayer extends ContainerLayer {
assert(bounds != null); assert(bounds != null);
assert(pixelRatio != null); assert(pixelRatio != null);
final ui.SceneBuilder builder = new ui.SceneBuilder(); final ui.SceneBuilder builder = new ui.SceneBuilder();
final Matrix4 transform = new Matrix4.translationValues( final Matrix4 transform = new Matrix4.translationValues(bounds.left - offset.dx, bounds.top - offset.dy, 0.0);
(-bounds.left - offset.dx) * pixelRatio,
(-bounds.top - offset.dy) * pixelRatio,
0.0,
);
transform.scale(pixelRatio, pixelRatio); transform.scale(pixelRatio, pixelRatio);
builder.pushTransform(transform.storage); builder.pushTransform(transform.storage);
addToScene(builder, Offset.zero); addToScene(builder, Offset.zero);
......
...@@ -60,13 +60,7 @@ typedef void PaintingContextCallback(PaintingContext context, Offset offset); ...@@ -60,13 +60,7 @@ typedef void PaintingContextCallback(PaintingContext context, Offset offset);
/// New [PaintingContext] objects are created automatically when using /// New [PaintingContext] objects are created automatically when using
/// [PaintingContext.repaintCompositedChild] and [pushLayer]. /// [PaintingContext.repaintCompositedChild] and [pushLayer].
class PaintingContext extends ClipContext { class PaintingContext extends ClipContext {
PaintingContext._(this._containerLayer, this.estimatedBounds)
/// Creates a painting context.
///
/// Typically only called by [PaintingContext.repaintCompositedChild]
/// and [pushLayer].
@protected
PaintingContext(this._containerLayer, this.estimatedBounds)
: assert(_containerLayer != null), : assert(_containerLayer != null),
assert(estimatedBounds != null); assert(estimatedBounds != null);
...@@ -92,19 +86,8 @@ class PaintingContext extends ClipContext { ...@@ -92,19 +86,8 @@ class PaintingContext extends ClipContext {
/// * [RenderObject.isRepaintBoundary], which determines if a [RenderObject] /// * [RenderObject.isRepaintBoundary], which determines if a [RenderObject]
/// has a composited layer. /// has a composited layer.
static void repaintCompositedChild(RenderObject child, { bool debugAlsoPaintedParent = false }) { static void repaintCompositedChild(RenderObject child, { bool debugAlsoPaintedParent = false }) {
assert(child._needsPaint);
_repaintCompositedChild(
child,
debugAlsoPaintedParent: debugAlsoPaintedParent,
);
}
static void _repaintCompositedChild(
RenderObject child, {
bool debugAlsoPaintedParent = false,
PaintingContext childContext,
}) {
assert(child.isRepaintBoundary); assert(child.isRepaintBoundary);
assert(child._needsPaint);
assert(() { assert(() {
// register the call for RepaintBoundary metrics // register the call for RepaintBoundary metrics
child.debugRegisterRepaintBoundaryPaint( child.debugRegisterRepaintBoundaryPaint(
...@@ -124,32 +107,9 @@ class PaintingContext extends ClipContext { ...@@ -124,32 +107,9 @@ class PaintingContext extends ClipContext {
child._layer.debugCreator = child.debugCreator ?? child.runtimeType; child._layer.debugCreator = child.debugCreator ?? child.runtimeType;
return true; return true;
}()); }());
childContext ??= new PaintingContext(child._layer, child.paintBounds); final PaintingContext childContext = new PaintingContext._(child._layer, child.paintBounds);
child._paintWithContext(childContext, Offset.zero); child._paintWithContext(childContext, Offset.zero);
childContext.stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
}
/// In debug mode, repaint the given render object using a custom painting
/// context that can record the results of the painting operation in addition
/// to performing the regular paint of the child.
///
/// See also:
///
/// * [repaintCompositedChild], for repainting a composited child without
/// instrumentation.
static void debugInstrumentRepaintCompositedChild(
RenderObject child, {
bool debugAlsoPaintedParent = false,
@required PaintingContext customContext,
}) {
assert(() {
_repaintCompositedChild(
child,
debugAlsoPaintedParent: debugAlsoPaintedParent,
childContext: customContext,
);
return true;
}());
} }
/// Paint a child [RenderObject]. /// Paint a child [RenderObject].
...@@ -165,7 +125,7 @@ class PaintingContext extends ClipContext { ...@@ -165,7 +125,7 @@ class PaintingContext extends ClipContext {
}()); }());
if (child.isRepaintBoundary) { if (child.isRepaintBoundary) {
stopRecordingIfNeeded(); _stopRecordingIfNeeded();
_compositeChild(child, offset); _compositeChild(child, offset);
} else { } else {
child._paintWithContext(this, offset); child._paintWithContext(this, offset);
...@@ -199,20 +159,10 @@ class PaintingContext extends ClipContext { ...@@ -199,20 +159,10 @@ class PaintingContext extends ClipContext {
}()); }());
} }
child._layer.offset = offset; child._layer.offset = offset;
appendLayer(child._layer); _appendLayer(child._layer);
} }
/// Adds a layer to the recording requiring that the recording is already void _appendLayer(Layer layer) {
/// stopped.
///
/// Do not call this function directly: call [addLayer] or [pushLayer]
/// instead. This function is called internally when all layers not
/// generated from the [canvas] are added.
///
/// Subclasses that need to customize how layers are added should override
/// this method.
@protected
void appendLayer(Layer layer) {
assert(!_isRecording); assert(!_isRecording);
layer.remove(); layer.remove();
_containerLayer.append(layer); _containerLayer.append(layer);
...@@ -260,19 +210,7 @@ class PaintingContext extends ClipContext { ...@@ -260,19 +210,7 @@ class PaintingContext extends ClipContext {
_containerLayer.append(_currentLayer); _containerLayer.append(_currentLayer);
} }
/// Stop recording to a canvas if recording has started. void _stopRecordingIfNeeded() {
///
/// Do not call this function directly: functions in this class will call
/// this method as needed. This function is called internally to ensure that
/// recording is stopped before adding layers or finalizing the results of a
/// paint.
///
/// Subclasses that need to customize how recording to a canvas is performed
/// should override this method to save the results of the custom canvas
/// recordings.
@protected
@mustCallSuper
void stopRecordingIfNeeded() {
if (!_isRecording) if (!_isRecording)
return; return;
assert(() { assert(() {
...@@ -333,8 +271,8 @@ class PaintingContext extends ClipContext { ...@@ -333,8 +271,8 @@ class PaintingContext extends ClipContext {
/// * [pushLayer], for adding a layer and using its canvas to paint with that /// * [pushLayer], for adding a layer and using its canvas to paint with that
/// layer. /// layer.
void addLayer(Layer layer) { void addLayer(Layer layer) {
stopRecordingIfNeeded(); _stopRecordingIfNeeded();
appendLayer(layer); _appendLayer(layer);
} }
/// Appends the given layer to the recording, and calls the `painter` callback /// Appends the given layer to the recording, and calls the `painter` callback
...@@ -357,21 +295,15 @@ class PaintingContext extends ClipContext { ...@@ -357,21 +295,15 @@ class PaintingContext extends ClipContext {
/// See also: /// See also:
/// ///
/// * [addLayer], for pushing a leaf layer whose canvas is not used. /// * [addLayer], for pushing a leaf layer whose canvas is not used.
void pushLayer(ContainerLayer childLayer, PaintingContextCallback painter, Offset offset, { Rect childPaintBounds }) { void pushLayer(Layer childLayer, PaintingContextCallback painter, Offset offset, { Rect childPaintBounds }) {
assert(!childLayer.attached); assert(!childLayer.attached);
assert(childLayer.parent == null); assert(childLayer.parent == null);
assert(painter != null); assert(painter != null);
stopRecordingIfNeeded(); _stopRecordingIfNeeded();
appendLayer(childLayer); _appendLayer(childLayer);
final PaintingContext childContext = createChildContext(childLayer, childPaintBounds ?? estimatedBounds); final PaintingContext childContext = new PaintingContext._(childLayer, childPaintBounds ?? estimatedBounds);
painter(childContext, offset); painter(childContext, offset);
childContext.stopRecordingIfNeeded(); childContext._stopRecordingIfNeeded();
}
/// Creates a compatible painting context to paint onto [childLayer].
@protected
PaintingContext createChildContext(ContainerLayer childLayer, Rect bounds) {
return new PaintingContext(childLayer, bounds);
} }
/// Clip further painting using a rectangle. /// Clip further painting using a rectangle.
...@@ -2104,6 +2036,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2104,6 +2036,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
Rect get paintBounds; Rect get paintBounds;
/// Override this method to paint debugging information. /// Override this method to paint debugging information.
@protected
void debugPaint(PaintingContext context, Offset offset) { } void debugPaint(PaintingContext context, Offset offset) { }
/// Paint this render object into the given context at the given offset. /// Paint this render object into the given context at the given offset.
......
...@@ -512,7 +512,7 @@ void main() { ...@@ -512,7 +512,7 @@ void main() {
// If you add a service extension... TEST IT! :-) // If you add a service extension... TEST IT! :-)
// ...then increment this number. // ...then increment this number.
expect(binding.extensions.length, 38); expect(binding.extensions.length, 37);
expect(console, isEmpty); expect(console, isEmpty);
debugPrint = debugPrintThrottled; debugPrint = debugPrintThrottled;
......
...@@ -185,43 +185,12 @@ void main() { ...@@ -185,43 +185,12 @@ void main() {
image = await boundary.toImage(); image = await boundary.toImage();
expect(image.width, equals(20)); expect(image.width, equals(20));
expect(image.height, equals(20)); expect(image.height, equals(20));
ByteData data = await image.toByteData(); final ByteData data = await image.toByteData();
int getPixel(int x, int y) => data.getUint32((x + y * image.width) * 4);
expect(data.lengthInBytes, equals(20 * 20 * 4)); expect(data.lengthInBytes, equals(20 * 20 * 4));
expect(data.elementSizeInBytes, equals(1)); expect(data.elementSizeInBytes, equals(1));
expect(getPixel(0, 0), equals(0x00000080)); const int stride = 20 * 4;
expect(getPixel(image.width - 1, 0 ), equals(0xffffffff)); expect(data.getUint32(0), equals(0x00000080));
expect(data.getUint32(stride - 4), equals(0xffffffff));
final OffsetLayer layer = boundary.layer;
image = await layer.toImage(Offset.zero & const Size(20.0, 20.0));
expect(image.width, equals(20));
expect(image.height, equals(20));
data = await image.toByteData();
expect(getPixel(0, 0), equals(0x00000080));
expect(getPixel(image.width - 1, 0 ), equals(0xffffffff));
// non-zero offsets.
image = await layer.toImage(const Offset(-10.0, -10.0) & const Size(30.0, 30.0));
expect(image.width, equals(30));
expect(image.height, equals(30));
data = await image.toByteData();
expect(getPixel(0, 0), equals(0x00000000));
expect(getPixel(10, 10), equals(0x00000080));
expect(getPixel(image.width - 1, 0), equals(0x00000000));
expect(getPixel(image.width - 1, 10), equals(0xffffffff));
// offset combined with a custom pixel ratio.
image = await layer.toImage(const Offset(-10.0, -10.0) & const Size(30.0, 30.0), pixelRatio: 2.0);
expect(image.width, equals(60));
expect(image.height, equals(60));
data = await image.toByteData();
expect(getPixel(0, 0), equals(0x00000000));
expect(getPixel(20, 20), equals(0x00000080));
expect(getPixel(image.width - 1, 0), equals(0x00000000));
expect(getPixel(image.width - 1, 20), equals(0xffffffff));
}); });
test('RenderOpacity does not composite if it is transparent', () { test('RenderOpacity does not composite if it is transparent', () {
......
...@@ -251,12 +251,8 @@ Matcher isMethodCall(String name, {@required dynamic arguments}) { ...@@ -251,12 +251,8 @@ Matcher isMethodCall(String name, {@required dynamic arguments}) {
Matcher coversSameAreaAs(Path expectedPath, {@required Rect areaToCompare, int sampleSize = 20}) Matcher coversSameAreaAs(Path expectedPath, {@required Rect areaToCompare, int sampleSize = 20})
=> new _CoversSameAreaAs(expectedPath, areaToCompare: areaToCompare, sampleSize: sampleSize); => new _CoversSameAreaAs(expectedPath, areaToCompare: areaToCompare, sampleSize: sampleSize);
/// Asserts that a [Finder], [Future<ui.Image>], or [ui.Image] matches the /// Asserts that a [Finder] matches exactly one widget whose rendered image
/// golden image file identified by [key]. /// matches the golden image file identified by [key].
///
/// For the case of a [Finder], the [Finder] must match exactly one widget and
/// the rendered image of the first [RepaintBoundary] ancestor of the widget is
/// treated as the image for the widget.
/// ///
/// [key] may be either a [Uri] or a [String] representation of a URI. /// [key] may be either a [Uri] or a [String] representation of a URI.
/// ///
...@@ -268,8 +264,6 @@ Matcher coversSameAreaAs(Path expectedPath, {@required Rect areaToCompare, int s ...@@ -268,8 +264,6 @@ Matcher coversSameAreaAs(Path expectedPath, {@required Rect areaToCompare, int s
/// ///
/// ```dart /// ```dart
/// await expectLater(find.text('Save'), matchesGoldenFile('save.png')); /// await expectLater(find.text('Save'), matchesGoldenFile('save.png'));
/// await expectLater(image, matchesGoldenFile('save.png'));
/// await expectLater(imageFuture, matchesGoldenFile('save.png'));
/// ``` /// ```
/// ///
/// See also: /// See also:
...@@ -1502,17 +1496,6 @@ class _CoversSameAreaAs extends Matcher { ...@@ -1502,17 +1496,6 @@ class _CoversSameAreaAs extends Matcher {
description.add('covers expected area and only expected area'); description.add('covers expected area and only expected area');
} }
Future<ui.Image> _captureImage(Element element) {
RenderObject renderObject = element.renderObject;
while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent;
assert(renderObject != null);
}
assert(!renderObject.debugNeedsPaint);
final OffsetLayer layer = renderObject.layer;
return layer.toImage(renderObject.paintBounds);
}
class _MatchesGoldenFile extends AsyncMatcher { class _MatchesGoldenFile extends AsyncMatcher {
const _MatchesGoldenFile(this.key); const _MatchesGoldenFile(this.key);
...@@ -1521,22 +1504,23 @@ class _MatchesGoldenFile extends AsyncMatcher { ...@@ -1521,22 +1504,23 @@ class _MatchesGoldenFile extends AsyncMatcher {
final Uri key; final Uri key;
@override @override
Future<String> matchAsync(dynamic item) async { Future<String> matchAsync(covariant Finder finder) async {
Future<ui.Image> imageFuture; final Iterable<Element> elements = finder.evaluate();
if (item is Future<ui.Image>) { if (elements.isEmpty) {
imageFuture = item; return 'could not be rendered because no widget was found';
} else if (item is ui.Image) { } else if (elements.length > 1) {
imageFuture = new Future<ui.Image>.value(item); return 'matched too many widgets';
} else { }
final Finder finder = item; final Element element = elements.single;
final Iterable<Element> elements = finder.evaluate();
if (elements.isEmpty) { RenderObject renderObject = element.renderObject;
return 'could not be rendered because no widget was found'; while (!renderObject.isRepaintBoundary) {
} else if (elements.length > 1) { renderObject = renderObject.parent;
return 'matched too many widgets'; assert(renderObject != null);
}
imageFuture = _captureImage(elements.single);
} }
assert(!renderObject.debugNeedsPaint);
final OffsetLayer layer = renderObject.layer;
final Future<ui.Image> imageFuture = layer.toImage(renderObject.paintBounds);
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
return binding.runAsync<String>(() async { return binding.runAsync<String>(() async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment