mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibWeb: Implement HTMLCanvasElement.toBlob()
This commit is contained in:
parent
3239f0fb7b
commit
b731705fec
Notes:
sideshowbarker
2024-07-17 03:51:15 +09:00
Author: https://github.com/krkk Commit: https://github.com/SerenityOS/serenity/commit/b731705fec Pull-request: https://github.com/SerenityOS/serenity/pull/20341 Reviewed-by: https://github.com/kennethmyhra
4 changed files with 52 additions and 1 deletions
|
@ -44,6 +44,9 @@ public:
|
|||
// Some elements, such as the HTMLMediaElement, must have a unique task source per instance.
|
||||
// Keep this field last, to serve as the base value of all unique task sources.
|
||||
UniqueTaskSourceStart,
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#canvas-blob-serialisation-task-source
|
||||
CanvasBlobSerializationTask,
|
||||
};
|
||||
|
||||
static NonnullOwnPtr<Task> create(Source source, DOM::Document const* document, JS::SafeFunction<void()> steps)
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
#include <AK/Checked.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/ImageFormats/PNGWriter.h>
|
||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/CSS/StyleComputer.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
|
||||
#include <LibWeb/HTML/HTMLCanvasElement.h>
|
||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||
#include <LibWeb/Layout/CanvasBox.h>
|
||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||
#include <LibWeb/WebIDL/AbstractOperations.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
|
@ -219,6 +223,47 @@ DeprecatedString HTMLCanvasElement::to_data_url(DeprecatedString const& type, Op
|
|||
return AK::URL::create_with_data(file.value().mime_type, base64_encoded_or_error.release_value(), true).to_deprecated_string();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-toblob
|
||||
WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(JS::NonnullGCPtr<WebIDL::CallbackType> callback, DeprecatedString const& type, Optional<double> quality)
|
||||
{
|
||||
// FIXME: 1. If this canvas element's bitmap's origin-clean flag is set to false, then throw a "SecurityError" DOMException.
|
||||
|
||||
// 2. Let result be null.
|
||||
RefPtr<Gfx::Bitmap> bitmap_result;
|
||||
|
||||
// 3. If this canvas element's bitmap has pixels (i.e., neither its horizontal dimension nor its vertical dimension is zero),
|
||||
// then set result to a copy of this canvas element's bitmap.
|
||||
if (m_bitmap)
|
||||
bitmap_result = TRY_OR_THROW_OOM(vm(), m_bitmap->clone());
|
||||
|
||||
// 4. Run these steps in parallel:
|
||||
Platform::EventLoopPlugin::the().deferred_invoke([this, callback, bitmap_result, type, quality] {
|
||||
// 1. If result is non-null, then set result to a serialization of result as a file with type and quality if given.
|
||||
Optional<SerializeBitmapResult> file_result;
|
||||
if (bitmap_result) {
|
||||
if (auto result = serialize_bitmap(*bitmap_result, type, move(quality)); !result.is_error())
|
||||
file_result = result.release_value();
|
||||
}
|
||||
|
||||
// 2. Queue an element task on the canvas blob serialization task source given the canvas element to run these steps:
|
||||
queue_an_element_task(Task::Source::CanvasBlobSerializationTask, [this, callback, file_result = move(file_result)] {
|
||||
auto maybe_error = Bindings::throw_dom_exception_if_needed(vm(), [&]() -> WebIDL::ExceptionOr<void> {
|
||||
// 1. If result is non-null, then set result to a new Blob object, created in the relevant realm of this canvas element, representing result. [FILEAPI]
|
||||
JS::GCPtr<FileAPI::Blob> blob_result;
|
||||
if (file_result.has_value())
|
||||
blob_result = TRY(FileAPI::Blob::create(realm(), file_result->buffer, TRY_OR_THROW_OOM(vm(), String::from_utf8(file_result->mime_type))));
|
||||
|
||||
// 2. Invoke callback with « result ».
|
||||
TRY(WebIDL::invoke_callback(*callback, {}, move(blob_result)));
|
||||
return {};
|
||||
});
|
||||
if (maybe_error.is_throw_completion())
|
||||
report_exception(maybe_error.throw_completion(), realm());
|
||||
});
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
void HTMLCanvasElement::present()
|
||||
{
|
||||
m_context.visit(
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
WebIDL::ExceptionOr<void> set_height(unsigned);
|
||||
|
||||
DeprecatedString to_data_url(DeprecatedString const& type, Optional<double> quality) const;
|
||||
WebIDL::ExceptionOr<void> to_blob(JS::NonnullGCPtr<WebIDL::CallbackType> callback, DeprecatedString const& type, Optional<double> quality);
|
||||
|
||||
void present();
|
||||
|
||||
|
|
|
@ -15,5 +15,7 @@ interface HTMLCanvasElement : HTMLElement {
|
|||
[CEReactions] attribute unsigned long height;
|
||||
|
||||
USVString toDataURL(optional DOMString type = "image/png", optional double quality);
|
||||
|
||||
undefined toBlob(BlobCallback _callback, optional DOMString type = "image/png", optional double quality);
|
||||
};
|
||||
|
||||
callback BlobCallback = undefined (Blob? blob);
|
||||
|
|
Loading…
Reference in a new issue