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
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ FILE: ../../../flutter/lib/ui/painting/color_filter.cc
FILE: ../../../flutter/lib/ui/painting/color_filter.h
FILE: ../../../flutter/lib/ui/painting/engine_layer.cc
FILE: ../../../flutter/lib/ui/painting/engine_layer.h
FILE: ../../../flutter/lib/ui/painting/frame_info.cc
FILE: ../../../flutter/lib/ui/painting/frame_info.h
FILE: ../../../flutter/lib/ui/painting/gradient.cc
FILE: ../../../flutter/lib/ui/painting/gradient.h
FILE: ../../../flutter/lib/ui/painting/image.cc
Expand Down
2 changes: 2 additions & 0 deletions lib/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ source_set("ui") {
"painting/color_filter.h",
"painting/engine_layer.cc",
"painting/engine_layer.h",
"painting/frame_info.cc",
"painting/frame_info.h",
"painting/gradient.cc",
"painting/gradient.h",
"painting/image.cc",
Expand Down
8 changes: 3 additions & 5 deletions lib/ui/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ class Scene extends NativeFieldWrapperClass2 {

/// Creates a raster image representation of the current state of the scene.
/// This is a slow operation that is performed on a background thread.
Future<Image> toImage(int width, int height) async {
Future<Image> toImage(int width, int height) {
if (width <= 0 || height <= 0) {
throw Exception('Invalid image dimensions.');
}
final Image image = Image._();
await _futurize((_Callback<bool> callback) => _toImage(image, width, height, callback));
return image;
return _futurize((_Callback<Image> callback) => _toImage(width, height, callback));
}

String _toImage(Image outImage, int width, int height, _Callback<bool> callback) native 'Scene_toImage';
String _toImage(int width, int height, _Callback<Image> callback) native 'Scene_toImage';

/// Releases the resources used by this scene.
///
Expand Down
6 changes: 2 additions & 4 deletions lib/ui/compositing/scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ void Scene::dispose() {
ClearDartWrapper();
}

Dart_Handle Scene::toImage(Dart_Handle image_handle,
uint32_t width,
Dart_Handle Scene::toImage(uint32_t width,
uint32_t height,
Dart_Handle raw_image_callback) {
TRACE_EVENT0("flutter", "Scene::toImage");
Expand All @@ -76,8 +75,7 @@ Dart_Handle Scene::toImage(Dart_Handle image_handle,
return tonic::ToDart("Could not flatten scene into a layer tree.");
}

return Picture::RasterizeToImage(image_handle, picture, width, height,
raw_image_callback);
return Picture::RasterizeToImage(picture, width, height, raw_image_callback);
}

std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() {
Expand Down
3 changes: 1 addition & 2 deletions lib/ui/compositing/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ class Scene : public RefCountedDartWrappable<Scene> {

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

Dart_Handle toImage(Dart_Handle image_handle,
uint32_t width,
Dart_Handle toImage(uint32_t width,
uint32_t height,
Dart_Handle image_callback);

Expand Down
2 changes: 2 additions & 0 deletions lib/ui/dart_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "flutter/lib/ui/painting/codec.h"
#include "flutter/lib/ui/painting/color_filter.h"
#include "flutter/lib/ui/painting/engine_layer.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/painting/gradient.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/image_filter.h"
Expand Down Expand Up @@ -79,6 +80,7 @@ void DartUI::InitForGlobal() {
DartRuntimeHooks::RegisterNatives(g_natives);
EngineLayer::RegisterNatives(g_natives);
FontCollection::RegisterNatives(g_natives);
FrameInfo::RegisterNatives(g_natives);
ImageFilter::RegisterNatives(g_natives);
ImageShader::RegisterNatives(g_natives);
IsolateNameServerNatives::RegisterNatives(g_natives);
Expand Down
63 changes: 25 additions & 38 deletions lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1639,19 +1639,22 @@ typedef ImageDecoderCallback = void Function(Image result);
///
/// To obtain an instance of the [FrameInfo] interface, see
/// [Codec.getNextFrame].
class FrameInfo {
@pragma('vm:entry-point')
class FrameInfo extends NativeFieldWrapperClass2 {
/// This class is created by the engine, and should not be instantiated
/// or extended directly.
///
/// To obtain an instance of the [FrameInfo] interface, see
/// [Codec.getNextFrame].
FrameInfo._(int durationMilliseconds, this.image) : duration = Duration(milliseconds: durationMilliseconds);
@pragma('vm:entry-point')
FrameInfo._();

/// The duration this frame should be shown.
final Duration duration;
Duration get duration => Duration(milliseconds: _durationMillis);
int get _durationMillis native 'FrameInfo_durationMillis';

/// The [Image] object for this frame.
final Image image;
Image get image native 'FrameInfo_image';
}

/// A handle to an image codec.
Expand Down Expand Up @@ -1681,32 +1684,21 @@ class Codec extends NativeFieldWrapperClass2 {
/// * -1 for infinity repetitions.
int get repetitionCount native 'Codec_repetitionCount';

FrameInfo _cachedFrame;

/// Fetches the next animation frame.
///
/// Wraps back to the first frame after returning the last frame.
///
/// The returned future can complete with an error if the decoding has failed.
Future<FrameInfo> getNextFrame() async {
if (_cachedFrame == null || frameCount != 1) {
final Image image = Image._();
final int durationMilliseconds = await _futurize((_Callback<int> callback) => _getNextFrame(image, callback));
_cachedFrame = FrameInfo._(durationMilliseconds, image);
}
return _cachedFrame;
Future<FrameInfo> getNextFrame() {
return _futurize(_getNextFrame);
}

/// Returns an error message on failure, null on success.
String _getNextFrame(Image outImage, _Callback<int> callback) native 'Codec_getNextFrame';
String _getNextFrame(_Callback<FrameInfo> callback) native 'Codec_getNextFrame';

/// Release the resources used by this object. The object is no longer usable
/// after this method is called.
void dispose() {
_cachedFrame = null;
_dispose();
}
void _dispose() native 'Codec_dispose';
void dispose() native 'Codec_dispose';
}

/// Instantiates an image codec [Codec] object.
Expand All @@ -1726,12 +1718,10 @@ class Codec extends NativeFieldWrapperClass2 {
Future<Codec> instantiateImageCodec(Uint8List list, {
int targetWidth,
int targetHeight,
}) async {
final Codec codec = Codec._();
await _futurize((_Callback<bool> callback) {
return _instantiateImageCodec(codec, list, callback, null, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension);
});
return codec;
}) {
return _futurize(
(_Callback<Codec> callback) => _instantiateImageCodec(list, callback, null, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
);
}

/// Instantiates a [Codec] object for an image binary data.
Expand All @@ -1745,7 +1735,7 @@ Future<Codec> instantiateImageCodec(Uint8List list, {
/// If both are equal to [_kDoNotResizeDimension], then the image maintains its real size.
///
/// Returns an error message if the instantiation has failed, null otherwise.
String _instantiateImageCodec(Codec outCodec, Uint8List list, _Callback<bool> callback, _ImageInfo imageInfo, int targetWidth, int targetHeight)
String _instantiateImageCodec(Uint8List list, _Callback<Codec> callback, _ImageInfo imageInfo, int targetWidth, int targetHeight)
native 'instantiateImageCodec';

/// Loads a single image frame from a byte array into an [Image] object.
Expand Down Expand Up @@ -1786,12 +1776,11 @@ void decodeImageFromPixels(
{int rowBytes, int targetWidth, int targetHeight}
) {
final _ImageInfo imageInfo = _ImageInfo(width, height, format.index, rowBytes);
final Codec codec = Codec._();
_futurize(
(_Callback<bool> callback) => _instantiateImageCodec(codec, pixels, callback, imageInfo, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
).then((bool _) {
codec.getNextFrame().then((FrameInfo frameInfo) => callback(frameInfo.image));
});
final Future<Codec> codecFuture = _futurize(
(_Callback<Codec> callback) => _instantiateImageCodec(pixels, callback, imageInfo, targetWidth ?? _kDoNotResizeDimension, targetHeight ?? _kDoNotResizeDimension)
);
codecFuture.then((Codec codec) => codec.getNextFrame())
.then((FrameInfo frameInfo) => callback(frameInfo.image));
}

/// Determines the winding rule that decides how the interior of a [Path] is
Expand Down Expand Up @@ -4136,17 +4125,15 @@ class Picture extends NativeFieldWrapperClass2 {
///
/// Although the image is returned synchronously, the picture is actually
/// rasterized the first time the image is drawn and then cached.
Future<Image> toImage(int width, int height) async {
Future<Image> toImage(int width, int height) {
if (width <= 0 || height <= 0)
throw Exception('Invalid image dimensions.');
final Image image = Image._();
await _futurize(
(_Callback<bool> callback) => _toImage(image, width, height, callback)
return _futurize(
(_Callback<Image> callback) => _toImage(width, height, callback)
);
return image;
}

String _toImage(Image outImage, int width, int height, _Callback<bool> callback) native 'Picture_toImage';
String _toImage(int width, int height, _Callback<Image> callback) native 'Picture_toImage';

/// Release the resources used by this object. The object is no longer usable
/// after this method is called.
Expand Down
23 changes: 12 additions & 11 deletions lib/ui/painting/codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/trace_event.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "flutter/lib/ui/painting/multi_frame_codec.h"
#include "flutter/lib/ui/painting/single_frame_codec.h"
#include "third_party/skia/include/codec/SkCodec.h"
Expand Down Expand Up @@ -144,14 +145,13 @@ static std::variant<ImageDecoder::ImageInfo, std::string> ConvertImageInfo(
}

static void InstantiateImageCodec(Dart_NativeArguments args) {
Dart_Handle codec_handle = Dart_GetNativeArgument(args, 0);
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 2);
Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
if (!Dart_IsClosure(callback_handle)) {
Dart_SetReturnValue(args, tonic::ToDart("Callback must be a function"));
return;
}

Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 3);
Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 2);

std::optional<ImageDecoder::ImageInfo> image_info;

Expand All @@ -171,7 +171,7 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
{
Dart_Handle exception = nullptr;
tonic::Uint8List list =
tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 1,
tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 0,
exception);
if (exception) {
Dart_SetReturnValue(args, exception);
Expand All @@ -191,9 +191,9 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
}

const int targetWidth =
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 4));
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 3));
const int targetHeight =
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 5));
tonic::DartConverter<int>::FromDart(Dart_GetNativeArgument(args, 4));

std::unique_ptr<SkCodec> codec;
bool single_frame;
Expand All @@ -208,6 +208,8 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
single_frame = codec->getFrameCount() == 1;
}

fml::RefPtr<Codec> ui_codec;

if (single_frame) {
ImageDecoder::ImageDescriptor descriptor;
descriptor.decompressed_image_info = image_info;
Expand All @@ -220,13 +222,12 @@ static void InstantiateImageCodec(Dart_NativeArguments args) {
}
descriptor.data = std::move(buffer);

SingleFrameCodec::Create(codec_handle, std::move(descriptor));
ui_codec = fml::MakeRefCounted<SingleFrameCodec>(std::move(descriptor));
} else {
MultiFrameCodec::Create(codec_handle, std::move(codec));
ui_codec = fml::MakeRefCounted<MultiFrameCodec>(std::move(codec));
}

tonic::DartInvoke(callback_handle, {Dart_True()});
Dart_SetReturnValue(args, Dart_Null());
tonic::DartInvoke(callback_handle, {ToDart(ui_codec)});
}

IMPLEMENT_WRAPPERTYPEINFO(ui, Codec);
Expand All @@ -245,7 +246,7 @@ void Codec::dispose() {

void Codec::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"instantiateImageCodec", InstantiateImageCodec, 6, true},
{"instantiateImageCodec", InstantiateImageCodec, 5, true},
});
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/painting/codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define FLUTTER_LIB_UI_PAINTING_CODEC_H_

#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
Expand All @@ -29,8 +30,7 @@ class Codec : public RefCountedDartWrappable<Codec> {

virtual int repetitionCount() const = 0;

virtual Dart_Handle getNextFrame(Dart_Handle image_handle,
Dart_Handle callback_handle) = 0;
virtual Dart_Handle getNextFrame(Dart_Handle callback_handle) = 0;

void dispose();

Expand Down
30 changes: 30 additions & 0 deletions lib/ui/painting/frame_info.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

// 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/frame_info.h"

#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, FrameInfo);

#define FOR_EACH_BINDING(V) \
V(FrameInfo, durationMillis) \
V(FrameInfo, image)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

FrameInfo::FrameInfo(fml::RefPtr<CanvasImage> image, int durationMillis)
: image_(std::move(image)), durationMillis_(durationMillis) {}

FrameInfo::~FrameInfo(){};

void FrameInfo::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

} // namespace flutter
37 changes: 37 additions & 0 deletions lib/ui/painting/frame_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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.

#ifndef FLUTTER_LIB_UI_PAINTING_FRAME_INFO_H_
#define FLUTTER_LIB_UI_PAINTING_FRAME_INFO_H_

#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/image.h"

namespace flutter {

// A single animation frame.
class FrameInfo final : public RefCountedDartWrappable<FrameInfo> {
DEFINE_WRAPPERTYPEINFO();

public:
int durationMillis() { return durationMillis_; }
fml::RefPtr<CanvasImage> image() { return image_; }

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

private:
FrameInfo(fml::RefPtr<CanvasImage> image, int durationMillis);

~FrameInfo() override;

const fml::RefPtr<CanvasImage> image_;
const int durationMillis_;

FML_FRIEND_MAKE_REF_COUNTED(FrameInfo);
FML_FRIEND_REF_COUNTED_THREAD_SAFE(FrameInfo);
};

} // namespace flutter

#endif // FLUTTER_LIB_UI_PAINTING_FRAME_INFO_H_
6 changes: 2 additions & 4 deletions lib/ui/painting/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ class CanvasImage final : public RefCountedDartWrappable<CanvasImage> {

public:
~CanvasImage() override;
static fml::RefPtr<CanvasImage> Create(Dart_Handle dart_handle) {
auto image = fml::MakeRefCounted<CanvasImage>();
image->AssociateWithDartWrapper(dart_handle);
return image;
static fml::RefPtr<CanvasImage> Create() {
return fml::MakeRefCounted<CanvasImage>();
}

int width() { return image_.get()->width(); }
Expand Down
Loading