diff --git a/Libraries/LibWeb/HTML/ImageBitmap.cpp b/Libraries/LibWeb/HTML/ImageBitmap.cpp index cc69acb7c3a..ed02e9ee54e 100644 --- a/Libraries/LibWeb/HTML/ImageBitmap.cpp +++ b/Libraries/LibWeb/HTML/ImageBitmap.cpp @@ -7,11 +7,40 @@ #include #include #include +#include +#include +#include namespace Web::HTML { GC_DEFINE_ALLOCATOR(ImageBitmap); +[[nodiscard]] static auto create_bitmap_from_bitmap_data(Gfx::BitmapFormat const format, Gfx::AlphaType const alpha_type, u32 const width, u32 const height, u32 const pitch, ByteBuffer data) +{ + return Gfx::Bitmap::create_wrapper(format, alpha_type, Gfx::IntSize(width, height), pitch, data.data()); +} + +static void serialize_bitmap(HTML::TransferDataEncoder& encoder, Gfx::Bitmap& bitmap) +{ + encoder.encode(bitmap.width()); + encoder.encode(bitmap.height()); + encoder.encode(bitmap.pitch()); + encoder.encode(bitmap.format()); + encoder.encode(bitmap.alpha_type()); + encoder.encode(ReadonlyBytes { bitmap.scanline_u8(0), bitmap.data_size() }); +} + +[[nodiscard]] static WebIDL::ExceptionOr> deserialize_bitmap(JS::Realm& realm, HTML::TransferDataDecoder& decoder) +{ + auto const width = decoder.decode(); + auto const height = decoder.decode(); + auto const pitch = decoder.decode(); + auto const format = decoder.decode(); + auto const alpha_type = decoder.decode(); + auto const data = TRY(decoder.decode_buffer(realm)); + return TRY_OR_THROW_OOM(realm.vm(), create_bitmap_from_bitmap_data(format, alpha_type, width, height, pitch, data)); +} + GC::Ref ImageBitmap::create(JS::Realm& realm) { return realm.create(realm); @@ -33,17 +62,23 @@ void ImageBitmap::visit_edges(Cell::Visitor& visitor) Base::visit_edges(visitor); } -WebIDL::ExceptionOr ImageBitmap::serialization_steps(HTML::TransferDataEncoder&, bool, HTML::SerializationMemory&) +// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#the-imagebitmap-interface:serialization-steps +WebIDL::ExceptionOr ImageBitmap::serialization_steps(HTML::TransferDataEncoder& serialized, bool, HTML::SerializationMemory&) { - // FIXME: Implement this - dbgln("(STUBBED) ImageBitmap::serialization_steps(HTML::TransferDataEncoder&, bool, HTML::SerializationMemory&)"); + // FIXME: 1. If value's origin-clean flag is not set, then throw a "DataCloneError" DOMException. + + // 2. Set serialized.[[BitmapData]] to a copy of value's bitmap data. + serialize_bitmap(serialized, *m_bitmap); + return {}; } -WebIDL::ExceptionOr ImageBitmap::deserialization_steps(HTML::TransferDataDecoder&, HTML::DeserializationMemory&) +// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#the-imagebitmap-interface:deserialization-steps +WebIDL::ExceptionOr ImageBitmap::deserialization_steps(HTML::TransferDataDecoder& serialized, HTML::DeserializationMemory&) { - // FIXME: Implement this - dbgln("(STUBBED) ImageBitmap::deserialization_steps(ReadonlySpan const&, size_t&, HTML::DeserializationMemory&)"); + // 1. Set value's bitmap data to serialized.[[BitmapData]]. + m_bitmap = TRY(deserialize_bitmap(this->realm(), serialized)); + return {}; } diff --git a/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp b/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp index 3e9d6293a1e..6ba1718f3ac 100644 --- a/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp +++ b/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp @@ -254,11 +254,19 @@ GC::Ref WindowOrWorkerGlobalScopeMixin::create_image_bitmap_imp WebIDL::reject_promise(realm, *p, error); }, // -> canvas - [&](GC::Root const&) { - dbgln("(STUBBED) createImageBitmap() for HTMLCanvasElement"); - auto const error = JS::Error::create(realm, "Not Implemented: createImageBitmap() for HTMLCanvasElement"sv); - TemporaryExecutionContext const context { relevant_realm(p->promise()), TemporaryExecutionContext::CallbacksEnabled::Yes }; - WebIDL::reject_promise(realm, *p, error); + [&](GC::Root const& canvas_element) { + // 1. Set imageBitmap's bitmap data to a copy of image's bitmap data, cropped to the source rectangle with formatting. + // FIXME: Actually crop the image to the source rectangle with formatting: https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#cropped-to-the-source-rectangle-with-formatting + image_bitmap->set_bitmap(canvas_element->get_bitmap_from_surface()); + + // FIXME: 2. Set the origin-clean flag of the imageBitmap's bitmap to the same value as the origin-clean flag of image's bitmap. + + // 3. Queue a global task, using the bitmap task source, to resolve promise with imageBitmap. + queue_global_task(Task::Source::BitmapTask, image_bitmap, GC::create_function(realm.heap(), [p, image_bitmap] { + auto& realm = relevant_realm(image_bitmap); + TemporaryExecutionContext const context { realm, TemporaryExecutionContext::CallbacksEnabled::Yes }; + WebIDL::resolve_promise(realm, *p, image_bitmap); + })); }, // -> ImageBitmap [&](GC::Root const&) { diff --git a/Tests/LibWeb/Text/expected/HTML/image-bitmap-from-invalid-types-no-crash.txt b/Tests/LibWeb/Text/expected/HTML/image-bitmap-from-invalid-types-no-crash.txt index d57ad0fe383..25c2f10346f 100644 --- a/Tests/LibWeb/Text/expected/HTML/image-bitmap-from-invalid-types-no-crash.txt +++ b/Tests/LibWeb/Text/expected/HTML/image-bitmap-from-invalid-types-no-crash.txt @@ -2,7 +2,7 @@ Blob [Success]: [object ImageBitmap] ImageData [Success]: [object ImageBitmap] HTMLImageElement [ Error ]: InvalidStateError: image argument is not usable SVGImageElement [ Error ]: InvalidStateError: image argument is not usable -HTMLCanvasElement [ Error ]: Error: Not Implemented: createImageBitmap() for HTMLCanvasElement +HTMLCanvasElement [Success]: [object ImageBitmap] ImageBitmap [ Error ]: TypeError: No union types matched OffscreenCanvas [ Error ]: Error: Not Implemented: createImageBitmap() for OffscreenCanvas -HTMLVideoElement [ Error ]: InvalidStateError: image argument is not usable \ No newline at end of file +HTMLVideoElement [ Error ]: InvalidStateError: image argument is not usable diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.txt b/Tests/LibWeb/Text/expected/wpt-import/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.txt index b779d6328cb..08d302e02cc 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.txt @@ -2,8 +2,8 @@ Harness status: OK Found 150 tests -141 Pass -9 Fail +147 Pass +3 Fail Pass primitive undefined Pass primitive null Pass primitive true @@ -126,12 +126,12 @@ Pass Object with non-enumerable property Pass Object with non-writable property Pass Object with non-configurable property Pass Object with a getter that throws -Fail ImageBitmap 1x1 transparent black -Fail ImageBitmap 1x1 non-transparent non-black -Fail Array ImageBitmap object, ImageBitmap 1x1 transparent black -Fail Array ImageBitmap object, ImageBitmap 1x1 transparent non-black -Fail Object ImageBitmap object, ImageBitmap 1x1 transparent black -Fail Object ImageBitmap object, ImageBitmap 1x1 transparent non-black +Pass ImageBitmap 1x1 transparent black +Pass ImageBitmap 1x1 non-transparent non-black +Pass Array ImageBitmap object, ImageBitmap 1x1 transparent black +Pass Array ImageBitmap object, ImageBitmap 1x1 transparent non-black +Pass Object ImageBitmap object, ImageBitmap 1x1 transparent black +Pass Object ImageBitmap object, ImageBitmap 1x1 transparent non-black Pass ObjectPrototype must lose its exotic-ness when cloned Pass Serializing a non-serializable platform object fails Pass An object whose interface is deleted from the global must still deserialize diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/webappapis/structured-clone/structured-clone.any.txt b/Tests/LibWeb/Text/expected/wpt-import/html/webappapis/structured-clone/structured-clone.any.txt index b779d6328cb..08d302e02cc 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/html/webappapis/structured-clone/structured-clone.any.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/html/webappapis/structured-clone/structured-clone.any.txt @@ -2,8 +2,8 @@ Harness status: OK Found 150 tests -141 Pass -9 Fail +147 Pass +3 Fail Pass primitive undefined Pass primitive null Pass primitive true @@ -126,12 +126,12 @@ Pass Object with non-enumerable property Pass Object with non-writable property Pass Object with non-configurable property Pass Object with a getter that throws -Fail ImageBitmap 1x1 transparent black -Fail ImageBitmap 1x1 non-transparent non-black -Fail Array ImageBitmap object, ImageBitmap 1x1 transparent black -Fail Array ImageBitmap object, ImageBitmap 1x1 transparent non-black -Fail Object ImageBitmap object, ImageBitmap 1x1 transparent black -Fail Object ImageBitmap object, ImageBitmap 1x1 transparent non-black +Pass ImageBitmap 1x1 transparent black +Pass ImageBitmap 1x1 non-transparent non-black +Pass Array ImageBitmap object, ImageBitmap 1x1 transparent black +Pass Array ImageBitmap object, ImageBitmap 1x1 transparent non-black +Pass Object ImageBitmap object, ImageBitmap 1x1 transparent black +Pass Object ImageBitmap object, ImageBitmap 1x1 transparent non-black Pass ObjectPrototype must lose its exotic-ness when cloned Pass Serializing a non-serializable platform object fails Pass An object whose interface is deleted from the global must still deserialize