diff --git a/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp b/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp index d2d2a42a8ab..1bd8f71fd1b 100644 --- a/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp +++ b/Libraries/LibWeb/HTML/Canvas/CanvasDrawImage.cpp @@ -45,6 +45,11 @@ static void default_source_size(CanvasImageSource const& image, float& source_wi [&source_width, &source_height](GC::Root const& source) { auto const bitmap = source->bitmap(); + if (!bitmap) { + source_width = 0; + source_height = 0; + return; + } source_width = bitmap->width(); source_height = bitmap->height(); }, diff --git a/Libraries/LibWeb/HTML/OffscreenCanvas.cpp b/Libraries/LibWeb/HTML/OffscreenCanvas.cpp index 74b7eb63773..4257ec23051 100644 --- a/Libraries/LibWeb/HTML/OffscreenCanvas.cpp +++ b/Libraries/LibWeb/HTML/OffscreenCanvas.cpp @@ -31,16 +31,17 @@ WebIDL::ExceptionOr> OffscreenCanvas::construct_impl( WebIDL::UnsignedLong width, WebIDL::UnsignedLong height) { + RefPtr bitmap; + if (width > 0 && height > 0) { + // The new OffscreenCanvas(width, height) constructor steps are: + auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize { width, height }); - // The new OffscreenCanvas(width, height) constructor steps are: - auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize { width, height }); - - if (bitmap_or_error.is_error()) { - return WebIDL::InvalidStateError::create(realm, MUST(String::formatted("Error in allocating bitmap: {}", bitmap_or_error.error()))); + if (bitmap_or_error.is_error()) { + return WebIDL::InvalidStateError::create(realm, MUST(String::formatted("Error in allocating bitmap: {}", bitmap_or_error.error()))); + } + bitmap = bitmap_or_error.release_value(); } - auto bitmap = bitmap_or_error.release_value(); - // 1. Initialize the bitmap of this to a rectangular array of transparent black pixels of the dimensions specified by width and height. // noop, the pixel value to set is equal to 0x00000000, which the bitmap already contains @@ -71,7 +72,7 @@ WebIDL::ExceptionOr> OffscreenCanvas::construct_impl( } // https://html.spec.whatwg.org/multipage/canvas.html#dom-offscreencanvas -OffscreenCanvas::OffscreenCanvas(JS::Realm& realm, NonnullRefPtr bitmap) +OffscreenCanvas::OffscreenCanvas(JS::Realm& realm, RefPtr bitmap) : EventTarget(realm) , m_bitmap { move(bitmap) } { @@ -102,11 +103,17 @@ HTML::TransferType OffscreenCanvas::primary_interface() const WebIDL::UnsignedLong OffscreenCanvas::width() const { + if (!m_bitmap) + return 0; + return m_bitmap->size().width(); } WebIDL::UnsignedLong OffscreenCanvas::height() const { + if (!m_bitmap) + return 0; + return m_bitmap->size().height(); } @@ -129,7 +136,11 @@ void OffscreenCanvas::reset_context_to_default_state() void OffscreenCanvas::set_new_bitmap_size(Gfx::IntSize new_size) { - m_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize { new_size.width(), new_size.height() })); + if (new_size.width() == 0 || new_size.height() == 0) + m_bitmap = nullptr; + else { + m_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize { new_size.width(), new_size.height() })); + } m_context.visit( [&](GC::Ref& context) { @@ -145,7 +156,7 @@ void OffscreenCanvas::set_new_bitmap_size(Gfx::IntSize new_size) // Do nothing. }); } -NonnullRefPtr OffscreenCanvas::bitmap() const +RefPtr OffscreenCanvas::bitmap() const { return m_bitmap; } @@ -171,6 +182,8 @@ WebIDL::ExceptionOr OffscreenCanvas::set_height(WebIDL::UnsignedLong value Gfx::IntSize OffscreenCanvas::bitmap_size_for_canvas() const { + if (!m_bitmap) + return { 0, 0 }; return m_bitmap->size(); } @@ -224,10 +237,14 @@ WebIDL::ExceptionOr> OffscreenCanvas::transfer_to_image_bit auto image = ImageBitmap::create(realm()); image->set_bitmap(m_bitmap); - // 4. Set this OffscreenCanvas object 's bitmap to reference a newly created bitmap of the same dimensions and color space as the previous bitmap, and with its pixels initialized to transparent black, or opaque black if the rendering context' s alpha is false. + // 4. Set this OffscreenCanvas object's bitmap to reference a newly created bitmap of the same dimensions and color space as the previous bitmap, and with its pixels initialized to transparent black, or opaque black if the rendering context' s alpha is false. // FIXME: implement the checking of the alpha from the context auto size = bitmap_size_for_canvas(); - m_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, size)); + if (size.is_empty()) { + m_bitmap = nullptr; + } else { + m_bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, size)); + } // 5. Return image. return image; @@ -262,7 +279,9 @@ GC::Ref OffscreenCanvas::convert_to_blob(Optionalclone()); + RefPtr bitmap; + if (m_bitmap) + bitmap = MUST(m_bitmap->clone()); // 5. Let result be a new promise object. auto result_promise = WebIDL::create_promise(realm()); diff --git a/Libraries/LibWeb/HTML/OffscreenCanvas.h b/Libraries/LibWeb/HTML/OffscreenCanvas.h index c9625310145..050877faae0 100644 --- a/Libraries/LibWeb/HTML/OffscreenCanvas.h +++ b/Libraries/LibWeb/HTML/OffscreenCanvas.h @@ -32,8 +32,7 @@ class OffscreenCanvas : public DOM::EventTarget GC_DECLARE_ALLOCATOR(OffscreenCanvas); public: - static GC::Ref create(JS::Realm&, WebIDL::UnsignedLong width, - WebIDL::UnsignedLong height); + static GC::Ref create(JS::Realm&, WebIDL::UnsignedLong width, WebIDL::UnsignedLong height); static WebIDL::ExceptionOr> construct_impl( JS::Realm&, @@ -50,7 +49,7 @@ public: WebIDL::UnsignedLong width() const; WebIDL::UnsignedLong height() const; - NonnullRefPtr bitmap() const; + RefPtr bitmap() const; WebIDL::ExceptionOr set_width(WebIDL::UnsignedLong); WebIDL::ExceptionOr set_height(WebIDL::UnsignedLong); @@ -69,7 +68,7 @@ public: GC::Ptr oncontextrestored(); private: - OffscreenCanvas(JS::Realm&, NonnullRefPtr bitmap); + OffscreenCanvas(JS::Realm&, RefPtr bitmap); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; @@ -85,7 +84,7 @@ private: Variant, GC::Ref, GC::Ref, Empty> m_context; - NonnullRefPtr m_bitmap; + RefPtr m_bitmap; }; } diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.idl.set.zero.txt b/Tests/LibWeb/Text/expected/wpt-import/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.idl.set.zero.txt new file mode 100644 index 00000000000..53dabbeb821 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.idl.set.zero.txt @@ -0,0 +1,6 @@ +Harness status: OK + +Found 1 tests + +1 Pass +Pass Setting width/height IDL attributes to 0 \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.idl.set.zero.html b/Tests/LibWeb/Text/input/wpt-import/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.idl.set.zero.html new file mode 100644 index 00000000000..981ac04ce33 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.idl.set.zero.html @@ -0,0 +1,31 @@ + + + +OffscreenCanvas test: 2d.canvas.host.size.attributes.idl.set.zero + + + + +

2d.canvas.host.size.attributes.idl.set.zero

+

Setting width/height IDL attributes to 0

+ + +