44
55#include " flutter/lib/ui/painting/image_descriptor.h"
66
7+ #include " flutter/fml/build_config.h"
78#include " flutter/fml/logging.h"
89#include " flutter/fml/trace_event.h"
910#include " flutter/lib/ui/painting/codec.h"
1011#include " flutter/lib/ui/painting/image_decoder.h"
1112#include " flutter/lib/ui/painting/multi_frame_codec.h"
1213#include " flutter/lib/ui/painting/single_frame_codec.h"
1314#include " flutter/lib/ui/ui_dart_state.h"
14- #include " third_party/skia/src/codec/SkCodecImageGenerator.h"
1515#include " third_party/tonic/dart_binding_macros.h"
1616#include " third_party/tonic/logging/dart_invoke.h"
1717
18+ #ifdef OS_MACOSX
19+ #include " third_party/skia/include/ports/SkImageGeneratorCG.h"
20+ #define PLATFORM_IMAGE_GENERATOR (data ) \
21+ SkImageGeneratorCG::MakeFromEncodedCG (data)
22+ #elif OS_WIN
23+ #include " third_party/skia/include/ports/SkImageGeneratorWIC.h"
24+ #define PLATFORM_IMAGE_GENERATOR (data ) \
25+ SkImageGeneratorWIC::MakeFromEncodedWIC (data)
26+ #else
27+ #define PLATFORM_IMAGE_GENERATOR (data ) \
28+ std::unique_ptr<SkImageGenerator>(nullptr )
29+ #endif
30+
1831namespace flutter {
1932
2033IMPLEMENT_WRAPPERTYPEINFO (ui, ImageDescriptor);
@@ -35,17 +48,21 @@ void ImageDescriptor::RegisterNatives(tonic::DartLibraryNatives* natives) {
3548}
3649
3750const SkImageInfo ImageDescriptor::CreateImageInfo () const {
38- if (!generator_) {
39- return SkImageInfo::MakeUnknown ();
51+ if (generator_) {
52+ return generator_->getInfo ();
53+ }
54+ if (platform_image_generator_) {
55+ return platform_image_generator_->getInfo ();
4056 }
41- return generator_-> getInfo ();
57+ return SkImageInfo::MakeUnknown ();
4258}
4359
4460ImageDescriptor::ImageDescriptor (sk_sp<SkData> buffer,
4561 const SkImageInfo& image_info,
4662 std::optional<size_t > row_bytes)
4763 : buffer_(std::move(buffer)),
4864 generator_ (nullptr ),
65+ platform_image_generator_(nullptr ),
4966 image_info_(std::move(image_info)),
5067 row_bytes_(row_bytes) {}
5168
@@ -56,6 +73,15 @@ ImageDescriptor::ImageDescriptor(sk_sp<SkData> buffer,
5673 static_cast <SkCodecImageGenerator*>(
5774 SkCodecImageGenerator::MakeFromCodec (std::move(codec))
5875 .release()))),
76+ platform_image_generator_(nullptr ),
77+ image_info_(CreateImageInfo()),
78+ row_bytes_(std::nullopt ) {}
79+
80+ ImageDescriptor::ImageDescriptor (sk_sp<SkData> buffer,
81+ std::unique_ptr<SkImageGenerator> generator)
82+ : buffer_(std::move(buffer)),
83+ generator_(nullptr ),
84+ platform_image_generator_(std::move(generator)),
5985 image_info_(CreateImageInfo()),
6086 row_bytes_(std::nullopt ) {}
6187
@@ -77,15 +103,28 @@ void ImageDescriptor::initEncoded(Dart_NativeArguments args) {
77103 return ;
78104 }
79105
106+ // This call will succeed if Skia has a built-in codec for this.
107+ // If it fails, we will check if the platform knows how to decode this image.
80108 std::unique_ptr<SkCodec> codec =
81109 SkCodec::MakeFromData (immutable_buffer->data ());
110+ fml::RefPtr<ImageDescriptor> descriptor;
82111 if (!codec) {
83- Dart_SetReturnValue (args, tonic::ToDart (" Invalid image data" ));
84- return ;
112+ std::unique_ptr<SkImageGenerator> generator =
113+ PLATFORM_IMAGE_GENERATOR (immutable_buffer->data ());
114+ if (!generator) {
115+ // We don't have a Skia codec for this image, and the platform doesn't
116+ // know how to decode it.
117+ Dart_SetReturnValue (args, tonic::ToDart (" Invalid image data" ));
118+ return ;
119+ }
120+ descriptor = fml::MakeRefCounted<ImageDescriptor>(immutable_buffer->data (),
121+ std::move (generator));
122+ } else {
123+ descriptor = fml::MakeRefCounted<ImageDescriptor>(immutable_buffer->data (),
124+ std::move (codec));
85125 }
86126
87- auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
88- immutable_buffer->data (), std::move (codec));
127+ FML_DCHECK (descriptor);
89128
90129 descriptor->AssociateWithDartWrapper (descriptor_handle);
91130 tonic::DartInvoke (callback_handle, {Dart_TypeVoid ()});
@@ -128,4 +167,31 @@ void ImageDescriptor::instantiateCodec(Dart_Handle codec_handle,
128167 }
129168 ui_codec->AssociateWithDartWrapper (codec_handle);
130169}
170+
171+ sk_sp<SkImage> ImageDescriptor::image () const {
172+ SkBitmap bitmap;
173+ if (!bitmap.tryAllocPixels (image_info_)) {
174+ FML_LOG (ERROR) << " Failed to allocate memory for bitmap of size "
175+ << image_info_.computeMinByteSize () << " B" ;
176+ return nullptr ;
177+ }
178+
179+ const auto & pixmap = bitmap.pixmap ();
180+ if (!get_pixels (pixmap)) {
181+ FML_LOG (ERROR) << " Failed to get pixels for image." ;
182+ return nullptr ;
183+ }
184+ bitmap.setImmutable ();
185+ return SkImage::MakeFromBitmap (bitmap);
186+ }
187+
188+ bool ImageDescriptor::get_pixels (const SkPixmap& pixmap) const {
189+ if (generator_) {
190+ return generator_->getPixels (pixmap.info (), pixmap.writable_addr (),
191+ pixmap.rowBytes ());
192+ }
193+ FML_DCHECK (platform_image_generator_);
194+ return platform_image_generator_->getPixels (pixmap);
195+ }
196+
131197} // namespace flutter
0 commit comments