blob: c2224e507a55b13aef26063d20481a33f64a46cd [file] [log] [blame]
// Copyright 2015 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_ASYNC_BLOB_CREATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_ASYNC_BLOB_CREATOR_H_
#include <memory>
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/canvas/image_encode_options.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
class ExecutionContext;
constexpr const char* kSRGBImageColorSpaceName = "srgb";
constexpr const char* kRec2020ImageColorSpaceName = "rec2020";
constexpr const char* kDisplayP3ImageColorSpaceName = "display-p3";
constexpr const char* kRGBA8ImagePixelFormatName = "uint8";
constexpr const char* kRGBA16ImagePixelFormatName = "uint16";
class CORE_EXPORT CanvasAsyncBlobCreator
: public GarbageCollectedFinalized<CanvasAsyncBlobCreator> {
public:
// This enum is used to back an UMA histogram, and should therefore be treated
// as append-only. Idle tasks are not implemented for some image types.
enum IdleTaskStatus {
kIdleTaskNotStarted = 0,
kIdleTaskStarted = 1,
kIdleTaskCompleted = 2,
kIdleTaskFailed = 3,
kIdleTaskSwitchedToImmediateTask = 4,
kIdleTaskNotSupported = 5,
kMaxValue = kIdleTaskNotSupported,
};
enum ToBlobFunctionType {
kHTMLCanvasToBlobCallback,
kHTMLCanvasConvertToBlobPromise,
kOffscreenCanvasConvertToBlobPromise,
kNumberOfToBlobFunctionTypes
};
static CanvasAsyncBlobCreator* Create(scoped_refptr<StaticBitmapImage>,
const ImageEncodingMimeType mime_type,
V8BlobCallback*,
ToBlobFunctionType function_type,
TimeTicks start_time,
ExecutionContext*);
static CanvasAsyncBlobCreator* Create(scoped_refptr<StaticBitmapImage>,
const ImageEncodeOptions* options,
ToBlobFunctionType function_type,
TimeTicks start_time,
ExecutionContext*,
ScriptPromiseResolver*);
void ScheduleAsyncBlobCreation(const double& quality);
CanvasAsyncBlobCreator(scoped_refptr<StaticBitmapImage>,
const ImageEncodeOptions*,
ToBlobFunctionType,
V8BlobCallback*,
TimeTicks start_time,
ExecutionContext*,
ScriptPromiseResolver*);
virtual ~CanvasAsyncBlobCreator();
// Methods are virtual for mocking in unit tests
virtual void SignalTaskSwitchInStartTimeoutEventForTesting() {}
virtual void SignalTaskSwitchInCompleteTimeoutEventForTesting() {}
virtual void Trace(Visitor*);
static sk_sp<SkColorSpace> BlobColorSpaceToSkColorSpace(
String blob_color_space);
bool EncodeImageForConvertToBlobTest();
Vector<unsigned char> GetEncodedImageForConvertToBlobTest() {
return encoded_image_;
}
protected:
static ImageEncodeOptions* GetImageEncodeOptionsForMimeType(
ImageEncodingMimeType);
// Methods are virtual for unit testing
virtual void ScheduleInitiateEncoding(double quality);
virtual void IdleEncodeRows(TimeTicks deadline);
virtual void PostDelayedTaskToCurrentThread(const base::Location&,
base::OnceClosure,
double delay_ms);
virtual void SignalAlternativeCodePathFinishedForTesting() {}
virtual void CreateBlobAndReturnResult();
virtual void CreateNullAndReturnResult();
void InitiateEncoding(double quality, TimeTicks deadline);
protected:
IdleTaskStatus idle_task_status_;
bool fail_encoder_initialization_for_test_;
bool enforce_idle_encoding_for_test_;
private:
friend class CanvasAsyncBlobCreatorTest;
void Dispose();
scoped_refptr<StaticBitmapImage> image_;
std::unique_ptr<ImageEncoder> encoder_;
Vector<unsigned char> encoded_image_;
int num_rows_completed_;
Member<ExecutionContext> context_;
SkPixmap src_data_;
ImageEncodingMimeType mime_type_;
Member<const ImageEncodeOptions> encode_options_;
ToBlobFunctionType function_type_;
sk_sp<SkData> png_data_helper_;
// Chrome metrics use
TimeTicks start_time_;
TimeTicks schedule_idle_task_start_time_;
bool static_bitmap_image_loaded_;
// Used when CanvasAsyncBlobCreator runs on main thread only
scoped_refptr<base::SingleThreadTaskRunner> parent_frame_task_runner_;
// Used for HTMLCanvasElement only
//
// Note: CanvasAsyncBlobCreator is never held by other objects. As soon as
// an instance gets created, ScheduleAsyncBlobCreation is invoked, and then
// the instance is only held by a task runner (via PostTask). Thus the
// instance has only limited lifetime. Hence, Persistent here is okay.
Member<V8PersistentCallbackFunction<V8BlobCallback>> callback_;
// Used for OffscreenCanvas only
Member<ScriptPromiseResolver> script_promise_resolver_;
bool EncodeImage(const double&);
// PNG, JPEG
bool InitializeEncoder(double quality);
void ForceEncodeRowsOnCurrentThread(); // Similar to IdleEncodeRows
// without deadline
// WEBP
void EncodeImageOnEncoderThread(double quality);
void IdleTaskStartTimeoutEvent(double quality);
void IdleTaskCompleteTimeoutEvent();
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_ASYNC_BLOB_CREATOR_H_