mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 12:05:15 +00:00
LibWeb/HTML: Implement ImageData initialization closer to spec
This commit is contained in:
parent
569ebeb6a4
commit
715bf0de2c
Notes:
github-actions[bot]
2025-03-05 11:36:24 +00:00
Author: https://github.com/LucasChollet Commit: https://github.com/LadybirdBrowser/ladybird/commit/715bf0de2c7 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3709 Reviewed-by: https://github.com/AtkinsSJ ✅
3 changed files with 57 additions and 22 deletions
|
@ -19,28 +19,15 @@ namespace Web::HTML {
|
|||
GC_DEFINE_ALLOCATOR(ImageData);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-imagedata
|
||||
WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::create(JS::Realm& realm, u32 sw, u32 sh, Optional<ImageDataSettings> const&)
|
||||
WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::create(JS::Realm& realm, u32 sw, u32 sh, Optional<ImageDataSettings> 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<u32> 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<ImageData>(realm, bitmap, data);
|
||||
return initialize(realm, sh, sw, settings);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::construct_impl(JS::Realm& realm, u32 sw, u32 sh, Optional<ImageDataSettings> const& settings)
|
||||
|
@ -49,7 +36,7 @@ WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::construct_impl(JS::Realm& rea
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-imagedata-with-data
|
||||
WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::create(JS::Realm& realm, GC::Root<WebIDL::BufferSource> const& data, u32 sw, Optional<u32> sh, Optional<ImageDataSettings> const&)
|
||||
WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::create(JS::Realm& realm, GC::Root<WebIDL::BufferSource> const& data, u32 sw, Optional<u32> sh, Optional<ImageDataSettings> const& settings)
|
||||
{
|
||||
auto& vm = realm.vm();
|
||||
|
||||
|
@ -82,9 +69,8 @@ WebIDL::ExceptionOr<GC::Ref<ImageData>> 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<ImageData>(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<GC::Ref<ImageData>> ImageData::construct_impl(JS::Realm& realm, GC::Root<WebIDL::BufferSource> const& data, u32 sw, Optional<u32> sh, Optional<ImageDataSettings> const& settings)
|
||||
|
@ -92,9 +78,53 @@ WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::construct_impl(JS::Realm& rea
|
|||
return ImageData::create(realm, data, sw, move(sh), settings);
|
||||
}
|
||||
|
||||
ImageData::ImageData(JS::Realm& realm, NonnullRefPtr<Gfx::Bitmap> bitmap, GC::Ref<JS::Uint8ClampedArray> data)
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#initialize-an-imagedata-object
|
||||
WebIDL::ExceptionOr<GC::Ref<ImageData>> ImageData::initialize(JS::Realm& realm, u32 rows, u32 pixels_per_row, Optional<ImageDataSettings> const& settings, GC::Ptr<JS::Uint8ClampedArray> source, Optional<Bindings::PredefinedColorSpace> default_color_space)
|
||||
{
|
||||
auto data = TRY([&]() -> WebIDL::ExceptionOr<GC::Ref<JS::Uint8ClampedArray>> {
|
||||
// 1. If source was given, then initialize the data attribute of imageData to source.
|
||||
if (source) {
|
||||
return GC::Ref<JS::Uint8ClampedArray> { *source };
|
||||
}
|
||||
|
||||
Checked<u32> 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<ImageData>(realm, move(bitmap), data, color_space);
|
||||
}
|
||||
|
||||
ImageData::ImageData(JS::Realm& realm, NonnullRefPtr<Gfx::Bitmap> bitmap, GC::Ref<JS::Uint8ClampedArray> data, Bindings::PredefinedColorSpace color_space)
|
||||
: PlatformObject(realm)
|
||||
, m_bitmap(move(bitmap))
|
||||
, m_color_space(color_space)
|
||||
, m_data(move(data))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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<Gfx::Bitmap>, GC::Ref<JS::Uint8ClampedArray>);
|
||||
[[nodiscard]] static WebIDL::ExceptionOr<GC::Ref<ImageData>> initialize(JS::Realm&, u32 rows, u32 pixels_per_row, Optional<ImageDataSettings> const&, GC::Ptr<JS::Uint8ClampedArray> = {}, Optional<Bindings::PredefinedColorSpace> = {});
|
||||
|
||||
ImageData(JS::Realm&, NonnullRefPtr<Gfx::Bitmap>, GC::Ref<JS::Uint8ClampedArray>, Bindings::PredefinedColorSpace);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
NonnullRefPtr<Gfx::Bitmap> m_bitmap;
|
||||
Bindings::PredefinedColorSpace m_color_space;
|
||||
GC::Ref<JS::Uint8ClampedArray> m_data;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue