Flutter Engine
picture.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/lib/ui/painting/picture.h"
6 
7 #include <memory>
8 
9 #include "flutter/fml/make_copyable.h"
10 #include "flutter/lib/ui/painting/canvas.h"
11 #include "flutter/lib/ui/ui_dart_state.h"
12 #include "third_party/skia/include/core/SkImage.h"
19 
20 namespace flutter {
21 
22 IMPLEMENT_WRAPPERTYPEINFO(ui, Picture);
23 
24 #define FOR_EACH_BINDING(V) \
25  V(Picture, toImage) \
26  V(Picture, dispose) \
27  V(Picture, GetAllocationSize)
28 
30 
31 fml::RefPtr<Picture> Picture::Create(
32  Dart_Handle dart_handle,
33  flutter::SkiaGPUObject<SkPicture> picture) {
34  auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(picture));
35 
36  canvas_picture->AssociateWithDartWrapper(dart_handle);
37  return canvas_picture;
38 }
39 
40 Picture::Picture(flutter::SkiaGPUObject<SkPicture> picture)
41  : picture_(std::move(picture)) {}
42 
43 Picture::~Picture() = default;
44 
45 Dart_Handle Picture::toImage(uint32_t width,
46  uint32_t height,
47  Dart_Handle raw_image_callback) {
48  if (!picture_.get()) {
49  return tonic::ToDart("Picture is null");
50  }
51 
52  return RasterizeToImage(picture_.get(), width, height, raw_image_callback);
53 }
54 
56  picture_.reset();
58 }
59 
61  if (auto picture = picture_.get()) {
62  return picture->approximateBytesUsed() + sizeof(Picture);
63  } else {
64  return sizeof(Picture);
65  }
66 }
67 
68 Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
69  uint32_t width,
70  uint32_t height,
71  Dart_Handle raw_image_callback) {
72  if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) {
73  return tonic::ToDart("Image callback was invalid");
74  }
75 
76  if (width == 0 || height == 0) {
77  return tonic::ToDart("Image dimensions for scene were invalid.");
78  }
79 
80  auto* dart_state = UIDartState::Current();
81  auto image_callback = std::make_unique<tonic::DartPersistentValue>(
82  dart_state, raw_image_callback);
83  auto unref_queue = dart_state->GetSkiaUnrefQueue();
84  auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
85  auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
86  auto snapshot_delegate = dart_state->GetSnapshotDelegate();
87 
88  // We can't create an image on this task runner because we don't have a
89  // graphics context. Even if we did, it would be slow anyway. Also, this
90  // thread owns the sole reference to the layer tree. So we flatten the layer
91  // tree into a picture and use that as the thread transport mechanism.
92 
93  auto picture_bounds = SkISize::Make(width, height);
94 
95  auto ui_task = fml::MakeCopyable([image_callback = std::move(image_callback),
96  unref_queue](
97  sk_sp<SkImage> raster_image) mutable {
98  auto dart_state = image_callback->dart_state().lock();
99  if (!dart_state) {
100  // The root isolate could have died in the meantime.
101  return;
102  }
103  tonic::DartState::Scope scope(dart_state);
104 
105  if (!raster_image) {
106  tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
107  return;
108  }
109 
110  auto dart_image = CanvasImage::Create();
111  dart_image->set_image({std::move(raster_image), std::move(unref_queue)});
112  auto* raw_dart_image = tonic::ToDart(std::move(dart_image));
113 
114  // All done!
115  tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
116 
117  // image_callback is associated with the Dart isolate and must be deleted
118  // on the UI thread.
119  image_callback.reset();
120  });
121 
122  // Kick things off on the raster rask runner.
124  raster_task_runner,
125  [ui_task_runner, snapshot_delegate, picture, picture_bounds, ui_task] {
126  sk_sp<SkImage> raster_image =
127  snapshot_delegate->MakeRasterSnapshot(picture, picture_bounds);
128 
130  ui_task_runner,
131  [ui_task, raster_image]() { ui_task(raster_image); });
132  });
133 
134  return Dart_Null();
135 }
136 
137 } // namespace flutter
~Picture() override
#define DART_BIND_ALL(CLASS, FOR_EACH)
sk_sp< SkiaObjectType > get() const
static void RunNowOrPostTask(fml::RefPtr< fml::TaskRunner > runner, const fml::closure &task)
Definition: task_runner.cc:55
Dart_Handle DartInvoke(Dart_Handle closure, std::initializer_list< Dart_Handle > args)
Definition: dart_invoke.cc:20
size_t GetAllocationSize() const override
Definition: picture.cc:60
Definition: ascii_trie.cc:9
void dispose()
Definition: picture.cc:55
static fml::RefPtr< CanvasImage > Create()
Definition: image.h:25
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene)
int32_t height
void AssociateWithDartWrapper(Dart_Handle wrappable)
int32_t width
#define FOR_EACH_BINDING(V)
Definition: picture.cc:24
Dart_Handle ToDart(const T &object)
Dart_Handle toImage(uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition: picture.cc:45
static UIDartState * Current()
static Dart_Handle RasterizeToImage(sk_sp< SkPicture > picture, uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition: picture.cc:68