diff --git a/Libraries/LibWeb/HTML/ImageData.cpp b/Libraries/LibWeb/HTML/ImageData.cpp
index 346275b4259..94133a96c05 100644
--- a/Libraries/LibWeb/HTML/ImageData.cpp
+++ b/Libraries/LibWeb/HTML/ImageData.cpp
@@ -19,28 +19,15 @@ namespace Web::HTML {
GC_DEFINE_ALLOCATOR(ImageData);
// https://html.spec.whatwg.org/multipage/canvas.html#dom-imagedata
-WebIDL::ExceptionOr> ImageData::create(JS::Realm& realm, u32 sw, u32 sh, Optional const&)
+WebIDL::ExceptionOr> ImageData::create(JS::Realm& realm, u32 sw, u32 sh, Optional const& settings)
{
- auto& vm = realm.vm();
-
// 1. If one or both of sw and sh are zero, then throw an "IndexSizeError" DOMException.
if (sw == 0 || sh == 0)
return WebIDL::IndexSizeError::create(realm, "The source width and height must be greater than zero."_string);
// 2. Initialize this given sw, sh, and settings set to settings.
// 3. Initialize the image data of this to transparent black.
- //
- // If the Canvas Pixel ArrayBuffer cannot be allocated, then rethrow the RangeError thrown by JavaScript, and return.
- Checked size = sw;
- size *= sh;
- size *= sizeof(u32);
- if (size.has_overflow())
- return WebIDL::IndexSizeError::create(realm, "The specified image size could not created"_string);
-
- auto data = TRY(JS::Uint8ClampedArray::create(realm, size.value()));
- auto bitmap = TRY_OR_THROW_OOM(vm, Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::RGBA8888, Gfx::AlphaType::Unpremultiplied, Gfx::IntSize(sw, sh), sw * sizeof(u32), data->data().data()));
-
- return realm.create(realm, bitmap, data);
+ return initialize(realm, sh, sw, settings);
}
WebIDL::ExceptionOr> ImageData::construct_impl(JS::Realm& realm, u32 sw, u32 sh, Optional const& settings)
@@ -49,7 +36,7 @@ WebIDL::ExceptionOr> ImageData::construct_impl(JS::Realm& rea
}
// https://html.spec.whatwg.org/multipage/canvas.html#dom-imagedata-with-data
-WebIDL::ExceptionOr> ImageData::create(JS::Realm& realm, GC::Root const& data, u32 sw, Optional sh, Optional const&)
+WebIDL::ExceptionOr> ImageData::create(JS::Realm& realm, GC::Root const& data, u32 sw, Optional sh, Optional const& settings)
{
auto& vm = realm.vm();
@@ -82,9 +69,8 @@ WebIDL::ExceptionOr> ImageData::create(JS::Realm& realm, GC::
return WebIDL::IndexSizeError::create(realm, "Source height must be equal to the calculated height of the data."_string);
// 7. Initialize this given sw, sh, settings set to settings, and source set to data.
- auto bitmap = TRY_OR_THROW_OOM(vm, Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::RGBA8888, Gfx::AlphaType::Unpremultiplied, Gfx::IntSize(sw, height), sw * sizeof(u32), uint8_clamped_array_data.data().data()));
-
- return realm.create(realm, bitmap, uint8_clamped_array_data);
+ // FIXME: This seems to be a spec issue, sh is an optional but height always have a value.
+ return initialize(realm, height, sw, settings, uint8_clamped_array_data);
}
WebIDL::ExceptionOr> ImageData::construct_impl(JS::Realm& realm, GC::Root const& data, u32 sw, Optional sh, Optional const& settings)
@@ -92,9 +78,53 @@ WebIDL::ExceptionOr> ImageData::construct_impl(JS::Realm& rea
return ImageData::create(realm, data, sw, move(sh), settings);
}
-ImageData::ImageData(JS::Realm& realm, NonnullRefPtr bitmap, GC::Ref data)
+// https://html.spec.whatwg.org/multipage/canvas.html#initialize-an-imagedata-object
+WebIDL::ExceptionOr> ImageData::initialize(JS::Realm& realm, u32 rows, u32 pixels_per_row, Optional const& settings, GC::Ptr source, Optional default_color_space)
+{
+ auto data = TRY([&]() -> WebIDL::ExceptionOr> {
+ // 1. If source was given, then initialize the data attribute of imageData to source.
+ if (source) {
+ return GC::Ref { *source };
+ }
+
+ Checked size = rows;
+ size *= pixels_per_row;
+ size *= sizeof(u32);
+ if (size.has_overflow())
+ return WebIDL::IndexSizeError::create(realm, "The specified image size could not created"_string);
+
+ // 2. Otherwise (source was not given), initialize the data attribute of imageData to a new Uint8ClampedArray object.
+ // The Uint8ClampedArray object must use a new Canvas Pixel ArrayBuffer for its storage, and must have a zero start
+ // offset and a length equal to the length of its storage, in bytes. The Canvas Pixel ArrayBuffer must have the
+ // correct size to store rows × pixelsPerRow pixels.
+ // 3. If the Canvas Pixel ArrayBuffer cannot be allocated, then rethrow the RangeError thrown by JavaScript, and return.
+ return TRY(JS::Uint8ClampedArray::create(realm, sizeof(u32) * rows * pixels_per_row));
+ }());
+
+ // AD-HOC: Create the bitmap backed by the Uint8ClampedArray.
+ auto bitmap = TRY_OR_THROW_OOM(realm.vm(), Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::RGBA8888, Gfx::AlphaType::Unpremultiplied, Gfx::IntSize(pixels_per_row, rows), pixels_per_row * sizeof(u32), data->data().data()));
+
+ // 4. Initialize the width attribute of imageData to pixelsPerRow.
+ // 5. Initialize the height attribute of imageData to rows.
+
+ // 6. If settings was given and settings["colorSpace"] exists, then initialize the colorSpace attribute of imageData to settings["colorSpace"].
+ Bindings::PredefinedColorSpace color_space {};
+ if (settings.has_value())
+ color_space = settings->color_space;
+ // 7. Otherwise, if defaultColorSpace was given, then initialize the colorSpace attribute of imageData to defaultColorSpace.
+ else if (default_color_space.has_value())
+ color_space = *default_color_space;
+ // 8. Otherwise, initialize the colorSpace attribute of imageData to "srgb".
+ else
+ color_space = Bindings::PredefinedColorSpace::Srgb;
+
+ return realm.create(realm, move(bitmap), data, color_space);
+}
+
+ImageData::ImageData(JS::Realm& realm, NonnullRefPtr bitmap, GC::Ref data, Bindings::PredefinedColorSpace color_space)
: PlatformObject(realm)
, m_bitmap(move(bitmap))
+ , m_color_space(color_space)
, m_data(move(data))
{
}
diff --git a/Libraries/LibWeb/HTML/ImageData.h b/Libraries/LibWeb/HTML/ImageData.h
index 652060f8939..079f0b8d875 100644
--- a/Libraries/LibWeb/HTML/ImageData.h
+++ b/Libraries/LibWeb/HTML/ImageData.h
@@ -39,13 +39,18 @@ public:
JS::Uint8ClampedArray* data();
const JS::Uint8ClampedArray* data() const;
+ Bindings::PredefinedColorSpace color_space() const { return m_color_space; }
+
private:
- ImageData(JS::Realm&, NonnullRefPtr, GC::Ref);
+ [[nodiscard]] static WebIDL::ExceptionOr> initialize(JS::Realm&, u32 rows, u32 pixels_per_row, Optional const&, GC::Ptr = {}, Optional = {});
+
+ ImageData(JS::Realm&, NonnullRefPtr, GC::Ref, Bindings::PredefinedColorSpace);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
NonnullRefPtr m_bitmap;
+ Bindings::PredefinedColorSpace m_color_space;
GC::Ref m_data;
};
diff --git a/Libraries/LibWeb/HTML/ImageData.idl b/Libraries/LibWeb/HTML/ImageData.idl
index d0647facc6e..34b67542700 100644
--- a/Libraries/LibWeb/HTML/ImageData.idl
+++ b/Libraries/LibWeb/HTML/ImageData.idl
@@ -13,5 +13,5 @@ interface ImageData {
readonly attribute unsigned long width;
readonly attribute unsigned long height;
readonly attribute Uint8ClampedArray data;
- [FIXME] readonly attribute PredefinedColorSpace colorSpace;
+ readonly attribute PredefinedColorSpace colorSpace;
};