Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
17 changes: 0 additions & 17 deletions lib/ui/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,6 @@ class Scene extends NativeFieldWrapperClass1 {
@pragma('vm:entry-point')
Scene._();

/// Synchronously creates a handle to an image from this scene.
///
/// {@macro dart.ui.painting.Picture.toImageSync}
Image toImageSync(int width, int height) {
if (width <= 0 || height <= 0) {
throw Exception('Invalid image dimensions.');
}

final _Image image = _Image._();
final String? result = _toImageSync(width, height, image);
if (result != null) {
throw PictureRasterizationException._(result);
}
return Image._(image, image.width, image.height);
}
String? _toImageSync(int width, int height, _Image outImage) native 'Scene_toImageSync';

/// Creates a raster image representation of the current state of the scene.
/// This is a slow operation that is performed on a background thread.
///
Expand Down
19 changes: 0 additions & 19 deletions lib/ui/compositing/scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ namespace flutter {
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene);

#define FOR_EACH_BINDING(V) \
V(Scene, toImageSync) \
V(Scene, toImage) \
V(Scene, dispose)

Expand Down Expand Up @@ -67,24 +66,6 @@ void Scene::dispose() {
ClearDartWrapper();
}

Dart_Handle Scene::toImageSync(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle) {
TRACE_EVENT0("flutter", "Scene::toImageSync");

if (!layer_tree_) {
return tonic::ToDart("Scene did not contain a layer tree.");
}

auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height));
if (!picture) {
return tonic::ToDart("Could not flatten scene into a layer tree.");
}

Picture::RasterizeToImageSync(picture, width, height, raw_image_handle);
return Dart_Null();
}

Dart_Handle Scene::toImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
Expand Down
4 changes: 0 additions & 4 deletions lib/ui/compositing/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ class Scene : public RefCountedDartWrappable<Scene> {

std::unique_ptr<flutter::LayerTree> takeLayerTree();

Dart_Handle toImageSync(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle);

Dart_Handle toImage(uint32_t width,
uint32_t height,
Dart_Handle image_callback);
Expand Down
31 changes: 1 addition & 30 deletions lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5375,35 +5375,6 @@ class Picture extends NativeFieldWrapperClass1 {
}
String? _toImage(int width, int height, _Callback<_Image?> callback) native 'Picture_toImage';

/// Synchronously creates a handle to an image of this picture.
///
/// {@template dart.ui.painting.Picture.toImageSync}
/// The returned image will be `width` pixels wide and `height` pixels high.
/// The picture is rasterized within the 0 (left), 0 (top), `width` (right),
/// `height` (bottom) bounds. Content outside these bounds is clipped.
///
/// The image object is created and returned synchronously, but is rasterized
/// asynchronously. If the rasterization fails, an exception will be thrown
/// when the image is drawn to a [Canvas].
///
/// If a GPU context is available, this image will be created as GPU resident
/// and not copied back to the host. This means the image will be more
/// efficient to draw.
///
/// If no GPU context is availalbe, the image will be rasterized on the CPU.
/// {@endtemplate}
Image toImageSync(int width, int height) {
assert(!_disposed);
if (width <= 0 || height <= 0) {
throw Exception('Invalid image dimensions.');
}

final _Image image = _Image._();
_toImageSync(width, height, image);
return Image._(image, image.width, image.height);
}
void _toImageSync(int width, int height, _Image outImage) native 'Picture_toImageSync';

/// Release the resources used by this object. The object is no longer usable
/// after this method is called.
void dispose() {
Expand Down Expand Up @@ -5912,7 +5883,7 @@ Future<T> _futurize<T>(_Callbacker<T> callbacker) {
}

/// An exception thrown by [Canvas.drawImage] and related methods when drawing
/// an [Image] created via [Picture.toImageSync] that is in an invalid state.
/// an [Image] that is in an invalid state.
///
/// This exception may be thrown if the requested image dimensions exceeded the
/// maximum 2D texture size allowed by the GPU, or if no GPU surface or context
Expand Down
41 changes: 0 additions & 41 deletions lib/ui/painting/picture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ IMPLEMENT_WRAPPERTYPEINFO(ui, Picture);

#define FOR_EACH_BINDING(V) \
V(Picture, toImage) \
V(Picture, toImageSync) \
V(Picture, dispose) \
V(Picture, GetAllocationSize)

Expand Down Expand Up @@ -53,46 +52,6 @@ Dart_Handle Picture::toImage(uint32_t width,
raw_image_callback);
}

void Picture::toImageSync(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle) {
FML_DCHECK(display_list_.skia_object());
RasterizeToImageSync(display_list_.skia_object(), width, height,
raw_image_handle);
}

// static
void Picture::RasterizeToImageSync(sk_sp<DisplayList> display_list,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle) {
auto* dart_state = UIDartState::Current();
auto unref_queue = dart_state->GetSkiaUnrefQueue();
auto snapshot_delegate = dart_state->GetSnapshotDelegate();
auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();

auto image = CanvasImage::Create();
auto dl_image = DlDeferredImageGPU::Make(SkISize::Make(width, height));
image->set_image(dl_image);

fml::TaskRunner::RunNowOrPostTask(
raster_task_runner,
[snapshot_delegate, unref_queue, dl_image = std::move(dl_image),
display_list = std::move(display_list)]() {
sk_sp<SkImage> sk_image;
std::string error;
std::tie(sk_image, error) = snapshot_delegate->MakeGpuImage(
display_list, dl_image->dimensions());
if (sk_image) {
dl_image->set_image(std::move(sk_image));
} else {
dl_image->set_error(std::move(error));
}
});

image->AssociateWithDartWrapper(raw_image_handle);
}

void Picture::dispose() {
display_list_.reset();
ClearDartWrapper();
Expand Down
9 changes: 0 additions & 9 deletions lib/ui/painting/picture.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,12 @@ class Picture : public RefCountedDartWrappable<Picture> {
uint32_t height,
Dart_Handle raw_image_callback);

void toImageSync(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle);

void dispose();

size_t GetAllocationSize() const override;

static void RegisterNatives(tonic::DartLibraryNatives* natives);

static void RasterizeToImageSync(sk_sp<DisplayList> display_list,
uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle);

static Dart_Handle RasterizeToImage(sk_sp<DisplayList> display_list,
uint32_t width,
uint32_t height,
Expand Down
1 change: 0 additions & 1 deletion lib/web_ui/lib/canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ abstract class Canvas {

abstract class Picture {
Future<Image> toImage(int width, int height);
Image toImageSync(int width, int height);
void dispose();
bool get debugDisposed;
int get approximateBytesUsed;
Expand Down
1 change: 0 additions & 1 deletion lib/web_ui/lib/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ part of ui;

abstract class Scene {
Future<Image> toImage(int width, int height);
Image toImageSync(int width, int height);
void dispose();
}

Expand Down
6 changes: 0 additions & 6 deletions lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ class LayerScene implements ui.Scene {
final ui.Picture picture = layerTree.flatten();
return picture.toImage(width, height);
}

@override
ui.Image toImageSync(int width, int height) {
final ui.Picture picture = layerTree.flatten();
return picture.toImageSync(width, height);
}
}

class LayerSceneBuilder implements ui.SceneBuilder {
Expand Down
5 changes: 0 additions & 5 deletions lib/web_ui/lib/src/engine/canvaskit/picture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,6 @@ class CkPicture extends ManagedSkiaObject<SkPicture> implements ui.Picture {

@override
Future<ui.Image> toImage(int width, int height) async {
return toImageSync(width, height);
}

@override
ui.Image toImageSync(int width, int height) {
assert(debugCheckNotDisposed('Cannot convert picture to image.'));
final SkSurface skSurface = canvasKit.MakeSurface(width, height);
final SkCanvas skCanvas = skSurface.getCanvas();
Expand Down
5 changes: 0 additions & 5 deletions lib/web_ui/lib/src/engine/html/scene.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ class SurfaceScene implements ui.Scene {
throw UnsupportedError('toImage is not supported on the Web');
}

@override
ui.Image toImageSync(int width, int height) {
throw UnsupportedError('toImageSync is not supported on the Web');
}

/// Releases the resources used by this scene.
///
/// After calling this function, the scene is cannot be used further.
Expand Down
5 changes: 0 additions & 5 deletions lib/web_ui/lib/src/engine/picture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ class EnginePicture implements ui.Picture {
return onImageLoaded.future;
}

@override
ui.Image toImageSync(int width, int height) {
throw UnsupportedError('toImageSync is not supported on the HTML backend. Use drawPicture instead, or toImage.');
}

bool _disposed = false;

@override
Expand Down
19 changes: 0 additions & 19 deletions lib/web_ui/test/canvaskit/picture_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';

import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -85,23 +83,6 @@ void testMain() {
expect(picture.resurrect(), isNotNull);
});
});

test('toImageSync', () async {
const ui.Color color = ui.Color(0xFFAAAAAA);
final ui.PictureRecorder recorder = ui.PictureRecorder();
final ui.Canvas canvas = ui.Canvas(recorder);
canvas.drawPaint(ui.Paint()..color = color);
final ui.Picture picture = recorder.endRecording();
final ui.Image image = picture.toImageSync(10, 15);

expect(image.width, 10);
expect(image.height, 15);

final ByteData? data = await image.toByteData();
expect(data, isNotNull);
expect(data!.lengthInBytes, 10 * 15 * 4);
expect(data.buffer.asUint32List().first, color.value);
});
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/60040
}, skip: isIosSafari);
}
23 changes: 0 additions & 23 deletions shell/common/fixtures/shell_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -321,26 +321,3 @@ void scene_with_red_box() {
};
PlatformDispatcher.instance.scheduleFrame();
}


@pragma('vm:entry-point')
Future<void> toImageSync() async {
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
canvas.drawPaint(Paint()..color = const Color(0xFFAAAAAA));
final Picture picture = recorder.endRecording();

final Image image = picture.toImageSync(20, 25);
void expect(Object? a, Object? b) {
if (a != b) {
throw 'Expected $a to == $b';
}
}
expect(image.width, 20);
expect(image.height, 25);

final ByteData data = (await image.toByteData())!;
expect(data.lengthInBytes, 20 * 25 * 4);
expect(data.buffer.asUint32List().every((int byte) => byte == 0xFFAAAAAA), true);
notifyNative();
}
34 changes: 0 additions & 34 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3754,40 +3754,6 @@ TEST_F(ShellTest, SpawnWorksWithOnError) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
}

TEST_F(ShellTest, PictureToImageSync) {
#if !SHELL_ENABLE_GL
// GL emulation does not exist on Fuchsia.
GTEST_SKIP();
#endif // !SHELL_ENABLE_GL
auto settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell =
CreateShell(settings, //
GetTaskRunnersForFixture(), //
false, //
nullptr, //
false, //
ShellTestPlatformView::BackendType::kGLBackend //
);

fml::AutoResetWaitableEvent latch;
AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&latch](auto args) {
latch.Signal();
}));

ASSERT_NE(shell, nullptr);
ASSERT_TRUE(shell->IsSetup());
auto configuration = RunConfiguration::InferFromSettings(settings);
PlatformViewNotifyCreated(shell.get());
configuration.SetEntrypoint("toImageSync");
RunEngine(shell.get(), std::move(configuration));
PumpOneFrame(shell.get());

latch.Wait();

PlatformViewNotifyDestroyed(shell.get());
DestroyShell(std::move(shell));
}

} // namespace testing
} // namespace flutter

Expand Down
Loading