Flutter Engine
image_descriptor.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/image_descriptor.h"
6 
7 #include "flutter/fml/build_config.h"
8 #include "flutter/fml/logging.h"
9 #include "flutter/fml/trace_event.h"
10 #include "flutter/lib/ui/painting/multi_frame_codec.h"
11 #include "flutter/lib/ui/painting/single_frame_codec.h"
12 #include "flutter/lib/ui/ui_dart_state.h"
15 
16 namespace flutter {
17 
18 IMPLEMENT_WRAPPERTYPEINFO(ui, ImageDescriptor);
19 
20 #define FOR_EACH_BINDING(V) \
21  V(ImageDescriptor, initRaw) \
22  V(ImageDescriptor, instantiateCodec) \
23  V(ImageDescriptor, width) \
24  V(ImageDescriptor, height) \
25  V(ImageDescriptor, bytesPerPixel) \
26  V(ImageDescriptor, dispose)
27 
29 
30 void ImageDescriptor::RegisterNatives(tonic::DartLibraryNatives* natives) {
31  natives->Register(
32  {{"ImageDescriptor_initEncoded", ImageDescriptor::initEncoded, 3, true},
34 }
35 
36 const SkImageInfo ImageDescriptor::CreateImageInfo() const {
37  FML_DCHECK(generator_);
38  return generator_->GetInfo();
39 }
40 
41 ImageDescriptor::ImageDescriptor(sk_sp<SkData> buffer,
42  const SkImageInfo& image_info,
43  std::optional<size_t> row_bytes)
44  : buffer_(std::move(buffer)),
45  generator_(nullptr),
46  image_info_(std::move(image_info)),
47  row_bytes_(row_bytes) {}
48 
49 ImageDescriptor::ImageDescriptor(sk_sp<SkData> buffer,
50  std::shared_ptr<ImageGenerator> generator)
51  : buffer_(std::move(buffer)),
52  generator_(std::move(generator)),
53  image_info_(CreateImageInfo()),
54  row_bytes_(std::nullopt) {}
55 
56 void ImageDescriptor::initEncoded(Dart_NativeArguments args) {
57  Dart_Handle callback_handle = Dart_GetNativeArgument(args, 2);
58  if (!Dart_IsClosure(callback_handle)) {
59  Dart_SetReturnValue(args, tonic::ToDart("Callback must be a function"));
60  return;
61  }
62 
63  Dart_Handle descriptor_handle = Dart_GetNativeArgument(args, 0);
64  ImmutableBuffer* immutable_buffer =
66  Dart_GetNativeArgument(args, 1));
67 
68  if (!immutable_buffer) {
69  Dart_SetReturnValue(args,
70  tonic::ToDart("Buffer parameter must not be null"));
71  return;
72  }
73 
74  // This has to be valid because this method is called from Dart.
75  auto dart_state = UIDartState::Current();
76  auto registry = dart_state->GetImageGeneratorRegistry();
77 
78  if (!registry) {
79  Dart_SetReturnValue(
80  args, tonic::ToDart("Failed to access the internal image decoder "
81  "registry on this isolate. Please file a bug on "
82  "https://github.com/flutter/flutter/issues."));
83  return;
84  }
85 
86  auto generator =
87  registry->CreateCompatibleGenerator(immutable_buffer->data());
88 
89  if (!generator) {
90  // No compatible image decoder was found.
91  Dart_SetReturnValue(args, tonic::ToDart("Invalid image data"));
92  return;
93  }
94 
95  auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
96  immutable_buffer->data(), std::move(generator));
97 
98  FML_DCHECK(descriptor);
99 
100  descriptor->AssociateWithDartWrapper(descriptor_handle);
101  tonic::DartInvoke(callback_handle, {Dart_TypeVoid()});
102 }
103 
104 void ImageDescriptor::initRaw(Dart_Handle descriptor_handle,
106  int width,
107  int height,
108  int row_bytes,
109  PixelFormat pixel_format) {
110  SkColorType color_type = kUnknown_SkColorType;
111  switch (pixel_format) {
112  case PixelFormat::kRGBA8888:
113  color_type = kRGBA_8888_SkColorType;
114  break;
115  case PixelFormat::kBGRA8888:
116  color_type = kBGRA_8888_SkColorType;
117  break;
118  }
119  FML_DCHECK(color_type != kUnknown_SkColorType);
120  auto image_info =
121  SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
122  auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
123  data->data(), std::move(image_info),
124  row_bytes == -1 ? std::nullopt : std::optional<size_t>(row_bytes));
125  descriptor->AssociateWithDartWrapper(descriptor_handle);
126 }
127 
128 void ImageDescriptor::instantiateCodec(Dart_Handle codec_handle,
129  int target_width,
130  int target_height) {
131  fml::RefPtr<Codec> ui_codec;
132  if (!generator_ || generator_->GetFrameCount() == 1) {
133  ui_codec = fml::MakeRefCounted<SingleFrameCodec>(
134  static_cast<fml::RefPtr<ImageDescriptor>>(this), target_width,
135  target_height);
136  } else {
137  ui_codec = fml::MakeRefCounted<MultiFrameCodec>(generator_);
138  }
139  ui_codec->AssociateWithDartWrapper(codec_handle);
140 }
141 
142 sk_sp<SkImage> ImageDescriptor::image() const {
143  return generator_->GetImage();
144 }
145 
146 bool ImageDescriptor::get_pixels(const SkPixmap& pixmap) const {
147  FML_DCHECK(generator_);
148  return generator_->GetPixels(pixmap.info(), pixmap.writable_addr(),
149  pixmap.rowBytes());
150 }
151 
152 } // namespace flutter
G_BEGIN_DECLS FlValue * args
#define FOR_EACH_BINDING(V)
sk_sp< SkData > data() const
Callers should not modify the returned data. This is not exposed to Dart.
sk_sp< SkImage > image() const
#define FML_DCHECK(condition)
Definition: logging.h:86
uint32_t color_type
#define DART_NATIVE_CALLBACK(CLASS, METHOD)
Dart_Handle DartInvoke(Dart_Handle closure, std::initializer_list< Dart_Handle > args)
Definition: dart_invoke.cc:20
static void initEncoded(Dart_NativeArguments args)
Asynchronously initlializes an ImageDescriptor for an encoded image, as long as the format is recogni...
Creates an image descriptor for encoded or decoded image data, describing the width, height, and bytes per pixel for that image. This class will hold a reference on the underlying image data, and in the case of compressed data, an ImageGenerator for the data. The Codec initialization actually happens in initEncoded, making initstantiateCodec a lightweight operation.
static void initRaw(Dart_Handle descriptor_handle, fml::RefPtr< ImmutableBuffer > data, int width, int height, int row_bytes, PixelFormat pixel_format)
Synchronously initializes an ImageDescriptor for decompressed image data as specified by the PixelFor...
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene)
int row_bytes() const
The byte length of the first row of the image. Defaults to width() * 4.
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data observatory The hostname IP address on which the Dart Observatory should be served If not defaults to or::depending on whether ipv6 is specified disable Disable the Dart Observatory The observatory is never available in release mode Bind to the IPv6 localhost address for the Dart Observatory Ignored if observatory host is set endless trace buffer
Definition: switches.h:98
sk_sp< SkData > data() const
The underlying buffer for this image.
const SkImageInfo & image_info() const
The orientation corrected image info for this image.
int height() const
The height of this image. EXIF oriented if applicable.
void instantiateCodec(Dart_Handle codec, int target_width, int target_height)
Associates a flutter::Codec object with the dart.ui Codec handle.
#define DART_REGISTER_NATIVE(CLASS, METHOD)
int width() const
The width of this image, EXIF oriented if applicable.
Dart_Handle ToDart(const T &object)
bool get_pixels(const SkPixmap &pixmap) const
Gets pixels for this image transformed based on the EXIF orientation tag, if applicable.
static UIDartState * Current()