blob: 75f0ec1a93e57c99f65458cb87f93ce016c7b31a [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/lib/ui/painting/image_descriptor.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "flutter/lib/ui/painting/multi_frame_codec.h"
#include "flutter/lib/ui/painting/single_frame_codec.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/logging/dart_invoke.h"
namespace flutter {
IMPLEMENT_WRAPPERTYPEINFO(ui, ImageDescriptor);
#define FOR_EACH_BINDING(V) \
V(ImageDescriptor, initRaw) \
V(ImageDescriptor, instantiateCodec) \
V(ImageDescriptor, width) \
V(ImageDescriptor, height) \
V(ImageDescriptor, bytesPerPixel) \
V(ImageDescriptor, dispose)
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
void ImageDescriptor::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register(
{{"ImageDescriptor_initEncoded", ImageDescriptor::initEncoded, 3, true},
FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
const SkImageInfo ImageDescriptor::CreateImageInfo() const {
FML_DCHECK(generator_);
return generator_->GetInfo();
}
ImageDescriptor::ImageDescriptor(sk_sp<SkData> buffer,
const SkImageInfo& image_info,
std::optional<size_t> row_bytes)
: buffer_(std::move(buffer)),
generator_(nullptr),
image_info_(std::move(image_info)),
row_bytes_(row_bytes) {}
ImageDescriptor::ImageDescriptor(sk_sp<SkData> buffer,
std::shared_ptr<ImageGenerator> generator)
: buffer_(std::move(buffer)),
generator_(std::move(generator)),
image_info_(CreateImageInfo()),
row_bytes_(std::nullopt) {}
void ImageDescriptor::initEncoded(Dart_NativeArguments args) {
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 2);
if (!Dart_IsClosure(callback_handle)) {
Dart_SetReturnValue(args, tonic::ToDart("Callback must be a function"));
return;
}
Dart_Handle descriptor_handle = Dart_GetNativeArgument(args, 0);
ImmutableBuffer* immutable_buffer =
tonic::DartConverter<ImmutableBuffer*>::FromDart(
Dart_GetNativeArgument(args, 1));
if (!immutable_buffer) {
Dart_SetReturnValue(args,
tonic::ToDart("Buffer parameter must not be null"));
return;
}
// This has to be valid because this method is called from Dart.
auto dart_state = UIDartState::Current();
auto registry = dart_state->GetImageGeneratorRegistry();
if (!registry) {
Dart_SetReturnValue(
args, tonic::ToDart("Failed to access the internal image decoder "
"registry on this isolate. Please file a bug on "
"https://github.com/flutter/flutter/issues."));
return;
}
auto generator =
registry->CreateCompatibleGenerator(immutable_buffer->data());
if (!generator) {
// No compatible image decoder was found.
Dart_SetReturnValue(args, tonic::ToDart("Invalid image data"));
return;
}
auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
immutable_buffer->data(), std::move(generator));
FML_DCHECK(descriptor);
descriptor->AssociateWithDartWrapper(descriptor_handle);
tonic::DartInvoke(callback_handle, {Dart_TypeVoid()});
}
void ImageDescriptor::initRaw(Dart_Handle descriptor_handle,
fml::RefPtr<ImmutableBuffer> data,
int width,
int height,
int row_bytes,
PixelFormat pixel_format) {
SkColorType color_type = kUnknown_SkColorType;
switch (pixel_format) {
case PixelFormat::kRGBA8888:
color_type = kRGBA_8888_SkColorType;
break;
case PixelFormat::kBGRA8888:
color_type = kBGRA_8888_SkColorType;
break;
}
FML_DCHECK(color_type != kUnknown_SkColorType);
auto image_info =
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
data->data(), std::move(image_info),
row_bytes == -1 ? std::nullopt : std::optional<size_t>(row_bytes));
descriptor->AssociateWithDartWrapper(descriptor_handle);
}
void ImageDescriptor::instantiateCodec(Dart_Handle codec_handle,
int target_width,
int target_height) {
fml::RefPtr<Codec> ui_codec;
if (!generator_ || generator_->GetFrameCount() == 1) {
ui_codec = fml::MakeRefCounted<SingleFrameCodec>(
static_cast<fml::RefPtr<ImageDescriptor>>(this), target_width,
target_height);
} else {
ui_codec = fml::MakeRefCounted<MultiFrameCodec>(generator_);
}
ui_codec->AssociateWithDartWrapper(codec_handle);
}
sk_sp<SkImage> ImageDescriptor::image() const {
return generator_->GetImage();
}
bool ImageDescriptor::get_pixels(const SkPixmap& pixmap) const {
FML_DCHECK(generator_);
return generator_->GetPixels(pixmap.info(), pixmap.writable_addr(),
pixmap.rowBytes());
}
} // namespace flutter