Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[canvaskit] read pixels back in Picture.toImage #40004

Merged
merged 1 commit into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 1 addition & 22 deletions lib/web_ui/lib/src/engine/canvaskit/picture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,28 +100,7 @@ class CkPicture extends ManagedSkiaObject<SkPicture> implements ui.Picture {
}

@override
ui.Image toImageSync(int width, int height) {
SurfaceFactory.instance.baseSurface.ensureSurface();
if (SurfaceFactory.instance.baseSurface.usingSoftwareBackend) {
return toImageSyncSoftware(width, height);
}
return toImageSyncGPU(width, height);
}

ui.Image toImageSyncGPU(int width, int height) {
assert(debugCheckNotDisposed('Cannot convert picture to image.'));

final CkSurface ckSurface = SurfaceFactory.instance.baseSurface
.createRenderTargetSurface(ui.Size(width.toDouble(), height.toDouble()));
final CkCanvas ckCanvas = ckSurface.getCanvas();
ckCanvas.clear(const ui.Color(0x00000000));
ckCanvas.drawPicture(this);
final SkImage skImage = ckSurface.surface.makeImageSnapshot();
ckSurface.dispose();
return CkImage(skImage);
}

ui.Image toImageSyncSoftware(int width, int height) {
CkImage toImageSync(int width, int height) {
assert(debugCheckNotDisposed('Cannot convert picture to image.'));

final Surface surface = SurfaceFactory.instance.pictureToImageSurface;
Expand Down
58 changes: 58 additions & 0 deletions lib/web_ui/test/canvaskit/canvas_golden_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,64 @@ void testMain() {
await matchGoldenFile('canvaskit_empty_scene.png',
region: const ui.Rect.fromLTRB(0, 0, 100, 100));
});

// Regression test for https://github.com/flutter/flutter/issues/121758
test('resources used in temporary surfaces for Image.toByteData can cross to rendering overlays', () async {
final Rasterizer rasterizer = CanvasKitRenderer.instance.rasterizer;
SurfaceFactory.instance.debugClear();

ui.platformViewRegistry.registerViewFactory(
'test-platform-view',
(int viewId) => createDomHTMLDivElement()..id = 'view-0',
);
await createPlatformView(0, 'test-platform-view');

CkPicture makeTextPicture(String text, ui.Offset offset) {
final CkPictureRecorder recorder = CkPictureRecorder();
final CkCanvas canvas = recorder.beginRecording(ui.Rect.largest);
final CkParagraphBuilder builder = CkParagraphBuilder(CkParagraphStyle());
builder.addText(text);
final CkParagraph paragraph = builder.build();
paragraph.layout(const ui.ParagraphConstraints(width: 100));
canvas.drawRect(
ui.Rect.fromLTWH(offset.dx, offset.dy, paragraph.width, paragraph.height).inflate(10),
CkPaint()..color = const ui.Color(0xFF00FF00)
);
canvas.drawParagraph(paragraph, offset);
return recorder.endRecording();
}

CkPicture imageToPicture(CkImage image, ui.Offset offset) {
final CkPictureRecorder recorder = CkPictureRecorder();
final CkCanvas canvas = recorder.beginRecording(ui.Rect.largest);
canvas.drawImage(image, offset, CkPaint());
return recorder.endRecording();
}

final CkPicture helloPicture = makeTextPicture('Hello', ui.Offset.zero);

final CkImage helloImage = helloPicture.toImageSync(100, 100);

// Calling toByteData is essential to hit the bug.
await helloImage.toByteData(format: ui.ImageByteFormat.png);

final LayerSceneBuilder sb = LayerSceneBuilder();
sb.pushOffset(0, 0);
sb.addPicture(ui.Offset.zero, helloPicture);
sb.addPlatformView(0, width: 10, height: 10);

// The image is rendered after the platform view so that it's rendered into
// a separate surface, which is what triggers the bug. If the bug is present
// the image will not appear on the UI.
sb.addPicture(const ui.Offset(0, 50), imageToPicture(helloImage, ui.Offset.zero));
sb.pop();

// The below line should not throw an error.
rasterizer.draw(sb.build().layerTree);

await matchGoldenFile('cross_overlay_resources.png', region: const ui.Rect.fromLTRB(0, 0, 100, 100));
});

// TODO(hterkelsen): https://github.com/flutter/flutter/issues/71520
}, skip: isSafari || isFirefox);
}
Expand Down